提交 05480ee4 编写于 作者: H Heejae Chang 提交者: GitHub

Merge pull request #19637 from heejaechang/lastbuild

changed behavior of LastDesignTimeBuildSucceeded following suggestion…
......@@ -871,6 +871,7 @@
<InternalsVisibleToTest Include="Microsoft.CodeAnalysis.Scripting.Destkop.UnitTests" />
<InternalsVisibleToTest Include="Microsoft.CodeAnalysis.CSharp.Scripting.UnitTests" />
<InternalsVisibleToTest Include="Microsoft.CodeAnalysis.CSharp.Scripting.Desktop.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor.CSharp.UnitTests" />
<InternalsVisibleToTest Include="Roslyn.Services.Editor2.UnitTests" />
</ItemGroup>
......
......@@ -55,7 +55,7 @@ public async Task AddStaticField()
await TestAddFieldAsync(input, expected,
type: GetTypeSymbol(typeof(string)),
accessibility: Accessibility.Private,
modifiers: new DeclarationModifiers(isStatic: true));
modifiers: new Editing.DeclarationModifiers(isStatic: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
......@@ -73,7 +73,7 @@ public async Task AddUnsafeField()
var input = "class [|C|] { }";
var expected = "class C { public unsafe int F; }";
await TestAddFieldAsync(input, expected,
modifiers: new DeclarationModifiers(isUnsafe: true),
modifiers: new Editing.DeclarationModifiers(isUnsafe: true),
type: GetTypeSymbol(typeof(int)));
}
......@@ -127,7 +127,7 @@ public async Task AddStaticConstructor()
var input = "class [|C|] { }";
var expected = "class C { static C() { } }";
await TestAddConstructorAsync(input, expected,
modifiers: new DeclarationModifiers(isStatic: true));
modifiers: new Editing.DeclarationModifiers(isStatic: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem(544082, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544082")]
......@@ -168,7 +168,7 @@ public async Task AddStaticClass()
var input = "namespace [|N|] { }";
var expected = "namespace N { public static class C { } }";
await TestAddNamedTypeAsync(input, expected,
modifiers: new DeclarationModifiers(isStatic: true));
modifiers: new Editing.DeclarationModifiers(isStatic: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem(544405, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544405")]
......@@ -178,7 +178,7 @@ public async Task AddSealedClass()
var expected = "namespace N { private sealed class C { } }";
await TestAddNamedTypeAsync(input, expected,
accessibility: Accessibility.Private,
modifiers: new DeclarationModifiers(isSealed: true));
modifiers: new Editing.DeclarationModifiers(isSealed: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration), WorkItem(544405, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544405")]
......@@ -188,7 +188,7 @@ public async Task AddAbstractClass()
var expected = "namespace N { protected internal abstract class C { } }";
await TestAddNamedTypeAsync(input, expected,
accessibility: Accessibility.ProtectedOrInternal,
modifiers: new DeclarationModifiers(isAbstract: true));
modifiers: new Editing.DeclarationModifiers(isAbstract: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
......@@ -209,7 +209,7 @@ public async Task AddSealedStruct()
var expected = "namespace N { public struct S { } }";
await TestAddNamedTypeAsync(input, expected,
name: "S",
modifiers: new DeclarationModifiers(isSealed: true),
modifiers: new Editing.DeclarationModifiers(isSealed: true),
accessibility: Accessibility.Public,
typeKind: TypeKind.Struct);
}
......@@ -261,7 +261,7 @@ public async Task AddSealedDelegateType()
await TestAddDelegateTypeAsync(input, expected,
returnType: typeof(int),
parameters: Parameters(Parameter(typeof(string), "s")),
modifiers: new DeclarationModifiers(isSealed: true));
modifiers: new Editing.DeclarationModifiers(isSealed: true));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeGeneration)]
......@@ -279,7 +279,7 @@ public async Task AddUnsafeEvent()
var input = "class [|C|] { }";
var expected = "class C { public unsafe event System.Action E; }";
await TestAddEventAsync(input, expected,
modifiers: new DeclarationModifiers(isUnsafe: true),
modifiers: new Editing.DeclarationModifiers(isUnsafe: true),
codeGenerationOptions: new CodeGenerationOptions(addImports: false));
}
......@@ -319,7 +319,7 @@ public async Task AddStaticMethodToStruct()
var input = "struct [|S|] { }";
var expected = "struct S { public static int M() { $$ } }";
await TestAddMethodAsync(input, expected,
modifiers: new DeclarationModifiers(isStatic: true),
modifiers: new Editing.DeclarationModifiers(isStatic: true),
returnType: typeof(int),
statements: "return 0;");
}
......@@ -331,7 +331,7 @@ public async Task AddSealedOverrideMethod()
var expected = "class C { public sealed override int GetHashCode() { $$ } }";
await TestAddMethodAsync(input, expected,
name: "GetHashCode",
modifiers: new DeclarationModifiers(isOverride: true, isSealed: true),
modifiers: new Editing.DeclarationModifiers(isOverride: true, isSealed: true),
returnType: typeof(int),
statements: "return 0;");
}
......@@ -342,7 +342,7 @@ public async Task AddAbstractMethod()
var input = "abstract class [|C|] { }";
var expected = "abstract class C { public abstract int M(); }";
await TestAddMethodAsync(input, expected,
modifiers: new DeclarationModifiers(isAbstract: true),
modifiers: new Editing.DeclarationModifiers(isAbstract: true),
returnType: typeof(int));
}
......@@ -374,7 +374,7 @@ public async Task AddVirtualMethod()
var expected = "class C { protected virtual int M() { $$ } }";
await TestAddMethodAsync(input, expected,
accessibility: Accessibility.Protected,
modifiers: new DeclarationModifiers(isVirtual: true),
modifiers: new Editing.DeclarationModifiers(isVirtual: true),
returnType: typeof(int),
statements: "return 0;");
}
......@@ -386,7 +386,7 @@ public async Task AddUnsafeNewMethod()
var expected = "class C { public unsafe new string ToString() { $$ } }";
await TestAddMethodAsync(input, expected,
name: "ToString",
modifiers: new DeclarationModifiers(isNew: true, isUnsafe: true),
modifiers: new Editing.DeclarationModifiers(isNew: true, isUnsafe: true),
returnType: typeof(string),
statements: "return String.Empty;");
}
......@@ -400,7 +400,7 @@ public async Task AddExplicitImplementationOfUnsafeMethod()
name: "M",
returnType: typeof(void),
parameters: Parameters(Parameter(typeof(int), "i")),
modifiers: new DeclarationModifiers(isUnsafe: true),
modifiers: new Editing.DeclarationModifiers(isUnsafe: true),
explicitInterface: s => s.LookupSymbols(input.IndexOf('M'), null, "M").First() as IMethodSymbol);
}
......@@ -638,7 +638,7 @@ public async Task AddUnsafeAutoProperty()
var expected = "class C { public unsafe int P { get; internal set; } }";
await TestAddPropertyAsync(input, expected,
type: typeof(int),
modifiers: new DeclarationModifiers(isUnsafe: true),
modifiers: new Editing.DeclarationModifiers(isUnsafe: true),
setterAccessibility: Accessibility.Internal);
}
......@@ -961,7 +961,7 @@ public async Task TestUpdateModifiers()
}";
var eol = SyntaxFactory.EndOfLine(@"");
var newModifiers = new[] { SyntaxFactory.Token(SyntaxKind.InternalKeyword).WithLeadingTrivia(eol) }.Concat(
CreateModifierTokens(new DeclarationModifiers(isSealed: true, isPartial: true), LanguageNames.CSharp));
CreateModifierTokens(new Editing.DeclarationModifiers(isSealed: true, isPartial: true), LanguageNames.CSharp));
await TestUpdateDeclarationAsync<ClassDeclarationSyntax>(input, expected, modifiers: newModifiers);
}
......@@ -1019,7 +1019,7 @@ public static class C
public int f;
public int f2;
}";
var getField = CreateField(Accessibility.Public, new DeclarationModifiers(), typeof(int), "f2");
var getField = CreateField(Accessibility.Public, new Editing.DeclarationModifiers(), typeof(int), "f2");
var getMembers = ImmutableArray.Create(getField);
await TestUpdateDeclarationAsync<ClassDeclarationSyntax>(
input, expected, getNewMembers: getMembers);
......@@ -1045,7 +1045,7 @@ public static class C
// Comment 1
public static char F() { return 0; }
}";
var getField = CreateField(Accessibility.Public, new DeclarationModifiers(), typeof(int), "f2");
var getField = CreateField(Accessibility.Public, new Editing.DeclarationModifiers(), typeof(int), "f2");
var getMembers = ImmutableArray.Create(getField);
await TestUpdateDeclarationAsync<ClassDeclarationSyntax>(input, expected, getNewMembers: getMembers, declareNewMembersAtTop: true);
}
......
......@@ -49,7 +49,7 @@ public partial class CodeGenerationTests
Func<SemanticModel, ITypeSymbol> type = null,
string name = "F",
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions),
bool ignoreTrivia = true,
bool hasConstantValue = false,
......@@ -84,7 +84,7 @@ public partial class CodeGenerationTests
string expected,
string name = "C",
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters = default(ImmutableArray<Func<SemanticModel, IParameterSymbol>>),
ImmutableArray<SyntaxNode> statements = default(ImmutableArray<SyntaxNode>),
ImmutableArray<SyntaxNode> baseArguments = default(ImmutableArray<SyntaxNode>),
......@@ -113,7 +113,7 @@ public partial class CodeGenerationTests
string expected,
string name = "M",
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
Type returnType = null,
Func<SemanticModel, IMethodSymbol> explicitInterface = null,
ImmutableArray<ITypeParameterSymbol> typeParameters = default(ImmutableArray<ITypeParameterSymbol>),
......@@ -154,7 +154,7 @@ public partial class CodeGenerationTests
string expected,
CodeGenerationOperatorKind[] operatorKinds,
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
Type returnType = null,
ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters = default(ImmutableArray<Func<SemanticModel, IParameterSymbol>>),
string statements = null,
......@@ -191,7 +191,7 @@ public partial class CodeGenerationTests
string initial,
CodeGenerationOperatorKind operatorKind,
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
Type returnType = null,
ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters = default(ImmutableArray<Func<SemanticModel, IParameterSymbol>>),
string statements = null,
......@@ -235,7 +235,7 @@ public partial class CodeGenerationTests
Func<SemanticModel, IParameterSymbol> fromType,
bool isImplicit = false,
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
string statements = null,
CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions),
bool ignoreTrivia = true)
......@@ -303,7 +303,7 @@ public partial class CodeGenerationTests
string expected,
string name = "D",
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
Type returnType = null,
ImmutableArray<ITypeParameterSymbol> typeParameters = default(ImmutableArray<ITypeParameterSymbol>),
ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters = default(ImmutableArray<Func<SemanticModel, IParameterSymbol>>),
......@@ -332,7 +332,7 @@ public partial class CodeGenerationTests
string name = "E",
ImmutableArray<AttributeData> attributes = default(ImmutableArray<AttributeData>),
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters = default(ImmutableArray<Func<SemanticModel, IParameterSymbol>>),
Type type = null,
Func<SemanticModel, IEventSymbol> explicitInterfaceSymbol = null,
......@@ -368,7 +368,7 @@ public partial class CodeGenerationTests
string name = "P",
Accessibility defaultAccessibility = Accessibility.Public,
Accessibility setterAccessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
string getStatements = null,
string setStatements = null,
Type type = null,
......@@ -408,7 +408,7 @@ public partial class CodeGenerationTests
IMethodSymbol getAccessor = CodeGenerationSymbolFactory.CreateMethodSymbol(
default(ImmutableArray<AttributeData>),
defaultAccessibility,
new DeclarationModifiers(isAbstract: getStatements == null),
new Editing.DeclarationModifiers(isAbstract: getStatements == null),
typeSymbol,
false,
null,
......@@ -419,7 +419,7 @@ public partial class CodeGenerationTests
IMethodSymbol setAccessor = CodeGenerationSymbolFactory.CreateMethodSymbol(
default(ImmutableArray<AttributeData>),
setterAccessibility,
new DeclarationModifiers(isAbstract: setStatements == null),
new Editing.DeclarationModifiers(isAbstract: setStatements == null),
GetTypeSymbol(typeof(void))(context.SemanticModel),
false,
null,
......@@ -461,7 +461,7 @@ public partial class CodeGenerationTests
string expected,
string name = "C",
Accessibility accessibility = Accessibility.Public,
DeclarationModifiers modifiers = default(DeclarationModifiers),
Editing.DeclarationModifiers modifiers = default(Editing.DeclarationModifiers),
TypeKind typeKind = TypeKind.Class,
ImmutableArray<ITypeParameterSymbol> typeParameters = default(ImmutableArray<ITypeParameterSymbol>),
INamedTypeSymbol baseType = null,
......@@ -645,7 +645,7 @@ private static ITypeSymbol GetTypeSymbol(Compilation compilation, string typeFul
}
private static ImmutableArray<IParameterSymbol> GetParameterSymbols(ImmutableArray<Func<SemanticModel, IParameterSymbol>> parameters, TestContext context)
=> parameters.IsDefault
=> parameters.IsDefault
? default(ImmutableArray<IParameterSymbol>)
: parameters.SelectAsArray(p => p(context.SemanticModel));
......@@ -656,7 +656,7 @@ private static IMethodSymbol GetMethodSymbol(Func<SemanticModel, IMethodSymbol>
private static ImmutableArray<ISymbol> GetSymbols(ImmutableArray<Func<SemanticModel, ISymbol>> members, TestContext context)
{
return members == null
return members == null
? default(ImmutableArray<ISymbol>)
: members.SelectAsArray(m => m(context.SemanticModel));
}
......@@ -665,10 +665,10 @@ private static ImmutableArray<ISymbol> GetSymbols(ImmutableArray<Func<SemanticMo
{
return s => CodeGenerationSymbolFactory.CreateFieldSymbol(
default(ImmutableArray<AttributeData>), Accessibility.Public,
new DeclarationModifiers(), GetTypeSymbol(typeof(int))(s), name, value != null, value);
new Editing.DeclarationModifiers(), GetTypeSymbol(typeof(int))(s), name, value != null, value);
}
internal static Func<SemanticModel, ISymbol> CreateField(Accessibility accessibility, DeclarationModifiers modifiers, Type type, string name)
internal static Func<SemanticModel, ISymbol> CreateField(Accessibility accessibility, Editing.DeclarationModifiers modifiers, Type type, string name)
{
return s => CodeGenerationSymbolFactory.CreateFieldSymbol(
default(ImmutableArray<AttributeData>), accessibility,
......@@ -685,7 +685,7 @@ private static ImmutableArray<ISymbol> GetSymbols(ImmutableArray<Func<SemanticMo
return s => s == null ? null : s.Compilation.GetTypeByMetadataName(typeMetadataName);
}
internal static IEnumerable<SyntaxToken> CreateModifierTokens(DeclarationModifiers modifiers, string language)
internal static IEnumerable<SyntaxToken> CreateModifierTokens(Editing.DeclarationModifiers modifiers, string language)
{
if (language == LanguageNames.CSharp)
{
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.CSharp;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Text;
......@@ -40,6 +43,19 @@ public async Task TestHasSuccessfullyLoadedBeingFalse()
await listener.CreateWaitTask().ConfigureAwait(false);
}
[Fact]
public async Task TestHasSuccessfullyLoadedBeingFalseFSAOn()
{
var workspace = new AdhocWorkspace();
workspace.Options = workspace.Options.WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.CSharp, true);
var document = GetDocumentFromIncompleteProject(workspace);
// open document
workspace.OpenDocument(document.Id);
await TestAnalyzerAsync(workspace, document, new Analyzer(), AnalyzerResultSetter, expectedSyntax: true, expectedSemantic: true);
}
[Fact]
public async Task TestHasSuccessfullyLoadedBeingFalseWhenFileOpened()
{
......@@ -49,9 +65,41 @@ public async Task TestHasSuccessfullyLoadedBeingFalseWhenFileOpened()
// open document
workspace.OpenDocument(document.Id);
await TestAnalyzerAsync(workspace, document, new Analyzer(), AnalyzerResultSetter, expectedSyntax: true, expectedSemantic: true);
}
[Fact]
public async Task TestHasSuccessfullyLoadedBeingFalseWhenFileOpenedWithCompilerAnalyzer()
{
var workspace = new AdhocWorkspace();
var document = GetDocumentFromIncompleteProject(workspace);
// open document
workspace.OpenDocument(document.Id);
await TestAnalyzerAsync(workspace, document, new CSharpCompilerDiagnosticAnalyzer(), CompilerAnalyzerResultSetter, expectedSyntax: true, expectedSemantic: false);
}
[Fact]
public async Task TestHasSuccessfullyLoadedBeingFalseWithCompilerAnalyzerFSAOn()
{
var workspace = new AdhocWorkspace();
workspace.Options = workspace.Options.WithChangedOption(ServiceFeatureOnOffOptions.ClosedFileDiagnostic, LanguageNames.CSharp, true);
var document = GetDocumentFromIncompleteProject(workspace);
await TestAnalyzerAsync(workspace, document, new CSharpCompilerDiagnosticAnalyzer(), CompilerAnalyzerResultSetter, expectedSyntax: true, expectedSemantic: false);
}
private static async Task TestAnalyzerAsync(
AdhocWorkspace workspace,
Document document,
DiagnosticAnalyzer diagnosticAnalyzer,
Func<bool, bool, ImmutableArray<DiagnosticData>, (bool, bool)> resultSetter,
bool expectedSyntax, bool expectedSemantic)
{
// create listener/service/analyzer
var listener = new AsynchronousOperationListener();
var service = new MyDiagnosticAnalyzerService(new Analyzer(), listener);
var service = new MyDiagnosticAnalyzerService(diagnosticAnalyzer, listener);
var analyzer = service.CreateIncrementalAnalyzer(workspace);
bool syntax = false;
......@@ -60,18 +108,7 @@ public async Task TestHasSuccessfullyLoadedBeingFalseWhenFileOpened()
// listen to events
service.DiagnosticsUpdated += (s, a) =>
{
switch (a.Diagnostics.Length)
{
case 0:
return;
case 1:
syntax |= a.Diagnostics[0].Id == Analyzer.s_syntaxRule.Id;
semantic |= a.Diagnostics[0].Id == Analyzer.s_semanticRule.Id;
return;
default:
AssertEx.Fail("shouldn't reach here");
return;
}
(syntax, semantic) = resultSetter(syntax, semantic, a.Diagnostics);
};
// now call each analyze method. none of them should run.
......@@ -81,8 +118,8 @@ public async Task TestHasSuccessfullyLoadedBeingFalseWhenFileOpened()
await listener.CreateWaitTask().ConfigureAwait(false);
// two should have been called.
Assert.True(syntax);
Assert.True(semantic);
Assert.Equal(expectedSyntax, syntax);
Assert.Equal(expectedSemantic, semantic);
}
[Fact]
......@@ -215,7 +252,33 @@ private static Document GetDocumentFromIncompleteProject(AdhocWorkspace workspac
"CSharpProject",
LanguageNames.CSharp).WithHasAllInformation(hasAllInformation: false));
return workspace.AddDocument(project.Id, "Empty.cs", SourceText.From(""));
return workspace.AddDocument(project.Id, "Empty.cs", SourceText.From("class A { B B {get} }"));
}
private static (bool, bool) AnalyzerResultSetter(bool syntax, bool semantic, ImmutableArray<DiagnosticData> diagnostics)
{
switch (diagnostics.Length)
{
case 0:
break;
case 1:
syntax |= diagnostics[0].Id == Analyzer.s_syntaxRule.Id;
semantic |= diagnostics[0].Id == Analyzer.s_semanticRule.Id;
break;
default:
AssertEx.Fail("shouldn't reach here");
break;
}
return (syntax, semantic);
}
private static (bool, bool) CompilerAnalyzerResultSetter(bool syntax, bool semantic, ImmutableArray<DiagnosticData> diagnostics)
{
syntax |= diagnostics.Any(d => d.Properties["Origin"] == "Syntactic");
semantic |= diagnostics.Any(d => d.Properties["Origin"] != "Syntactic");
return (syntax, semantic);
}
private static async Task RunAllAnalysisAsync(IIncrementalAnalyzer analyzer, Document document)
......
......@@ -110,13 +110,18 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
}
// perf optimization. check whether we want to analyze this project or not.
if (!await FullAnalysisEnabledAsync(project, forceAnalyzerRun, cancellationToken).ConfigureAwait(false))
if (!FullAnalysisEnabled(project, forceAnalyzerRun))
{
return new ProjectAnalysisData(project.Id, VersionStamp.Default, existingData.Result, ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>.Empty);
}
var result = await ComputeDiagnosticsAsync(analyzerDriverOpt, project, stateSets, existingData.Result, cancellationToken).ConfigureAwait(false);
// if project is not loaded successfully, get rid of any semantic errors from compiler analyzer
// * NOTE * previously when project is not loaded successfully, we actually dropped doing anything on the project, but now
// we do everything but filter out some information. so on such projects, there will be some perf degradation.
result = await FilterOutCompilerSemanticErrorsIfNeccessaryAsync(project, result, cancellationToken).ConfigureAwait(false);
return new ProjectAnalysisData(project.Id, version, existingData.Result, result);
}
catch (Exception e) when (FatalError.ReportUnlessCanceled(e))
......@@ -126,6 +131,45 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
}
}
private async Task<ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult>> FilterOutCompilerSemanticErrorsIfNeccessaryAsync(
Project project, ImmutableDictionary<DiagnosticAnalyzer, DiagnosticAnalysisResult> result, CancellationToken cancellationToken)
{
// see whether solution is loaded successfully
var projectLoadedSuccessfully = await project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false);
if (projectLoadedSuccessfully)
{
return result;
}
var compilerAnalyzer = _owner.HostAnalyzerManager.GetCompilerDiagnosticAnalyzer(project.Language);
if (compilerAnalyzer == null)
{
// this language doesn't support compiler analyzer
return result;
}
DiagnosticAnalysisResult analysisResult;
if (!result.TryGetValue(compilerAnalyzer, out analysisResult))
{
// no result from compiler analyzer
return result;
}
// get rid of any result except syntax from compiler analyzer result
var newCompilerAnalysisResult = new DiagnosticAnalysisResult(
analysisResult.ProjectId,
analysisResult.Version,
analysisResult.SyntaxLocals,
semanticLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
nonLocals: ImmutableDictionary<DocumentId, ImmutableArray<DiagnosticData>>.Empty,
others: ImmutableArray<DiagnosticData>.Empty,
documentIds: null,
fromBuild: false);
// return new result
return result.SetItem(compilerAnalyzer, newCompilerAnalysisResult);
}
/// <summary>
/// Return all local diagnostics (syntax, semantic) that belong to given document for the given StateSet (analyzer) by calculating them
/// </summary>
......@@ -397,6 +441,11 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
return ImmutableArray<Diagnostic>.Empty;
}
if (!await SemanticAnalysisEnabled(document, analyzer, kind, cancellationToken).ConfigureAwait(false))
{
return ImmutableArray<Diagnostic>.Empty;
}
// REVIEW: more unnecessary allocations just to get diagnostics per analyzer
var oneAnalyzers = ImmutableArray.Create(analyzer);
......@@ -419,6 +468,16 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
}
}
private async Task<bool> SemanticAnalysisEnabled(Document document, DiagnosticAnalyzer analyzer, AnalysisKind kind, CancellationToken cancellationToken)
{
// if project is not loaded successfully then, we disable semantic errors for compiler analyzers
var disabled = kind != AnalysisKind.Syntax &&
_owner.HostAnalyzerManager.IsCompilerDiagnosticAnalyzer(document.Project.Language, analyzer) &&
!await document.Project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false);
return !disabled;
}
private void UpdateAnalyzerTelemetryData(
DiagnosticAnalysisResultMap<DiagnosticAnalyzer, DiagnosticAnalysisResult> analysisResults, Project project, CancellationToken cancellationToken)
{
......@@ -428,11 +487,12 @@ public IEnumerable<DiagnosticData> ConvertToLocalDiagnostics(Document targetDocu
}
}
private static async Task<bool> FullAnalysisEnabledAsync(Project project, bool ignoreFullAnalysisOptions, CancellationToken cancellationToken)
private static bool FullAnalysisEnabled(Project project, bool forceAnalyzerRun)
{
if (ignoreFullAnalysisOptions)
if (forceAnalyzerRun)
{
return await project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false);
// asked to ignore any checks.
return true;
}
if (!ServiceFeatureOnOffOptions.IsClosedFileDiagnosticsEnabled(project) ||
......@@ -441,7 +501,7 @@ private static async Task<bool> FullAnalysisEnabledAsync(Project project, bool i
return false;
}
return await project.HasSuccessfullyLoadedAsync(cancellationToken).ConfigureAwait(false);
return true;
}
private static bool IsCanceled(Exception ex, CancellationToken cancellationToken)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册