diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxTreeFactoryService.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxTreeFactoryService.cs index 374c6c6e00c6c1fc69570e4315e2934ac22287ba..454d5624b82f6e515e9d403b70714bd8b46dc04d 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxTreeFactoryService.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxTreeFactoryService.cs @@ -44,10 +44,10 @@ public override ParseOptions GetDefaultParseOptionsWithLatestLanguageVersion() return _parseOptionWithLatestLanguageVersion; } - public override SyntaxTree CreateSyntaxTree(string fileName, ParseOptions options, Encoding encoding, SyntaxNode root) + public override SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root, ImmutableDictionary treeDiagnosticReportingOptionsOpt) { options = options ?? GetDefaultParseOptions(); - return SyntaxFactory.SyntaxTree(root, options, fileName, encoding); + return CSharpSyntaxTree.Create((CSharpSyntaxNode)root, (CSharpParseOptions)options, filePath, encoding, treeDiagnosticReportingOptionsOpt); } public override SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, ImmutableDictionary treeDiagnosticReportingOptionsOpt, CancellationToken cancellationToken) @@ -65,7 +65,14 @@ public override bool CanCreateRecoverableTree(SyntaxNode root) return base.CanCreateRecoverableTree(root) && cu != null && cu.AttributeLists.Count == 0; } - public override SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource text, Encoding encoding, SyntaxNode root) + public override SyntaxTree CreateRecoverableTree( + ProjectId cacheKey, + string filePath, + ParseOptions options, + ValueSource text, + Encoding encoding, + SyntaxNode root, + ImmutableDictionary treeDiagnosticReportingOptionsOpt) { System.Diagnostics.Debug.Assert(CanCreateRecoverableTree(root)); return RecoverableSyntaxTree.CreateRecoverableTree( @@ -76,7 +83,7 @@ public override SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string file text, encoding, (CompilationUnitSyntax)root, - diagnosticOptions: null); + treeDiagnosticReportingOptionsOpt); } } } diff --git a/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/AbstractSyntaxTreeFactoryService.cs b/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/AbstractSyntaxTreeFactoryService.cs index d1c664f794fb1f1e65b0d6e8eb82dfca11274035..6c0642ab5475ed024f3bbe12777b2cd7bbcf9229 100644 --- a/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/AbstractSyntaxTreeFactoryService.cs +++ b/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/AbstractSyntaxTreeFactoryService.cs @@ -25,9 +25,9 @@ public AbstractSyntaxTreeFactoryService(HostLanguageServices languageServices) } public abstract ParseOptions GetDefaultParseOptions(); - public abstract SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root); + public abstract SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root, ImmutableDictionary treeDiagnosticReportingOptionsOpt); public abstract SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, ImmutableDictionary treeDiagnosticReportingOptionsOpt, CancellationToken cancellationToken); - public abstract SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource text, Encoding encoding, SyntaxNode root); + public abstract SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource text, Encoding encoding, SyntaxNode root, ImmutableDictionary treeDiagnosticReportingOptionsOpt); public abstract SyntaxNode DeserializeNodeFrom(Stream stream, CancellationToken cancellationToken); public abstract ParseOptions GetDefaultParseOptionsWithLatestLanguageVersion(); diff --git a/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/ISyntaxTreeFactoryService.cs b/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/ISyntaxTreeFactoryService.cs index 8cc0d43c987967047debb31b737820d67c6b0cf7..e359f93f978502cf94d18ad0696073e1e4b487a7 100644 --- a/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/ISyntaxTreeFactoryService.cs +++ b/src/Workspaces/Core/Portable/Workspace/Host/SyntaxTreeFactory/ISyntaxTreeFactoryService.cs @@ -19,7 +19,7 @@ internal interface ISyntaxTreeFactoryService : ILanguageService ParseOptions GetDefaultParseOptionsWithLatestLanguageVersion(); // new tree from root node - SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root); + SyntaxTree CreateSyntaxTree(string filePath, ParseOptions options, Encoding encoding, SyntaxNode root, ImmutableDictionary treeDiagnosticReportingOptionsOpt); // new tree from text SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, ImmutableDictionary treeDiagnosticReportingOptionsOpt, CancellationToken cancellationToken); @@ -27,7 +27,7 @@ internal interface ISyntaxTreeFactoryService : ILanguageService bool CanCreateRecoverableTree(SyntaxNode root); // new recoverable tree from root node - SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource text, Encoding encoding, SyntaxNode root); + SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource text, Encoding encoding, SyntaxNode root, ImmutableDictionary treeDiagnosticReportingOptionsOpt); SyntaxNode DeserializeNodeFrom(Stream stream, CancellationToken cancellationToken); } diff --git a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs index c1098f09c5d1dcb2859e0e3c4f1e85a4ade382ad..ea06268ca9d5d5931adf87db9791c701e5e30afa 100644 --- a/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs +++ b/src/Workspaces/Core/Portable/Workspace/Solution/DocumentState.cs @@ -180,7 +180,7 @@ private static string GetSyntaxTreeFilePath(DocumentInfo.DocumentAttributes info var root = tree.GetRoot(cancellationToken); if (mode == PreservationMode.PreserveValue && treeFactory.CanCreateRecoverableTree(root)) { - tree = treeFactory.CreateRecoverableTree(cacheKey, tree.FilePath, tree.Options, newTextSource, text.Encoding, root); + tree = treeFactory.CreateRecoverableTree(cacheKey, tree.FilePath, tree.Options, newTextSource, text.Encoding, root, tree.DiagnosticOptions); } Contract.ThrowIfNull(tree); @@ -538,10 +538,13 @@ internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode) // determine encoding Encoding encoding; + ImmutableDictionary treeDiagnosticReportingOptions = null; + if (this.TryGetSyntaxTree(out var priorTree)) { // this is most likely available since UpdateTree is normally called after modifying the existing tree. encoding = priorTree.Encoding; + treeDiagnosticReportingOptions = priorTree.DiagnosticOptions; } else if (this.TryGetText(out var priorText)) { @@ -555,7 +558,18 @@ internal DocumentState UpdateTree(SyntaxNode newRoot, PreservationMode mode) var syntaxTreeFactory = _languageServices.GetService(); - var result = CreateRecoverableTextAndTree(newRoot, newTextVersion, newTreeVersion, encoding, this.Attributes, _options, syntaxTreeFactory, mode); + var filePath = GetSyntaxTreeFilePath(this.Attributes); + + if (treeDiagnosticReportingOptions == null && filePath != null) + { + // Ideally we'd pass a cancellation token here but we don't have one to pass as the operation previously didn't take a cancellation token. + // In practice, I don't suspect it will matter: GetValue will only do work if we haven't already computed the AnalyzerConfigSet for this project, + // which would only happen if no tree was observed for any file in this project. Arbitrarily replacing trees without ever looking at the + // original one is possible but unlikely. + treeDiagnosticReportingOptions = _analyzerConfigSetSource.GetValue(CancellationToken.None).GetOptionsForSourcePath(filePath).TreeOptions; + } + + var result = CreateRecoverableTextAndTree(newRoot, filePath, newTextVersion, newTreeVersion, encoding, this.Attributes, _options, treeDiagnosticReportingOptions, syntaxTreeFactory, mode); return new DocumentState( this.LanguageServices, @@ -586,10 +600,17 @@ private VersionStamp GetNewTreeVersionForUpdatedTree(SyntaxNode newRoot, Version // use static method so we don't capture references to this private static Tuple, TreeAndVersion> CreateRecoverableTextAndTree( - SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding, - DocumentInfo.DocumentAttributes attributes, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode) + SyntaxNode newRoot, + string filePath, + VersionStamp textVersion, + VersionStamp treeVersion, + Encoding encoding, + DocumentInfo.DocumentAttributes attributes, + ParseOptions options, + ImmutableDictionary treeDiagnosticReportingOptionsOpt, + ISyntaxTreeFactoryService factory, + PreservationMode mode) { - string filePath = attributes.FilePath; SyntaxTree tree = null; ValueSource lazyTextAndVersion = null; @@ -604,7 +625,7 @@ private VersionStamp GetNewTreeVersionForUpdatedTree(SyntaxNode newRoot, Version textVersion, filePath); - tree = factory.CreateSyntaxTree(GetSyntaxTreeFilePath(attributes), options, encoding, newRoot); + tree = factory.CreateSyntaxTree(filePath, options, encoding, newRoot, treeDiagnosticReportingOptionsOpt); } else { @@ -619,7 +640,7 @@ private VersionStamp GetNewTreeVersionForUpdatedTree(SyntaxNode newRoot, Version textVersion, filePath); - tree = factory.CreateRecoverableTree(attributes.Id.ProjectId, GetSyntaxTreeFilePath(attributes), options, lazyTextAndVersion, encoding, newRoot); + tree = factory.CreateRecoverableTree(attributes.Id.ProjectId, filePath, options, lazyTextAndVersion, encoding, newRoot, treeDiagnosticReportingOptionsOpt); } return Tuple.Create(lazyTextAndVersion, TreeAndVersion.Create(tree, treeVersion)); diff --git a/src/Workspaces/CoreTest/Microsoft.CodeAnalysis.Workspaces.UnitTests.csproj b/src/Workspaces/CoreTest/Microsoft.CodeAnalysis.Workspaces.UnitTests.csproj index 7e2caad0cd259b43c4ab82c27f21c2cba959a8e0..2da229d54a6a4e548cc973425d9d3404b0db8c45 100644 --- a/src/Workspaces/CoreTest/Microsoft.CodeAnalysis.Workspaces.UnitTests.csproj +++ b/src/Workspaces/CoreTest/Microsoft.CodeAnalysis.Workspaces.UnitTests.csproj @@ -27,6 +27,7 @@ + diff --git a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs index 0c25ad2490344de8fbe2633b8d49b6f914685f78..3b14fca92262cdaa5d1f106301cd31644273a0cc 100644 --- a/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs +++ b/src/Workspaces/CoreTest/SolutionTests/SolutionTests.cs @@ -1516,7 +1516,8 @@ public void TestWithSyntaxTree() strongTree.Options, new ConstantValueSource(TextAndVersion.Create(strongTree.GetText(), VersionStamp.Create(), strongTree.FilePath)), strongTree.GetText().Encoding, - strongTree.GetRoot()); + strongTree.GetRoot(), + strongTree.DiagnosticOptions); // create new tree before it ever getting root node var newTree = recoverableTree.WithFilePath("different/dummy"); @@ -1631,15 +1632,17 @@ public void TestUpdateDocumentsOrderExceptions() Assert.Throws(() => solution = solution.WithProjectDocumentsOrder(pid, ImmutableList.CreateRange(new[] { did3, did2, did1 }))); } - [Fact, Trait(Traits.Feature, Traits.Features.Workspace)] - public async Task TestAddingEditorConfigFileWithDiagnosticSeverity() + [Theory, Trait(Traits.Feature, Traits.Features.Workspace)] + [CombinatorialData] + public async Task TestAddingEditorConfigFileWithDiagnosticSeverity([CombinatorialValues(LanguageNames.CSharp, LanguageNames.VisualBasic)] string languageName, bool useRecoverableTrees) { - var solution = CreateSolution(); + var solution = useRecoverableTrees ? CreateNotKeptAliveSolution() : CreateSolution(); + var extension = languageName == LanguageNames.CSharp ? ".cs" : ".vb"; var projectId = ProjectId.CreateNewId(); var sourceDocumentId = DocumentId.CreateNewId(projectId); - solution = solution.AddProject(projectId, "Test", "Test.dll", LanguageNames.CSharp); - solution = solution.AddDocument(sourceDocumentId, "Test.cs", "// Hello, world!", filePath: @"Z:\Test.cs"); + solution = solution.AddProject(projectId, "Test", "Test.dll", languageName); + solution = solution.AddDocument(sourceDocumentId, "Test" + extension, "", filePath: @"Z:\Test" + extension); var originalSyntaxTree = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); var originalCompilation = await solution.GetProject(projectId).GetCompilationAsync(); @@ -1650,7 +1653,7 @@ public async Task TestAddingEditorConfigFileWithDiagnosticSeverity() editorConfigDocumentId, ".editorconfig", filePath: @"Z:\.editorconfig", - loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.cs]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); + loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.*]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); var newSyntaxTree = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); var newCompilation = await solution.GetProject(projectId).GetCompilationAsync(); @@ -1664,15 +1667,17 @@ public async Task TestAddingEditorConfigFileWithDiagnosticSeverity() Assert.Equal(ReportDiagnostic.Error, newSyntaxTree.DiagnosticOptions["CA1234"]); } - [Fact, Trait(Traits.Feature, Traits.Features.Workspace)] - public async Task TestAddingAndRemovingEditorConfigFileWithDiagnosticSeverity() + [Theory, Trait(Traits.Feature, Traits.Features.Workspace)] + [CombinatorialData] + public async Task TestAddingAndRemovingEditorConfigFileWithDiagnosticSeverity([CombinatorialValues(LanguageNames.CSharp, LanguageNames.VisualBasic)] string languageName, bool useRecoverableTrees) { - var solution = CreateSolution(); + var solution = useRecoverableTrees ? CreateNotKeptAliveSolution() : CreateSolution(); + var extension = languageName == LanguageNames.CSharp ? ".cs" : ".vb"; var projectId = ProjectId.CreateNewId(); var sourceDocumentId = DocumentId.CreateNewId(projectId); - solution = solution.AddProject(projectId, "Test", "Test.dll", LanguageNames.CSharp); - solution = solution.AddDocument(sourceDocumentId, "Test.cs", "// Hello, world!", filePath: @"Z:\Test.cs"); + solution = solution.AddProject(projectId, "Test", "Test.dll", languageName); + solution = solution.AddDocument(sourceDocumentId, "Test" + extension, "", filePath: @"Z:\Test" + extension); var editorConfigDocumentId = DocumentId.CreateNewId(projectId); solution = solution.AddAnalyzerConfigDocuments(ImmutableArray.Create( @@ -1680,7 +1685,7 @@ public async Task TestAddingAndRemovingEditorConfigFileWithDiagnosticSeverity() editorConfigDocumentId, ".editorconfig", filePath: @"Z:\.editorconfig", - loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.cs]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); + loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.*]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); var syntaxTreeAfterAddingEditorConfig = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); @@ -1698,15 +1703,17 @@ public async Task TestAddingAndRemovingEditorConfigFileWithDiagnosticSeverity() Assert.True(finalCompilation.ContainsSyntaxTree(syntaxTreeAfterRemovingEditorConfig)); } - [Fact, Trait(Traits.Feature, Traits.Features.Workspace)] - public async Task TestChangingAnEditorConfigFile() + [Theory, Trait(Traits.Feature, Traits.Features.Workspace)] + [CombinatorialData] + public async Task TestChangingAnEditorConfigFile([CombinatorialValues(LanguageNames.CSharp, LanguageNames.VisualBasic)] string languageName, bool useRecoverableTrees) { - var solution = CreateSolution(); + var solution = useRecoverableTrees ? CreateNotKeptAliveSolution() : CreateSolution(); + var extension = languageName == LanguageNames.CSharp ? ".cs" : ".vb"; var projectId = ProjectId.CreateNewId(); var sourceDocumentId = DocumentId.CreateNewId(projectId); - solution = solution.AddProject(projectId, "Test", "Test.dll", LanguageNames.CSharp); - solution = solution.AddDocument(sourceDocumentId, "Test.cs", "// Hello, world!", filePath: @"Z:\Test.cs"); + solution = solution.AddProject(projectId, "Test", "Test.dll", languageName); + solution = solution.AddDocument(sourceDocumentId, "Test" + extension, "", filePath: @"Z:\Test" + extension); var editorConfigDocumentId = DocumentId.CreateNewId(projectId); solution = solution.AddAnalyzerConfigDocuments(ImmutableArray.Create( @@ -1714,7 +1721,7 @@ public async Task TestChangingAnEditorConfigFile() editorConfigDocumentId, ".editorconfig", filePath: @"Z:\.editorconfig", - loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.cs]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); + loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.*]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); var syntaxTreeBeforeEditorConfigChange = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); @@ -1723,7 +1730,7 @@ public async Task TestChangingAnEditorConfigFile() solution = solution.WithAnalyzerConfigDocumentTextLoader( editorConfigDocumentId, - TextLoader.From(TextAndVersion.Create(SourceText.From("[*.cs]\r\n\r\ndotnet_diagnostic.CA6789.severity = error"), VersionStamp.Default)), + TextLoader.From(TextAndVersion.Create(SourceText.From("[*.*]\r\n\r\ndotnet_diagnostic.CA6789.severity = error"), VersionStamp.Default)), PreservationMode.PreserveValue); var syntaxTreeAfterEditorConfigChange = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); @@ -1736,6 +1743,46 @@ public async Task TestChangingAnEditorConfigFile() Assert.True(finalCompilation.ContainsSyntaxTree(syntaxTreeAfterEditorConfigChange)); } + [Theory, Trait(Traits.Feature, Traits.Features.Workspace)] + [CombinatorialData] + public async Task TestUpdateRootStillCarriesDiagnosticData([CombinatorialValues(LanguageNames.CSharp, LanguageNames.VisualBasic)] string languageName, bool useRecoverableTrees, PreservationMode preservationMode) + { + var solution = useRecoverableTrees ? CreateNotKeptAliveSolution() : CreateSolution(); + var extension = languageName == LanguageNames.CSharp ? ".cs" : ".vb"; + var projectId = ProjectId.CreateNewId(); + var sourceDocumentId = DocumentId.CreateNewId(projectId); + + solution = solution.AddProject(projectId, "Test", "Test.dll", languageName); + solution = solution.AddDocument(sourceDocumentId, "Test" + extension, "", filePath: @"Z:\Test" + extension); + + var editorConfigDocumentId = DocumentId.CreateNewId(projectId); + solution = solution.AddAnalyzerConfigDocuments(ImmutableArray.Create( + DocumentInfo.Create( + editorConfigDocumentId, + ".editorconfig", + filePath: @"Z:\.editorconfig", + loader: TextLoader.From(TextAndVersion.Create(SourceText.From("[*.*]\r\n\r\ndotnet_diagnostic.CA1234.severity = error"), VersionStamp.Default))))); + + var syntaxTreeBeforeUpdateRoot = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); + + Assert.Single(syntaxTreeBeforeUpdateRoot.DiagnosticOptions); + Assert.Equal(ReportDiagnostic.Error, syntaxTreeBeforeUpdateRoot.DiagnosticOptions["CA1234"]); + + // We are adding a new line to the previously empty file + var newRoot = syntaxTreeBeforeUpdateRoot.WithChangedText(SourceText.From("\r\n")); + + solution = solution.WithDocumentSyntaxRoot(sourceDocumentId, newRoot.GetRoot(), preservationMode); + + var syntaxTreeAfterUpdateRoot = await solution.GetDocument(sourceDocumentId).GetSyntaxTreeAsync(); + + Assert.Single(syntaxTreeAfterUpdateRoot.DiagnosticOptions); + Assert.Equal(ReportDiagnostic.Error, syntaxTreeAfterUpdateRoot.DiagnosticOptions["CA1234"]); + + var finalCompilation = await solution.GetProject(projectId).GetCompilationAsync(); + + Assert.True(finalCompilation.ContainsSyntaxTree(syntaxTreeAfterUpdateRoot)); + } + [Fact, Trait(Traits.Feature, Traits.Features.Workspace)] public void AddingAndRemovingProjectsUpdatesFilePathMap() { diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxTreeFactoryService.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxTreeFactoryService.vb index 3ab117630dbef170505a670668a86ac16f94d789..1f273237817c89b2438e747670f7b1bcca9a35a7 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxTreeFactoryService.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxTreeFactoryService.vb @@ -48,11 +48,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return SyntaxFactory.ParseSyntaxTree(text, options, filePath, treeDiagnosticReportingOptionsOpt, cancellationToken) End Function - Public Overloads Overrides Function CreateSyntaxTree(fileName As String, options As ParseOptions, encoding As Encoding, root As SyntaxNode) As SyntaxTree + Public Overrides Function CreateSyntaxTree(filePath As String, options As ParseOptions, encoding As Encoding, root As SyntaxNode, treeDiagnosticReportingOptionsOpt As ImmutableDictionary(Of String, ReportDiagnostic)) As SyntaxTree If options Is Nothing Then options = GetDefaultParseOptions() End If - Return SyntaxFactory.SyntaxTree(root, options, fileName, encoding) + Return VisualBasicSyntaxTree.Create(DirectCast(root, VisualBasicSyntaxNode), DirectCast(options, VisualBasicParseOptions), filePath, encoding, treeDiagnosticReportingOptionsOpt) End Function Public Overrides Function CanCreateRecoverableTree(root As SyntaxNode) As Boolean @@ -60,7 +60,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return MyBase.CanCreateRecoverableTree(root) AndAlso cu IsNot Nothing AndAlso cu.Attributes.Count = 0 End Function - Public Overrides Function CreateRecoverableTree(cacheKey As ProjectId, filePath As String, optionsOpt As ParseOptions, text As ValueSource(Of TextAndVersion), encoding As Encoding, root As SyntaxNode) As SyntaxTree + Public Overrides Function CreateRecoverableTree(cacheKey As ProjectId, + filePath As String, + optionsOpt As ParseOptions, + text As ValueSource(Of TextAndVersion), + encoding As Encoding, + root As SyntaxNode, + treeDiagnosticReportingOptionsOpt As ImmutableDictionary(Of String, ReportDiagnostic)) As SyntaxTree + Debug.Assert(CanCreateRecoverableTree(root)) Return RecoverableSyntaxTree.CreateRecoverableTree( Me, @@ -70,7 +77,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic text, encoding, DirectCast(root, CompilationUnitSyntax), - diagnosticOptions:=Nothing) + treeDiagnosticReportingOptionsOpt) End Function Public Overrides Function DeserializeNodeFrom(stream As Stream, cancellationToken As CancellationToken) As SyntaxNode