/// <summary>
        /// Appends all trees (including any trees from #load'ed files).
        /// </summary>
        private static void AppendAllSyntaxTrees(
            ArrayBuilder <SyntaxTree> treesBuilder,
            SyntaxTree tree,
            string scriptClassName,
            SourceReferenceResolver resolver,
            CommonMessageProvider messageProvider,
            bool isSubmission,
            IDictionary <SyntaxTree, int> ordinalMapBuilder,
            IDictionary <SyntaxTree, ImmutableArray <LoadDirective> > loadDirectiveMapBuilder,
            IDictionary <string, SyntaxTree> loadedSyntaxTreeMapBuilder,
            IDictionary <SyntaxTree, Lazy <RootSingleNamespaceDeclaration> > declMapBuilder,
            ref DeclarationTable declTable)
        {
            var sourceCodeKind = tree.Options.Kind;

            if (sourceCodeKind == SourceCodeKind.Script)
            {
                AppendAllLoadedSyntaxTrees(treesBuilder, tree, scriptClassName, resolver, messageProvider, isSubmission, ordinalMapBuilder, loadDirectiveMapBuilder, loadedSyntaxTreeMapBuilder, declMapBuilder, ref declTable);
            }

            AddSyntaxTreeToDeclarationMapAndTable(tree, scriptClassName, isSubmission, declMapBuilder, ref declTable);

            treesBuilder.Add(tree);

            ordinalMapBuilder.Add(tree, ordinalMapBuilder.Count);
        }
예제 #2
0
            internal State(
                ImmutableArray <SyntaxTree> syntaxTrees,
                ImmutableDictionary <SyntaxTree, int> syntaxTreeOrdinalMap,
                ImmutableDictionary <SyntaxTree, ImmutableArray <LoadDirective> > loadDirectiveMap,
                ImmutableDictionary <string, SyntaxTree> loadedSyntaxTreeMap,
                ImmutableDictionary <
                    SyntaxTree,
                    Lazy <RootSingleNamespaceDeclaration>
                    > rootNamespaces,
                DeclarationTable declarationTable
                )
            {
                Debug.Assert(
                    syntaxTrees.All(tree => syntaxTrees[syntaxTreeOrdinalMap[tree]] == tree)
                    );
                Debug.Assert(
                    syntaxTrees.SetEquals(
                        rootNamespaces.Keys.AsImmutable(),
                        EqualityComparer <SyntaxTree> .Default
                        )
                    );

                this.SyntaxTrees         = syntaxTrees;
                this.OrdinalMap          = syntaxTreeOrdinalMap;
                this.LoadDirectiveMap    = loadDirectiveMap;
                this.LoadedSyntaxTreeMap = loadedSyntaxTreeMap;
                this.RootNamespaces      = rootNamespaces;
                this.DeclarationTable    = declarationTable;
            }
        private static void RemoveSyntaxTreeFromDeclarationMapAndTable(
            SyntaxTree tree,
            IDictionary <SyntaxTree, Lazy <RootSingleNamespaceDeclaration> > declMap,
            ref DeclarationTable declTable)
        {
            var lazyRoot = declMap[tree];

            declTable = declTable.RemoveRootDeclaration(lazyRoot);
            declMap.Remove(tree);
        }
        private static void AddSyntaxTreeToDeclarationMapAndTable(
            SyntaxTree tree,
            string scriptClassName,
            bool isSubmission,
            IDictionary <SyntaxTree, Lazy <RootSingleNamespaceDeclaration> > declMapBuilder,
            ref DeclarationTable declTable)
        {
            var lazyRoot = new Lazy <RootSingleNamespaceDeclaration>(() => DeclarationTreeBuilder.ForTree(tree, scriptClassName, isSubmission));

            declMapBuilder.Add(tree, lazyRoot); // Callers are responsible for checking for existing entries.
            declTable = declTable.AddRootDeclaration(lazyRoot);
        }
예제 #5
0
            public Cache(DeclarationTable table)
            {
                this.MergedRoot = new Lazy<MergedNamespaceDeclaration>(
                    () => MergedNamespaceDeclaration.Create(table._allOlderRootDeclarations.InInsertionOrder.AsImmutable<SingleNamespaceDeclaration>()));

                this.TypeNames = new Lazy<ISet<string>>(
                    () => GetTypeNames(this.MergedRoot.Value));

                this.NamespaceNames = new Lazy<ISet<string>>(
                    () => GetNamespaceNames(this.MergedRoot.Value));

                this.ReferenceDirectives = new Lazy<ImmutableArray<ReferenceDirective>>(
                    () => MergedRoot.Value.Declarations.OfType<RootSingleNamespaceDeclaration>().SelectMany(r => r.ReferenceDirectives).AsImmutable());
            }
예제 #6
0
            public Cache(DeclarationTable table)
            {
                this.MergedRoot = new Lazy <MergedNamespaceDeclaration>(
                    () => MergedNamespaceDeclaration.Create(table._allOlderRootDeclarations.InInsertionOrder.AsImmutable <SingleNamespaceDeclaration>()));

                this.TypeNames = new Lazy <ISet <string> >(
                    () => GetTypeNames(this.MergedRoot.Value));

                this.NamespaceNames = new Lazy <ISet <string> >(
                    () => GetNamespaceNames(this.MergedRoot.Value));

                this.ReferenceDirectives = new Lazy <ImmutableArray <ReferenceDirective> >(
                    () => MergedRoot.Value.Declarations.OfType <RootSingleNamespaceDeclaration>().SelectMany(r => r.ReferenceDirectives).AsImmutable());
            }
            internal State(
                ImmutableArray<SyntaxTree> syntaxTrees,
                ImmutableDictionary<SyntaxTree, int> syntaxTreeOrdinalMap,
                ImmutableDictionary<SyntaxTree, ImmutableArray<LoadDirective>> loadDirectiveMap,
                ImmutableDictionary<string, SyntaxTree> loadedSyntaxTreeMap,
                ImmutableDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> rootNamespaces,
                DeclarationTable declarationTable)
            {
                Debug.Assert(syntaxTrees.All(tree => syntaxTrees[syntaxTreeOrdinalMap[tree]] == tree));
                Debug.Assert(syntaxTrees.SetEquals(rootNamespaces.Keys.AsImmutable(), EqualityComparer<SyntaxTree>.Default));

                this.SyntaxTrees = syntaxTrees;
                this.OrdinalMap = syntaxTreeOrdinalMap;
                this.LoadDirectiveMap = loadDirectiveMap;
                this.LoadedSyntaxTreeMap = loadedSyntaxTreeMap;
                this.RootNamespaces = rootNamespaces;
                this.DeclarationTable = declarationTable;
            }
        private static void RemoveSyntaxTreeFromDeclarationMapAndTable(
            SyntaxTree tree,
            ref ImmutableDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMap,
            ref DeclarationTable declTable,
            ref bool referenceDirectivesChanged)
        {
            Lazy<RootSingleNamespaceDeclaration> lazyRoot;
            if (!declMap.TryGetValue(tree, out lazyRoot))
            {
                throw new ArgumentException(string.Format(CSharpResources.SyntaxTreeNotFoundTo, tree), "trees");
            }

            declTable = declTable.RemoveRootDeclaration(lazyRoot);
            declMap = declMap.Remove(tree);
            referenceDirectivesChanged = referenceDirectivesChanged || tree.HasReferenceDirectives();
        }
 private CSharpCompilation UpdateSyntaxTrees(
     ImmutableArray<SyntaxTree> syntaxTrees,
     ImmutableDictionary<SyntaxTree, int> syntaxTreeOrdinalMap,
     ImmutableDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> rootNamespaces,
     DeclarationTable declarationTable,
     bool referenceDirectivesChanged)
 {
     return new CSharpCompilation(
         this.AssemblyName,
         this.options,
         this.ExternalReferences,
         syntaxTrees,
         syntaxTreeOrdinalMap,
         rootNamespaces,
         declarationTable,
         this.previousSubmission,
         this.SubmissionReturnType,
         this.HostObjectType,
         this.IsSubmission,
         this.referenceManager,
         reuseReferenceManager: !referenceDirectivesChanged);
 }
 private static void AddSyntaxTreeToDeclarationMapAndTable(
     SyntaxTree tree,
     CSharpCompilationOptions options,
     bool isSubmission,
     ref ImmutableDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMap,
     ref DeclarationTable declTable,
     ref bool referenceDirectivesChanged)
 {
     var lazyRoot = new Lazy<RootSingleNamespaceDeclaration>(() => DeclarationTreeBuilder.ForTree(tree, options.ScriptClassName ?? "", isSubmission));
     declMap = declMap.SetItem(tree, lazyRoot);
     declTable = declTable.AddRootDeclaration(lazyRoot);
     referenceDirectivesChanged = referenceDirectivesChanged || tree.HasReferenceDirectives();
 }
 private static void RemoveSyntaxTreeFromDeclarationMapAndTable(
     SyntaxTree tree,
     IDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMap,
     ref DeclarationTable declTable)
 {
     var lazyRoot = declMap[tree];
     declTable = declTable.RemoveRootDeclaration(lazyRoot);
     declMap.Remove(tree);
 }
        private CSharpCompilation(
            string assemblyName,
            CSharpCompilationOptions options,
            ImmutableArray<MetadataReference> references,
            ImmutableArray<SyntaxTree> syntaxTrees,
            ImmutableDictionary<SyntaxTree, int> syntaxTreeOrdinalMap,
            ImmutableDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> rootNamespaces,
            DeclarationTable declarationTable,
            CSharpCompilation previousSubmission,
            Type submissionReturnType,
            Type hostObjectType,
            bool isSubmission,
            ReferenceManager referenceManager,
            bool reuseReferenceManager,
            AsyncQueue<CompilationEvent> eventQueue = null)
            : base(assemblyName, references, submissionReturnType, hostObjectType, isSubmission, syntaxTreeOrdinalMap, eventQueue)
        {
            using (Logger.LogBlock(FunctionId.CSharp_Compilation_Create, message: assemblyName))
            {
                this.wellKnownMemberSignatureComparer = new WellKnownMembersSignatureComparer(this);
                this.options = options;
                this.syntaxTrees = syntaxTrees;

                this.rootNamespaces = rootNamespaces;
                this.declarationTable = declarationTable;

                Debug.Assert(syntaxTrees.All(tree => syntaxTrees[syntaxTreeOrdinalMap[tree]] == tree));
                Debug.Assert(syntaxTrees.SetEquals(rootNamespaces.Keys.AsImmutable(), EqualityComparer<SyntaxTree>.Default));

                this.builtInOperators = new BuiltInOperators(this);
                this.scriptClass = new Lazy<ImplicitNamedTypeSymbol>(BindScriptClass);
                this.globalImports = new Lazy<Imports>(BindGlobalUsings);
                this.globalNamespaceAlias = new Lazy<AliasSymbol>(CreateGlobalNamespaceAlias);
                this.anonymousTypeManager = new AnonymousTypeManager(this);

                if (isSubmission)
                {
                    Debug.Assert(previousSubmission == null || previousSubmission.HostObjectType == hostObjectType);

                    this.previousSubmission = previousSubmission;
                }
                else
                {
                    Debug.Assert(previousSubmission == null && submissionReturnType == null && hostObjectType == null);
                }

                if (reuseReferenceManager)
                {
                    referenceManager.AssertCanReuseForCompilation(this);
                    this.referenceManager = referenceManager;
                }
                else
                {
                    this.referenceManager = new ReferenceManager(
                        MakeSourceAssemblySimpleName(),
                        options.AssemblyIdentityComparer,
                        (referenceManager != null) ? referenceManager.ObservedMetadata : null);
                }

                Debug.Assert((object)this.lazyAssemblySymbol == null);
                if (EventQueue != null) EventQueue.Enqueue(new CompilationStartedEvent(this));
            }
        }
 private static void AddSyntaxTreeToDeclarationMapAndTable(
     SyntaxTree tree,
     string scriptClassName,
     bool isSubmission,
     IDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMapBuilder,
     ref DeclarationTable declTable)
 {
     var lazyRoot = new Lazy<RootSingleNamespaceDeclaration>(() => DeclarationTreeBuilder.ForTree(tree, scriptClassName, isSubmission));
     declMapBuilder.Add(tree, lazyRoot); // Callers are responsible for checking for existing entries.
     declTable = declTable.AddRootDeclaration(lazyRoot);
 }
        private static void AppendAllLoadedSyntaxTrees(
            ArrayBuilder<SyntaxTree> treesBuilder,
            SyntaxTree tree,
            string scriptClassName,
            SourceReferenceResolver resolver,
            CommonMessageProvider messageProvider,
            bool isSubmission,
            IDictionary<SyntaxTree, int> ordinalMapBuilder,
            IDictionary<SyntaxTree, ImmutableArray<LoadDirective>> loadDirectiveMapBuilder,
            IDictionary<string, SyntaxTree> loadedSyntaxTreeMapBuilder,
            IDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMapBuilder,
            ref DeclarationTable declTable)
        {
            ArrayBuilder<LoadDirective> loadDirectives = null;

            foreach (var directive in tree.GetCompilationUnitRoot().GetLoadDirectives())
            {
                var fileToken = directive.File;
                var path = (string)fileToken.Value;
                if (path == null)
                {
                    // If there is no path, the parser should have some Diagnostics to report (if we're in an active region).
                    Debug.Assert(!directive.IsActive || tree.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error));
                    continue;
                }

                var diagnostics = DiagnosticBag.GetInstance();
                string resolvedFilePath = null;
                if (resolver == null)
                {
                    diagnostics.Add(
                        messageProvider.CreateDiagnostic(
                            (int)ErrorCode.ERR_SourceFileReferencesNotSupported,
                            directive.Location));
                }
                else
                {
                    resolvedFilePath = resolver.ResolveReference(path, baseFilePath: tree.FilePath);
                    if (resolvedFilePath == null)
                    {
                        diagnostics.Add(
                            messageProvider.CreateDiagnostic(
                                (int)ErrorCode.ERR_NoSourceFile,
                                fileToken.GetLocation(),
                                path,
                                CSharpResources.CouldNotFindFile));
                    }
                    else if (!loadedSyntaxTreeMapBuilder.ContainsKey(resolvedFilePath))
                    {
                        try
                        {
                            var code = resolver.ReadText(resolvedFilePath);
                            var loadedTree = SyntaxFactory.ParseSyntaxTree(
                                code,
                                tree.Options, // Use ParseOptions propagated from "external" tree.
                                resolvedFilePath);

                            // All #load'ed trees should have unique path information.
                            loadedSyntaxTreeMapBuilder.Add(loadedTree.FilePath, loadedTree);

                            AppendAllSyntaxTrees(
                                treesBuilder,
                                loadedTree,
                                scriptClassName,
                                resolver,
                                messageProvider,
                                isSubmission,
                                ordinalMapBuilder,
                                loadDirectiveMapBuilder,
                                loadedSyntaxTreeMapBuilder,
                                declMapBuilder,
                                ref declTable);
                        }
                        catch (Exception e)
                        {
                            diagnostics.Add(
                                CommonCompiler.ToFileReadDiagnostics(messageProvider, e, resolvedFilePath),
                                fileToken.GetLocation());
                        }
                    }
                    else
                    {
                        // The path resolved, but we've seen this file before,
                        // so don't attempt to load it again.
                        Debug.Assert(diagnostics.IsEmptyWithoutResolution);
                    }
                }

                if (loadDirectives == null)
                {
                    loadDirectives = ArrayBuilder<LoadDirective>.GetInstance();
                }
                loadDirectives.Add(new LoadDirective(resolvedFilePath, diagnostics.ToReadOnlyAndFree()));
            }

            if (loadDirectives != null)
            {
                loadDirectiveMapBuilder.Add(tree, loadDirectives.ToImmutableAndFree());
            }
        }
        /// <summary>
        /// Appends all trees (including any trees from #load'ed files).
        /// </summary>
        private static void AppendAllSyntaxTrees(
            ArrayBuilder<SyntaxTree> treesBuilder,
            SyntaxTree tree,
            string scriptClassName,
            SourceReferenceResolver resolver,
            CommonMessageProvider messageProvider,
            bool isSubmission,
            IDictionary<SyntaxTree, int> ordinalMapBuilder,
            IDictionary<SyntaxTree, ImmutableArray<LoadDirective>> loadDirectiveMapBuilder,
            IDictionary<string, SyntaxTree> loadedSyntaxTreeMapBuilder,
            IDictionary<SyntaxTree, Lazy<RootSingleNamespaceDeclaration>> declMapBuilder,
            ref DeclarationTable declTable)
        {
            var sourceCodeKind = tree.Options.Kind;
            if (sourceCodeKind == SourceCodeKind.Script)
            {
                AppendAllLoadedSyntaxTrees(treesBuilder, tree, scriptClassName, resolver, messageProvider, isSubmission, ordinalMapBuilder, loadDirectiveMapBuilder, loadedSyntaxTreeMapBuilder, declMapBuilder, ref declTable);
            }

            AddSyntaxTreeToDeclarationMapAndTable(tree, scriptClassName, isSubmission, declMapBuilder, ref declTable);

            treesBuilder.Add(tree);

            ordinalMapBuilder.Add(tree, ordinalMapBuilder.Count);
        }
예제 #16
0
 public Cache(DeclarationTable table)
 {
     _table = table;
 }
        private static void AppendAllLoadedSyntaxTrees(
            ArrayBuilder <SyntaxTree> treesBuilder,
            SyntaxTree tree,
            string scriptClassName,
            SourceReferenceResolver resolver,
            CommonMessageProvider messageProvider,
            bool isSubmission,
            IDictionary <SyntaxTree, int> ordinalMapBuilder,
            IDictionary <SyntaxTree, ImmutableArray <LoadDirective> > loadDirectiveMapBuilder,
            IDictionary <string, SyntaxTree> loadedSyntaxTreeMapBuilder,
            IDictionary <SyntaxTree, Lazy <RootSingleNamespaceDeclaration> > declMapBuilder,
            ref DeclarationTable declTable)
        {
            ArrayBuilder <LoadDirective> loadDirectives = null;

            foreach (var directive in tree.GetCompilationUnitRoot().GetLoadDirectives())
            {
                var fileToken = directive.File;
                var path      = (string)fileToken.Value;
                if (path == null)
                {
                    // If there is no path, the parser should have some Diagnostics to report (if we're in an active region).
                    Debug.Assert(!directive.IsActive || tree.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error));
                    continue;
                }

                var    diagnostics      = DiagnosticBag.GetInstance();
                string resolvedFilePath = null;
                if (resolver == null)
                {
                    diagnostics.Add(
                        messageProvider.CreateDiagnostic(
                            (int)ErrorCode.ERR_SourceFileReferencesNotSupported,
                            directive.Location));
                }
                else
                {
                    resolvedFilePath = resolver.ResolveReference(path, baseFilePath: tree.FilePath);
                    if (resolvedFilePath == null)
                    {
                        diagnostics.Add(
                            messageProvider.CreateDiagnostic(
                                (int)ErrorCode.ERR_NoSourceFile,
                                fileToken.GetLocation(),
                                path,
                                CSharpResources.CouldNotFindFile));
                    }
                    else if (!loadedSyntaxTreeMapBuilder.ContainsKey(resolvedFilePath))
                    {
                        try
                        {
                            var code       = resolver.ReadText(resolvedFilePath);
                            var loadedTree = SyntaxFactory.ParseSyntaxTree(
                                code,
                                tree.Options, // Use ParseOptions propagated from "external" tree.
                                resolvedFilePath);

                            // All #load'ed trees should have unique path information.
                            loadedSyntaxTreeMapBuilder.Add(loadedTree.FilePath, loadedTree);

                            AppendAllSyntaxTrees(
                                treesBuilder,
                                loadedTree,
                                scriptClassName,
                                resolver,
                                messageProvider,
                                isSubmission,
                                ordinalMapBuilder,
                                loadDirectiveMapBuilder,
                                loadedSyntaxTreeMapBuilder,
                                declMapBuilder,
                                ref declTable);
                        }
                        catch (Exception e)
                        {
                            diagnostics.Add(
                                CommonCompiler.ToFileReadDiagnostics(messageProvider, e, resolvedFilePath),
                                fileToken.GetLocation());
                        }
                    }
                    else
                    {
                        // The path resolved, but we've seen this file before,
                        // so don't attempt to load it again.
                        Debug.Assert(diagnostics.IsEmptyWithoutResolution);
                    }
                }

                if (loadDirectives == null)
                {
                    loadDirectives = ArrayBuilder <LoadDirective> .GetInstance();
                }
                loadDirectives.Add(new LoadDirective(resolvedFilePath, diagnostics.ToReadOnlyAndFree()));
            }

            if (loadDirectives != null)
            {
                loadDirectiveMapBuilder.Add(tree, loadDirectives.ToImmutableAndFree());
            }
        }