private static void AppendAllLoadedSyntaxTrees( ArrayBuilder <SyntaxTree> treesBuilder, SyntaxTree tree, string scriptClassName, SourceReferenceResolver resolver, Language language, bool isSubmission, IDictionary <SyntaxTree, int> ordinalMapBuilder, IDictionary <SyntaxTree, ImmutableArray <DeclarationLoadDirective> > loadDirectiveMapBuilder, IDictionary <string, SyntaxTree> loadedSyntaxTreeMapBuilder, IDictionary <SyntaxTree, Lazy <RootSingleDeclaration> > declMapBuilder, ref DeclarationTable declTable) { ArrayBuilder <DeclarationLoadDirective> loadDirectives = null; foreach (var d in tree.GetCompilationUnitRoot().GetLoadDirectives()) { var directive = (LoadDirective)d.Directive; var node = (LanguageSyntaxNode)d; var path = directive.File; 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(diag => diag.Severity == DiagnosticSeverity.Error)); continue; } var diagnostics = DiagnosticBag.GetInstance(); string resolvedFilePath = null; if (resolver == null) { diagnostics.Add(InternalErrorCode.ERR_SourceFileReferencesNotSupported.ToDiagnosticInfo().ToDiagnostic(node.Location)); } else { resolvedFilePath = resolver.ResolveReference(path, baseFilePath: tree.FilePath); if (resolvedFilePath == null) { diagnostics.Add(InternalErrorCode.ERR_NoSourceFile.ToDiagnosticInfo(path).ToDiagnostic(node.Location)); } else if (!loadedSyntaxTreeMapBuilder.ContainsKey(resolvedFilePath)) { try { var code = resolver.ReadText(resolvedFilePath); var loadedTree = language.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, language, isSubmission, ordinalMapBuilder, loadDirectiveMapBuilder, loadedSyntaxTreeMapBuilder, declMapBuilder, ref declTable); } catch (Exception e) { diagnostics.Add(ModelErrorCode.ERR_FileReadError.ToDiagnosticInfo(resolvedFilePath, e).ToDiagnostic(node.Location)); } } 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 <DeclarationLoadDirective> .GetInstance(); } loadDirectives.Add(new DeclarationLoadDirective(resolvedFilePath, diagnostics.ToReadOnlyAndFree())); } if (loadDirectives != null) { loadDirectiveMapBuilder.Add(tree, loadDirectives.ToImmutableAndFree()); } }
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()); } }
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. Debug.Assert(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()); } }