Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit897d928

Browse files
authored
Merge pull request#46508 from mavasani/AnalyzerDriverSemanticModelProvider
Analyzer driver performance improvements
2 parents2c1be7c +5389716 commit897d928

File tree

22 files changed

+490
-304
lines changed

22 files changed

+490
-304
lines changed

‎src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs‎

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ private static CSharpCompilation Create(
361361
options.SourceReferenceResolver,
362362
CSharp.MessageProvider.Instance,
363363
isSubmission,
364-
state:null));
364+
state:null),
365+
semanticModelProvider:null);
365366

366367
if(syntaxTrees!=null)
367368
{
@@ -383,8 +384,9 @@ private CSharpCompilation(
383384
ReferenceManager?referenceManager,
384385
boolreuseReferenceManager,
385386
SyntaxAndDeclarationManagersyntaxAndDeclarations,
387+
SemanticModelProvider?semanticModelProvider,
386388
AsyncQueue<CompilationEvent>?eventQueue=null)
387-
:this(assemblyName,options,references,previousSubmission,submissionReturnType,hostObjectType,isSubmission,referenceManager,reuseReferenceManager,syntaxAndDeclarations,SyntaxTreeCommonFeatures(syntaxAndDeclarations.ExternalSyntaxTrees),eventQueue)
389+
:this(assemblyName,options,references,previousSubmission,submissionReturnType,hostObjectType,isSubmission,referenceManager,reuseReferenceManager,syntaxAndDeclarations,SyntaxTreeCommonFeatures(syntaxAndDeclarations.ExternalSyntaxTrees),semanticModelProvider,eventQueue)
388390
{
389391
}
390392

@@ -400,8 +402,9 @@ private CSharpCompilation(
400402
boolreuseReferenceManager,
401403
SyntaxAndDeclarationManagersyntaxAndDeclarations,
402404
IReadOnlyDictionary<string,string>features,
405+
SemanticModelProvider?semanticModelProvider,
403406
AsyncQueue<CompilationEvent>?eventQueue=null)
404-
:base(assemblyName,references,features,isSubmission,eventQueue)
407+
:base(assemblyName,references,features,isSubmission,semanticModelProvider,eventQueue)
405408
{
406409
WellKnownMemberSignatureComparer=newWellKnownMembersSignatureComparer(this);
407410
_options=options;
@@ -494,7 +497,8 @@ private static LanguageVersion CommonLanguageVersion(ImmutableArray<SyntaxTree>
494497
this.IsSubmission,
495498
_referenceManager,
496499
reuseReferenceManager:true,
497-
syntaxAndDeclarations:_syntaxAndDeclarations);
500+
_syntaxAndDeclarations,
501+
this.SemanticModelProvider);
498502
}
499503

500504
privateCSharpCompilationUpdate(
@@ -512,7 +516,8 @@ private CSharpCompilation Update(
512516
this.IsSubmission,
513517
referenceManager,
514518
reuseReferenceManager,
515-
syntaxAndDeclarations);
519+
syntaxAndDeclarations,
520+
this.SemanticModelProvider);
516521
}
517522

518523
/// <summary>
@@ -534,7 +539,8 @@ private CSharpCompilation Update(
534539
this.IsSubmission,
535540
_referenceManager,
536541
reuseReferenceManager:assemblyName==this.AssemblyName,
537-
syntaxAndDeclarations:_syntaxAndDeclarations);
542+
_syntaxAndDeclarations,
543+
this.SemanticModelProvider);
538544
}
539545

540546
/// <summary>
@@ -563,7 +569,8 @@ private CSharpCompilation Update(
563569
this.IsSubmission,
564570
referenceManager:null,
565571
reuseReferenceManager:false,
566-
syntaxAndDeclarations:_syntaxAndDeclarations);
572+
_syntaxAndDeclarations,
573+
this.SemanticModelProvider);
567574
}
568575

569576
/// <summary>
@@ -602,7 +609,8 @@ public CSharpCompilation WithOptions(CSharpCompilationOptions options)
602609
options.SourceReferenceResolver,
603610
_syntaxAndDeclarations.MessageProvider,
604611
_syntaxAndDeclarations.IsSubmission,
605-
state:null));
612+
state:null),
613+
this.SemanticModelProvider);
606614
}
607615

608616
/// <summary>
@@ -633,7 +641,32 @@ public CSharpCompilation WithScriptCompilationInfo(CSharpScriptCompilationInfo?
633641
isSubmission:info!=null,
634642
_referenceManager,
635643
reuseReferenceManager,
636-
syntaxAndDeclarations:_syntaxAndDeclarations);
644+
_syntaxAndDeclarations,
645+
this.SemanticModelProvider);
646+
}
647+
648+
/// <summary>
649+
/// Returns a new compilation with the given semantic model provider.
650+
/// </summary>
651+
internaloverrideCompilationWithSemanticModelProvider(SemanticModelProvider?semanticModelProvider)
652+
{
653+
if(this.SemanticModelProvider==semanticModelProvider)
654+
{
655+
returnthis;
656+
}
657+
658+
returnnewCSharpCompilation(
659+
this.AssemblyName,
660+
_options,
661+
this.ExternalReferences,
662+
this.PreviousSubmission,
663+
this.SubmissionReturnType,
664+
this.HostObjectType,
665+
this.IsSubmission,
666+
_referenceManager,
667+
reuseReferenceManager:true,
668+
_syntaxAndDeclarations,
669+
semanticModelProvider);
637670
}
638671

639672
/// <summary>
@@ -651,8 +684,9 @@ internal override Compilation WithEventQueue(AsyncQueue<CompilationEvent>? event
651684
this.IsSubmission,
652685
_referenceManager,
653686
reuseReferenceManager:true,
654-
syntaxAndDeclarations:_syntaxAndDeclarations,
655-
eventQueue:eventQueue);
687+
_syntaxAndDeclarations,
688+
this.SemanticModelProvider,
689+
eventQueue);
656690
}
657691

658692
#endregion
@@ -2085,9 +2119,19 @@ internal void AddModuleInitializerMethod(MethodSymbol method)
20852119
thrownewArgumentException(CSharpResources.SyntaxTreeNotFound,nameof(syntaxTree));
20862120
}
20872121

2088-
returnnewSyntaxTreeSemanticModel(this,(SyntaxTree)syntaxTree,ignoreAccessibility);
2122+
SemanticModel?model=null;
2123+
if(SemanticModelProvider!=null)
2124+
{
2125+
model=SemanticModelProvider.GetSemanticModel(syntaxTree,this,ignoreAccessibility);
2126+
Debug.Assert(model!=null);
2127+
}
2128+
2129+
returnmodel??CreateSemanticModel(syntaxTree,ignoreAccessibility);
20892130
}
20902131

2132+
internaloverrideSemanticModelCreateSemanticModel(SyntaxTreesyntaxTree,boolignoreAccessibility)
2133+
=>newSyntaxTreeSemanticModel(this,syntaxTree,ignoreAccessibility);
2134+
20912135
// When building symbols from the declaration table (lazily), or inside a type, or when
20922136
// compiling a method body, we may not have a BinderContext in hand for the enclosing
20932137
// scopes. Therefore, we build them when needed (and cache them) using a ContextBuilder.

‎src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.CSharp
2121
/// <summary>
2222
/// Allows asking semantic questions about a tree of syntax nodes in a Compilation. Typically,
2323
/// an instance is obtained by a call to <see cref="Compilation"/>.<see
24-
/// cref="Compilation.GetSemanticModel"/>.
24+
/// cref="Compilation.GetSemanticModel(SyntaxTree, bool)"/>.
2525
/// </summary>
2626
/// <remarks>
2727
/// <para>An instance of <see cref="CSharpSemanticModel"/> caches local symbols and semantic

‎src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs‎

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,32 +1084,26 @@ private void CompileMethod(
10841084

10851085
if(diagsWritten&&!methodSymbol.IsImplicitlyDeclared&&_compilation.EventQueue!=null)
10861086
{
1087-
Lazy<SemanticModel>lazySemanticModel=null;
1088-
1089-
if(body!=null)
1087+
// If compilation has a caching semantic model provider, then cache the already-computed bound tree
1088+
// onto the semantic model and store it on the event.
1089+
SyntaxTreeSemanticModelsemanticModelWithCachedBoundNodes=null;
1090+
if(body!=null&&
1091+
forSemanticModel.Syntaxis{}semanticModelSyntax&&
1092+
_compilation.SemanticModelProviderisCachingSemanticModelProvidercachingSemanticModelProvider)
10901093
{
1091-
lazySemanticModel=newLazy<SemanticModel>(()=>
1092-
{
1093-
varsyntax=body.Syntax;
1094-
varsemanticModel=(SyntaxTreeSemanticModel)_compilation.GetSemanticModel(syntax.SyntaxTree);
1095-
1096-
if(forSemanticModel.Syntaxis{}semanticModelSyntax)
1097-
{
1098-
semanticModel.GetOrAddModel(semanticModelSyntax,
1099-
(rootSyntax)=>
1100-
{
1101-
Debug.Assert(rootSyntax==forSemanticModel.Syntax);
1102-
returnMethodBodySemanticModel.Create(semanticModel,
1103-
methodSymbol,
1104-
forSemanticModel);
1105-
});
1106-
}
1107-
1108-
returnsemanticModel;
1109-
});
1094+
varsyntax=body.Syntax;
1095+
semanticModelWithCachedBoundNodes=(SyntaxTreeSemanticModel)cachingSemanticModelProvider.GetSemanticModel(syntax.SyntaxTree,_compilation);
1096+
semanticModelWithCachedBoundNodes.GetOrAddModel(semanticModelSyntax,
1097+
(rootSyntax)=>
1098+
{
1099+
Debug.Assert(rootSyntax==forSemanticModel.Syntax);
1100+
returnMethodBodySemanticModel.Create(semanticModelWithCachedBoundNodes,
1101+
methodSymbol,
1102+
forSemanticModel);
1103+
});
11101104
}
11111105

1112-
_compilation.EventQueue.TryEnqueue(newSymbolDeclaredCompilationEvent(_compilation,methodSymbol.GetPublicSymbol(),lazySemanticModel));
1106+
_compilation.EventQueue.TryEnqueue(newSymbolDeclaredCompilationEvent(_compilation,methodSymbol.GetPublicSymbol(),semanticModelWithCachedBoundNodes));
11131107
}
11141108

11151109
// Don't lower if we're not emitting or if there were errors.

‎src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.cs‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
usingSystem;
6+
usingSystem.Collections.Concurrent;
67
usingSystem.Collections.Generic;
78
usingSystem.Collections.Immutable;
89
usingSystem.Linq;
@@ -3747,5 +3748,38 @@ static ImmutableArray<Diagnostic> getReportedDiagnostics(AnalysisResult analysis
37473748
}
37483749
}
37493750
}
3751+
3752+
[Fact]
3753+
publicvoidTestSemanticModelProvider()
3754+
{
3755+
vartree=CSharpSyntaxTree.ParseText(@"class C { }");
3756+
Compilationcompilation=CreateCompilation(new[]{tree});
3757+
3758+
varsemanticModelProvider=newMySemanticModelProvider();
3759+
compilation=compilation.WithSemanticModelProvider(semanticModelProvider);
3760+
3761+
// Verify semantic model provider is used by Compilation.GetSemanticModel API
3762+
varmodel=compilation.GetSemanticModel(tree);
3763+
semanticModelProvider.VerifyCachedModel(tree,model);
3764+
3765+
// Verify semantic model provider is used by CSharpCompilation.GetSemanticModel API
3766+
model=((CSharpCompilation)compilation).GetSemanticModel(tree,ignoreAccessibility:false);
3767+
semanticModelProvider.VerifyCachedModel(tree,model);
3768+
}
3769+
3770+
privatesealedclassMySemanticModelProvider:SemanticModelProvider
3771+
{
3772+
privatereadonlyConcurrentDictionary<SyntaxTree,SemanticModel>_cache=newConcurrentDictionary<SyntaxTree,SemanticModel>();
3773+
3774+
publicoverrideSemanticModelGetSemanticModel(SyntaxTreetree,Compilationcompilation,boolignoreAccessibility=false)
3775+
{
3776+
return_cache.GetOrAdd(tree,compilation.CreateSemanticModel(tree,ignoreAccessibility));
3777+
}
3778+
3779+
publicvoidVerifyCachedModel(SyntaxTreetree,SemanticModelmodel)
3780+
{
3781+
Assert.Same(model,_cache[tree]);
3782+
}
3783+
}
37503784
}
37513785
}

‎src/Compilers/Core/Portable/Compilation/Compilation.cs‎

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,15 @@ internal Compilation(
7272
ImmutableArray<MetadataReference>references,
7373
IReadOnlyDictionary<string,string>features,
7474
boolisSubmission,
75+
SemanticModelProvider?semanticModelProvider,
7576
AsyncQueue<CompilationEvent>?eventQueue)
7677
{
7778
RoslynDebug.Assert(!references.IsDefault);
7879
RoslynDebug.Assert(features!=null);
7980

8081
this.AssemblyName=name;
8182
this.ExternalReferences=references;
83+
this.SemanticModelProvider=semanticModelProvider;
8284
this.EventQueue=eventQueue;
8385

8486
_lazySubmissionSlotIndex=isSubmission?SubmissionSlotIndexToBeAllocated:SubmissionSlotIndexNotApplicable;
@@ -195,6 +197,11 @@ public Compilation Clone()
195197
/// </summary>
196198
internalabstractCompilationWithEventQueue(AsyncQueue<CompilationEvent>?eventQueue);
197199

200+
/// <summary>
201+
/// Returns a new compilation with a given semantic model provider.
202+
/// </summary>
203+
internalabstractCompilationWithSemanticModelProvider(SemanticModelProvidersemanticModelProvider);
204+
198205
/// <summary>
199206
/// Gets a new <see cref="SemanticModel"/> for the specified syntax tree.
200207
/// </summary>
@@ -203,12 +210,28 @@ public Compilation Clone()
203210
/// True if the SemanticModel should ignore accessibility rules when answering semantic questions.
204211
/// </param>
205212
publicSemanticModelGetSemanticModel(SyntaxTreesyntaxTree,boolignoreAccessibility=false)
206-
{
207-
returnCommonGetSemanticModel(syntaxTree,ignoreAccessibility);
208-
}
213+
=>CommonGetSemanticModel(syntaxTree,ignoreAccessibility);
209214

215+
/// <summary>
216+
/// Gets a <see cref="SemanticModel"/> for the given <paramref name="syntaxTree"/>.
217+
/// If <see cref="SemanticModelProvider"/> is non-null, it attempts to use <see cref="SemanticModelProvider.GetSemanticModel(SyntaxTree, Compilation, bool)"/>
218+
/// to get a semantic model. Otherwise, it creates a new semantic model using <see cref="CreateSemanticModel(SyntaxTree, bool)"/>.
219+
/// </summary>
220+
/// <param name="syntaxTree"></param>
221+
/// <param name="ignoreAccessibility"></param>
222+
/// <returns></returns>
210223
protectedabstractSemanticModelCommonGetSemanticModel(SyntaxTreesyntaxTree,boolignoreAccessibility);
211224

225+
/// <summary>
226+
/// Creates a new <see cref="SemanticModel"/> for the given <paramref name="syntaxTree"/>.
227+
/// Unlike the <see cref="GetSemanticModel(SyntaxTree, bool)"/> and <see cref="CommonGetSemanticModel(SyntaxTree, bool)"/>,
228+
/// it does not attempt to use the <see cref="SemanticModelProvider"/> to get a semantic model, but instead always creates a new semantic model.
229+
/// </summary>
230+
/// <param name="syntaxTree"></param>
231+
/// <param name="ignoreAccessibility"></param>
232+
/// <returns></returns>
233+
internalabstractSemanticModelCreateSemanticModel(SyntaxTreesyntaxTree,boolignoreAccessibility);
234+
212235
/// <summary>
213236
/// Returns a new INamedTypeSymbol representing an error type with the given name and arity
214237
/// in the given optional container.
@@ -501,10 +524,15 @@ public bool ContainsSyntaxTree(SyntaxTree syntaxTree)
501524

502525
protectedabstractboolCommonContainsSyntaxTree(SyntaxTree?syntaxTree);
503526

527+
/// <summary>
528+
/// Optional semantic model provider for this compilation.
529+
/// </summary>
530+
internalSemanticModelProvider?SemanticModelProvider{get;}
531+
504532
/// <summary>
505533
/// The event queue that this compilation was created with.
506534
/// </summary>
507-
internalreadonlyAsyncQueue<CompilationEvent>?EventQueue;
535+
internalAsyncQueue<CompilationEvent>?EventQueue{get;}
508536

509537
#endregion
510538

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#nullable enable
6+
7+
namespaceMicrosoft.CodeAnalysis
8+
{
9+
/// <summary>
10+
/// Provides semantic models for syntax trees in a compilation.
11+
/// This provider can be attached to a compilation, see <see cref="Compilation.SemanticModelProvider"/>.
12+
/// </summary>
13+
internalabstractclassSemanticModelProvider
14+
{
15+
/// <summary>
16+
/// Gets a <see cref="SemanticModel"/> for the given <paramref name="tree"/> that belongs to the given <paramref name="compilation"/>.
17+
/// </summary>
18+
publicabstractSemanticModelGetSemanticModel(SyntaxTreetree,Compilationcompilation,boolignoreAccessibility=false);
19+
}
20+
}

‎src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,6 @@ internal static Diagnostic Create(DiagnosticInfo info)
347347
varsuppressMessageState=newSuppressMessageAttributeState(compilation);
348348
if(!suppressMessageState.IsDiagnosticSuppressed(
349349
this,
350-
getSemanticModel:(compilation,tree)=>compilation.GetSemanticModel(tree),
351350
outattribute))
352351
{
353352
attribute=null;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp