| File: Compilation\SpeculativeSyntaxTreeSemanticModel.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// 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 System.Threading; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.CodeAnalysis.CSharp { /// <summary> /// Allows asking semantic questions about a tree of syntax nodes that did not appear in the original source code. /// Typically, an instance is obtained by a call to SemanticModel.TryGetSpeculativeSemanticModel. /// </summary> internal class SpeculativeSyntaxTreeSemanticModel : SyntaxTreeSemanticModel { private readonly SyntaxTreeSemanticModel _parentSemanticModel; private readonly CSharpSyntaxNode _root; private readonly Binder _rootBinder; private readonly int _position; private readonly SpeculativeBindingOption _bindingOption; public static SpeculativeSyntaxTreeSemanticModel Create(SyntaxTreeSemanticModel parentSemanticModel, TypeSyntax root, Binder rootBinder, int position, SpeculativeBindingOption bindingOption) { return CreateCore(parentSemanticModel, root, rootBinder, position, bindingOption); } public static SpeculativeSyntaxTreeSemanticModel Create(SyntaxTreeSemanticModel parentSemanticModel, CrefSyntax root, Binder rootBinder, int position) { return CreateCore(parentSemanticModel, root, rootBinder, position, bindingOption: SpeculativeBindingOption.BindAsTypeOrNamespace); } private static SpeculativeSyntaxTreeSemanticModel CreateCore(SyntaxTreeSemanticModel parentSemanticModel, CSharpSyntaxNode root, Binder rootBinder, int position, SpeculativeBindingOption bindingOption) { Debug.Assert(parentSemanticModel is SyntaxTreeSemanticModel); Debug.Assert(root != null); Debug.Assert(root is TypeSyntax || root is CrefSyntax); Debug.Assert(rootBinder != null); Debug.Assert(rootBinder.IsSemanticModelBinder); var speculativeModel = new SpeculativeSyntaxTreeSemanticModel(parentSemanticModel, root, rootBinder, position, bindingOption); return speculativeModel; } private SpeculativeSyntaxTreeSemanticModel(SyntaxTreeSemanticModel parentSemanticModel, CSharpSyntaxNode root, Binder rootBinder, int position, SpeculativeBindingOption bindingOption) : base(parentSemanticModel.Compilation, parentSemanticModel.SyntaxTree, root.SyntaxTree, parentSemanticModel.Options) { _parentSemanticModel = parentSemanticModel; _root = root; _rootBinder = rootBinder; _position = position; _bindingOption = bindingOption; } public override bool IsSpeculativeSemanticModel { get { return true; } } public override int OriginalPositionForSpeculation { get { return _position; } } public override CSharpSemanticModel ParentModel { get { return _parentSemanticModel; } } internal override CSharpSyntaxNode Root { get { return _root; } } internal override BoundNode Bind(Binder binder, CSharpSyntaxNode node, BindingDiagnosticBag diagnostics) { return _parentSemanticModel.Bind(binder, node, diagnostics); } internal override Binder GetEnclosingBinderInternal(int position) { return _rootBinder; } private SpeculativeBindingOption GetSpeculativeBindingOption(ExpressionSyntax node) { if (SyntaxFacts.IsInNamespaceOrTypeContext(node)) { return SpeculativeBindingOption.BindAsTypeOrNamespace; } return _bindingOption; } internal override SymbolInfo GetSymbolInfoWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken)) { var cref = node as CrefSyntax; if (cref != null) { return _parentSemanticModel.GetSpeculativeSymbolInfo(_position, cref, options); } var expression = (ExpressionSyntax)node; if ((options & SymbolInfoOptions.PreserveAliases) != 0) { var aliasSymbol = _parentSemanticModel.GetSpeculativeAliasInfo(_position, expression, this.GetSpeculativeBindingOption(expression)); return new SymbolInfo(aliasSymbol); } return _parentSemanticModel.GetSpeculativeSymbolInfo(_position, expression, this.GetSpeculativeBindingOption(expression)); } internal override CSharpTypeInfo GetTypeInfoWorker(CSharpSyntaxNode node, CancellationToken cancellationToken = default(CancellationToken)) { var expression = (ExpressionSyntax)node; return _parentSemanticModel.GetSpeculativeTypeInfoWorker(_position, expression, this.GetSpeculativeBindingOption(expression)); } } }