/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/Compilation/InitializerSemanticModel.cs
290 строк
13 KB
Maryam Ariyan
Using Nullable Disabled semantic model to compute semantic classification (#71036)
27 фев 2024, 05:06
Не верифицирован
27 фев 2024, 05:06
662557c
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp { /// <summary> /// A binding for a field initializer, property initializer, constructor /// initializer, or a parameter default value. /// Represents the result of binding a value expression rather than a /// block (for that, use a <see cref="MethodBodySemanticModel"/>). /// </summary> internal sealed class InitializerSemanticModel : MemberSemanticModel { // create a SemanticModel for: // (a) A true field initializer (field = value) of a named type (incl. Enums) OR // (b) A parameter default value internal InitializerSemanticModel(CSharpSyntaxNode syntax, Symbol symbol, Binder rootBinder, PublicSemanticModel containingPublicSemanticModel, ImmutableDictionary<Symbol, Symbol> parentRemappedSymbolsOpt = null) : base(syntax, symbol, rootBinder, containingPublicSemanticModel, parentRemappedSymbolsOpt) { Debug.Assert(!(syntax is ConstructorInitializerSyntax || syntax is PrimaryConstructorBaseTypeSyntax)); } /// <summary> /// Creates a SemanticModel for a true field initializer (field = value) of a named type (incl. Enums). /// </summary> internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, CSharpSyntaxNode syntax, FieldSymbol fieldSymbol, Binder rootBinder) { Debug.Assert(containingSemanticModel != null); Debug.Assert(syntax.IsKind(SyntaxKind.VariableDeclarator) || syntax.IsKind(SyntaxKind.EnumMemberDeclaration)); return new InitializerSemanticModel(syntax, fieldSymbol, rootBinder, containingSemanticModel); } /// <summary> /// Creates a SemanticModel for an autoprop initializer of a named type /// </summary> internal static InitializerSemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, CSharpSyntaxNode syntax, PropertySymbol propertySymbol, Binder rootBinder) { Debug.Assert(containingSemanticModel != null); Debug.Assert(syntax.IsKind(SyntaxKind.PropertyDeclaration)); return new InitializerSemanticModel(syntax, propertySymbol, rootBinder, containingSemanticModel); } /// <summary> /// Creates a SemanticModel for a parameter default value. /// </summary> internal static InitializerSemanticModel Create(PublicSemanticModel containingSemanticModel, ParameterSyntax syntax, ParameterSymbol parameterSymbol, Binder rootBinder, ImmutableDictionary<Symbol, Symbol> parentRemappedSymbolsOpt) { Debug.Assert(containingSemanticModel != null); return new InitializerSemanticModel(syntax, parameterSymbol, rootBinder, containingSemanticModel, parentRemappedSymbolsOpt: parentRemappedSymbolsOpt); } /// <summary> /// Creates a speculative SemanticModel for an initializer node (field initializer, constructor initializer, or parameter default value) /// that did not appear in the original source code. /// </summary> internal static SpeculativeSemanticModelWithMemberModel CreateSpeculative(SyntaxTreeSemanticModel parentSemanticModel, Symbol owner, EqualsValueClauseSyntax syntax, Binder rootBinder, ImmutableDictionary<Symbol, Symbol> parentRemappedSymbolsOpt, int position) { return new SpeculativeSemanticModelWithMemberModel(parentSemanticModel, position, owner, syntax, rootBinder, parentRemappedSymbolsOpt); } protected internal override CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNode node) { return IsBindableInitializer(node) ? node : base.GetBindableSyntaxNode(node); } internal override BoundNode GetBoundRoot() { CSharpSyntaxNode rootSyntax = this.Root; switch (rootSyntax.Kind()) { case SyntaxKind.VariableDeclarator: rootSyntax = ((VariableDeclaratorSyntax)rootSyntax).Initializer; break; case SyntaxKind.Parameter: rootSyntax = ((ParameterSyntax)rootSyntax).Default; break; case SyntaxKind.EqualsValueClause: rootSyntax = ((EqualsValueClauseSyntax)rootSyntax); break; case SyntaxKind.EnumMemberDeclaration: rootSyntax = ((EnumMemberDeclarationSyntax)rootSyntax).EqualsValue; break; case SyntaxKind.PropertyDeclaration: rootSyntax = ((PropertyDeclarationSyntax)rootSyntax).Initializer; break; default: throw ExceptionUtilities.UnexpectedValue(rootSyntax.Kind()); } return GetUpperBoundNode(GetBindableSyntaxNode(rootSyntax)); } internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, BindingDiagnosticBag diagnostics) { EqualsValueClauseSyntax equalsValue = null; switch (node.Kind()) { case SyntaxKind.EqualsValueClause: equalsValue = (EqualsValueClauseSyntax)node; break; case SyntaxKind.VariableDeclarator: equalsValue = ((VariableDeclaratorSyntax)node).Initializer; break; case SyntaxKind.PropertyDeclaration: equalsValue = ((PropertyDeclarationSyntax)node).Initializer; break; case SyntaxKind.Parameter: equalsValue = ((ParameterSyntax)node).Default; break; case SyntaxKind.EnumMemberDeclaration: equalsValue = ((EnumMemberDeclarationSyntax)node).EqualsValue; break; } if (equalsValue != null) { return BindEqualsValue(binder, equalsValue, diagnostics); } return base.Bind(binder, node, diagnostics); } private BoundEqualsValue BindEqualsValue(Binder binder, EqualsValueClauseSyntax equalsValue, BindingDiagnosticBag diagnostics) { switch (this.MemberSymbol.Kind) { case SymbolKind.Field: { var field = (FieldSymbol)this.MemberSymbol; var enumField = field as SourceEnumConstantSymbol; if ((object)enumField != null) { return binder.BindEnumConstantInitializer(enumField, equalsValue, diagnostics); } else { return binder.BindFieldInitializer(field, equalsValue, diagnostics); } } case SymbolKind.Property: { var property = (SourcePropertySymbol)this.MemberSymbol; BoundFieldEqualsValue result = binder.BindFieldInitializer(property.BackingField, equalsValue, diagnostics); return new BoundPropertyEqualsValue(result.Syntax, property, result.Locals, result.Value); } case SymbolKind.Parameter: { var parameter = (ParameterSymbol)this.MemberSymbol; return binder.BindParameterDefaultValue( equalsValue, parameter, diagnostics, out _); } default: throw ExceptionUtilities.UnexpectedValue(this.MemberSymbol.Kind); } } private bool IsBindableInitializer(CSharpSyntaxNode node) { // If we are being asked to bind the equals clause (the "=1" part of "double x=1,y=2;"), // that's our root and we know how to bind that thing even if it is not an // expression or a statement. switch (node.Kind()) { case SyntaxKind.EqualsValueClause: return this.Root == node || /*enum or parameter initializer*/ this.Root == node.Parent /*field initializer*/; default: return false; } } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, EqualsValueClauseSyntax initializer, out PublicSemanticModel speculativeModel) { var binder = this.GetEnclosingBinder(position); if (binder == null) { speculativeModel = null; return false; } binder = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder); speculativeModel = CreateSpeculative(parentModel, this.MemberSymbol, initializer, binder, GetRemappedSymbols(), position); return true; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, PrimaryConstructorBaseTypeSyntax constructorInitializer, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, BaseMethodDeclarationSyntax method, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out PublicSemanticModel speculativeModel) { speculativeModel = null; return false; } protected override BoundNode RewriteNullableBoundNodesWithSnapshots( BoundNode boundRoot, Binder binder, DiagnosticBag diagnostics, bool createSnapshots, out NullableWalker.SnapshotManager snapshotManager, ref ImmutableDictionary<Symbol, Symbol> remappedSymbols) { // https://github.com/dotnet/roslyn/issues/46424 // Bind and analyze preceding field initializers in order to give an accurate initial nullable state. return NullableWalker.AnalyzeAndRewrite(Compilation, MemberSymbol, boundRoot, binder, initialState: null, diagnostics, createSnapshots, out snapshotManager, ref remappedSymbols); } protected override void AnalyzeBoundNodeNullability(BoundNode boundRoot, Binder binder, DiagnosticBag diagnostics, bool createSnapshots) { NullableWalker.AnalyzeWithoutRewrite(Compilation, MemberSymbol, boundRoot, binder, diagnostics, createSnapshots); } #nullable enable protected override bool IsNullableAnalysisEnabledCore() { switch (MemberSymbol.Kind) { case SymbolKind.Field: case SymbolKind.Property: Debug.Assert(MemberSymbol.ContainingType is SourceMemberContainerTypeSymbol); return MemberSymbol.ContainingType is SourceMemberContainerTypeSymbol type && type.IsNullableEnabledForConstructorsAndInitializers(useStatic: MemberSymbol.IsStatic); case SymbolKind.Parameter: return SourceComplexParameterSymbolBase.GetDefaultValueSyntaxForIsNullableAnalysisEnabled(Root as ParameterSyntax) is { } value && Compilation.IsNullableAnalysisEnabledIn(value); default: throw ExceptionUtilities.UnexpectedValue(MemberSymbol.Kind); } } } }