提交 d367ce54 编写于 作者: S Sam Harwell

Merge remote-tracking branch 'dotnet/release/dev16.3-preview1' into...

Merge remote-tracking branch 'dotnet/release/dev16.3-preview1' into merges/release/dev16.3-preview1-to-master
......@@ -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<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt)
{
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<string, ReportDiagnostic> 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<TextAndVersion> text, Encoding encoding, SyntaxNode root)
public override SyntaxTree CreateRecoverableTree(
ProjectId cacheKey,
string filePath,
ParseOptions options,
ValueSource<TextAndVersion> text,
Encoding encoding,
SyntaxNode root,
ImmutableDictionary<string, ReportDiagnostic> 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);
}
}
}
......
......@@ -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<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt);
public abstract SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, ImmutableDictionary<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt, CancellationToken cancellationToken);
public abstract SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource<TextAndVersion> text, Encoding encoding, SyntaxNode root);
public abstract SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource<TextAndVersion> text, Encoding encoding, SyntaxNode root, ImmutableDictionary<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt);
public abstract SyntaxNode DeserializeNodeFrom(Stream stream, CancellationToken cancellationToken);
public abstract ParseOptions GetDefaultParseOptionsWithLatestLanguageVersion();
......
......@@ -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<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt);
// new tree from text
SyntaxTree ParseSyntaxTree(string filePath, ParseOptions options, SourceText text, ImmutableDictionary<string, ReportDiagnostic> 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<TextAndVersion> text, Encoding encoding, SyntaxNode root);
SyntaxTree CreateRecoverableTree(ProjectId cacheKey, string filePath, ParseOptions options, ValueSource<TextAndVersion> text, Encoding encoding, SyntaxNode root, ImmutableDictionary<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt);
SyntaxNode DeserializeNodeFrom(Stream stream, CancellationToken cancellationToken);
}
......
......@@ -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<string, ReportDiagnostic> 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<ISyntaxTreeFactoryService>();
var result = CreateRecoverableTextAndTree(newRoot, newTextVersion, newTreeVersion, encoding, this.Attributes, _options, syntaxTreeFactory, mode, this.solutionServices);
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<ValueSource<TextAndVersion>, TreeAndVersion> CreateRecoverableTextAndTree(
SyntaxNode newRoot, VersionStamp textVersion, VersionStamp treeVersion, Encoding encoding,
DocumentInfo.DocumentAttributes attributes, ParseOptions options, ISyntaxTreeFactoryService factory, PreservationMode mode, SolutionServices solutionServices)
SyntaxNode newRoot,
string filePath,
VersionStamp textVersion,
VersionStamp treeVersion,
Encoding encoding,
DocumentInfo.DocumentAttributes attributes,
ParseOptions options,
ImmutableDictionary<string, ReportDiagnostic> treeDiagnosticReportingOptionsOpt,
ISyntaxTreeFactoryService factory,
PreservationMode mode)
{
var filePath = attributes.FilePath;
SyntaxTree tree = null;
ValueSource<TextAndVersion> 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));
......
......@@ -27,6 +27,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Buffers" Version="$(SystemBuffersVersion)" />
<PackageReference Include="Xunit.Combinatorial" Version="$(XunitCombinatorialVersion)" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
......
......@@ -11,7 +11,6 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
......@@ -1515,7 +1514,8 @@ public void TestWithSyntaxTree()
strongTree.Options,
new ConstantValueSource<TextAndVersion>(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");
......@@ -1630,15 +1630,17 @@ public void TestUpdateDocumentsOrderExceptions()
Assert.Throws<ArgumentException>(() => 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();
......@@ -1649,7 +1651,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();
......@@ -1663,15 +1665,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(
......@@ -1679,7 +1683,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();
......@@ -1697,15 +1701,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(
......@@ -1713,7 +1719,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();
......@@ -1722,7 +1728,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();
......@@ -1735,6 +1741,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()
{
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册