提交 b338bae8 编写于 作者: H Heejae Chang

made operation factory an instance factory and semantic model owns the factory.

上级 e047f24c
......@@ -34,6 +34,8 @@ internal abstract partial class MemberSemanticModel : CSharpSemanticModel
private readonly SyntaxTreeSemanticModel _parentSemanticModelOpt;
private readonly int _speculatedPosition;
private readonly CSharpOperationFactory _operationFactory;
protected MemberSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode root, Symbol memberSymbol, Binder rootBinder, SyntaxTreeSemanticModel parentSemanticModelOpt, int speculatedPosition)
{
Debug.Assert(compilation != null);
......@@ -48,6 +50,8 @@ protected MemberSemanticModel(CSharpCompilation compilation, CSharpSyntaxNode ro
this.RootBinder = rootBinder.WithAdditionalFlags(GetSemanticModelBinderFlags());
_parentSemanticModelOpt = parentSemanticModelOpt;
_speculatedPosition = speculatedPosition;
_operationFactory = new CSharpOperationFactory();
}
public override CSharpCompilation Compilation
......@@ -979,7 +983,7 @@ internal override IOperation GetOperationWorker(CSharpSyntaxNode node, GetOperat
break;
}
return CSharpOperationFactory.Create(result);
return _operationFactory.Create(result);
}
internal override SymbolInfo GetSymbolInfoWorker(CSharpSyntaxNode node, SymbolInfoOptions options, CancellationToken cancellationToken = default(CancellationToken))
......@@ -1542,7 +1546,7 @@ private static Binder GetQueryEnclosingBinder(int position, CSharpSyntaxNode sta
}
while (node != null);
done:
done:
return GetEnclosingBinderInternalWithinRoot(AdjustStartingNodeAccordingToNewRoot(startingNode, queryClause.Syntax),
position, queryClause.Binder, queryClause.Syntax);
}
......@@ -1936,7 +1940,7 @@ public override BoundStatement BindStatement(StatementSyntax node, DiagnosticBag
// _lazyGuardedSynthesizedStatementsMap
if (statement.WasCompilerGenerated)
{
_semanticModel.GuardedAddSynthesizedStatementToMap(node, statement);
_semanticModel.GuardedAddSynthesizedStatementToMap(node, statement);
}
return statement;
......
......@@ -492,6 +492,7 @@ private static bool IsSafeForReordering(BoundExpression expression, RefKind kind
}
internal static ImmutableArray<IArgument> MakeArgumentsInEvaluationOrder(
CSharpOperationFactory operationFactory,
Binder binder,
SyntaxNode syntax,
ImmutableArray<BoundExpression> arguments,
......@@ -517,19 +518,21 @@ private static bool IsSafeForReordering(BoundExpression expression, RefKind kind
if (CanSkipRewriting(arguments, methodOrIndexer, expanded, argsToParamsOpt, invokedAsExtensionMethod, out var isComReceiver))
{
{
// In this case, the invocation is not in expanded form and there's no named argument provided.
// So we just return list of arguments as is.
return arguments.ZipAsArray(methodOrIndexer.GetParameters(), (a, p) => CSharpOperationFactory.CreateArgumentOperation(ArgumentKind.Explicit, p, CSharpOperationFactory.Create(a)));
}
return arguments.ZipAsArray(methodOrIndexer.GetParameters(), (a, p) => CSharpOperationFactory.CreateArgumentOperation(ArgumentKind.Explicit, p, operationFactory.Create(a)));
}
return BuildArgumentsInEvaluationOrder(syntax,
return BuildArgumentsInEvaluationOrder(
operationFactory,
syntax,
methodOrIndexer,
optionalParametersMethod,
expanded,
argsToParamsOpt,
arguments,
binder);
expanded,
argsToParamsOpt,
arguments,
binder);
}
// temporariesBuilder will be null when factory is null.
......@@ -558,7 +561,7 @@ private static bool IsSafeForReordering(BoundExpression expression, RefKind kind
((MethodSymbol)methodOrIndexer).Parameters[0].Type as NamedTypeSymbol :
methodOrIndexer.ContainingType;
isComReceiver = (object)receiverNamedType != null && receiverNamedType.IsComImport;
isComReceiver = (object)receiverNamedType != null && receiverNamedType.IsComImport;
return rewrittenArguments.Length == methodOrIndexer.GetParameterCount() &&
argsToParamsOpt.IsDefault &&
......@@ -619,8 +622,8 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
// then we need to create a temporary as usual. The step that
// produces the parameter array will need to deal with that
// eventuality.
if (IsBeginningOfParamArray(p, a, expanded, arguments.Length, rewrittenArguments, argsToParamsOpt, out int paramArrayArgumentCount)
if (IsBeginningOfParamArray(p, a, expanded, arguments.Length, rewrittenArguments, argsToParamsOpt, out int paramArrayArgumentCount)
&& a + paramArrayArgumentCount == rewrittenArguments.Length)
{
return;
......@@ -643,6 +646,7 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
// This fills in the arguments and parameters arrays in evaluation order.
private static ImmutableArray<IArgument> BuildArgumentsInEvaluationOrder(
CSharpOperationFactory operationFactory,
SyntaxNode syntax,
Symbol methodOrIndexer,
MethodSymbol optionalParametersMethod,
......@@ -690,8 +694,8 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
argument = CreateParamArrayArgument(syntax, parameter.Type, paramArray.ToImmutableAndFree(), null, binder);
}
argumentsInEvaluationBuilder.Add(CSharpOperationFactory.CreateArgumentOperation(kind, parameter, CSharpOperationFactory.Create(argument)));
}
argumentsInEvaluationBuilder.Add(CSharpOperationFactory.CreateArgumentOperation(kind, parameter, operationFactory.Create(argument)));
}
// Collect parameters with missing arguments.
ArrayBuilder<ParameterSymbol> missingParametersBuilder = ArrayBuilder<ParameterSymbol>.GetInstance(parameters.Length);
......@@ -706,7 +710,7 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
processedParameters.Free();
// Finally, append default value as arguments.
AppendMissingOptionalArguments(syntax, methodOrIndexer, optionalParametersMethod, expanded, binder, missingParametersBuilder, argumentsInEvaluationBuilder);
AppendMissingOptionalArguments(operationFactory, syntax, methodOrIndexer, optionalParametersMethod, expanded, binder, missingParametersBuilder, argumentsInEvaluationBuilder);
missingParametersBuilder.Free();
......@@ -729,13 +733,13 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
numberOfParamArrayArguments = 0;
if (expanded && parameterIndex == parameterCount - 1)
{
{
int remainingArgument = argumentIndex + 1;
for (; remainingArgument < arguments.Length; ++remainingArgument)
{
int remainingParameter = (!argsToParamsOpt.IsDefault) ? argsToParamsOpt[remainingArgument] : remainingArgument;
if (remainingParameter != parameterCount - 1)
{
{
break;
}
}
......@@ -816,15 +820,15 @@ private static ImmutableArray<RefKind> GetRefKindsOrNull(ArrayBuilder<RefKind> r
}
private static BoundExpression CreateParamArrayArgument(SyntaxNode syntax,
TypeSymbol paramArrayType,
ImmutableArray<BoundExpression> arrayArgs,
TypeSymbol paramArrayType,
ImmutableArray<BoundExpression> arrayArgs,
LocalRewriter localRewriter,
Binder binder)
{
Debug.Assert(localRewriter == null ^ binder == null);
Debug.Assert(localRewriter == null ^ binder == null);
TypeSymbol int32Type = (localRewriter != null ? localRewriter._compilation : binder.Compilation).GetSpecialType(SpecialType.System_Int32);
BoundExpression arraySize = MakeLiteral(syntax, ConstantValue.Create(arrayArgs.Length), int32Type, localRewriter);
BoundExpression arraySize = MakeLiteral(syntax, ConstantValue.Create(arrayArgs.Length), int32Type, localRewriter);
return new BoundArrayCreation(
syntax,
......@@ -994,16 +998,18 @@ private static BoundExpression MakeLiteral(SyntaxNode syntax, ConstantValue cons
}
}
private static void AppendMissingOptionalArguments(SyntaxNode syntax,
private static void AppendMissingOptionalArguments(
CSharpOperationFactory operationFactory,
SyntaxNode syntax,
Symbol methodOrIndexer,
MethodSymbol optionalParametersMethod,
bool expanded,
bool expanded,
Binder binder,
ArrayBuilder<ParameterSymbol> missingParameters,
ArrayBuilder<IArgument> argumentsBuilder)
{
ImmutableArray<ParameterSymbol> parameters = methodOrIndexer.GetParameters();
ImmutableArray<ParameterSymbol> parametersOfOptionalParametersMethod = optionalParametersMethod.Parameters;
ImmutableArray<ParameterSymbol> parametersOfOptionalParametersMethod = optionalParametersMethod.Parameters;
foreach (ParameterSymbol parameter in missingParameters)
{
......@@ -1021,7 +1027,7 @@ private static BoundExpression MakeLiteral(SyntaxNode syntax, ConstantValue cons
// Create an empty array for omitted param array argument.
argument = CreateParamArrayArgument(syntax, parameterOfOptionalParametersMethod.Type, ImmutableArray<BoundExpression>.Empty, null, binder);
kind = ArgumentKind.ParamArray;
kind = ArgumentKind.ParamArray;
}
else
{
......@@ -1030,18 +1036,18 @@ private static BoundExpression MakeLiteral(SyntaxNode syntax, ConstantValue cons
var unusedDiagnostics = DiagnosticBag.GetInstance();
argument = GetDefaultParameterValue(syntax,
parameterOfOptionalParametersMethod,
enableCallerInfo: ThreeState.Unknown,
localRewriter: null,
binder: binder,
parameterOfOptionalParametersMethod,
enableCallerInfo: ThreeState.Unknown,
localRewriter: null,
binder: binder,
diagnostics: unusedDiagnostics);
kind = ArgumentKind.DefaultValue;
unusedDiagnostics.Free();
}
unusedDiagnostics.Free();
}
argumentsBuilder.Add(CSharpOperationFactory.CreateArgumentOperation(kind, parameter, CSharpOperationFactory.Create(argument)));
}
argumentsBuilder.Add(CSharpOperationFactory.CreateArgumentOperation(kind, parameter, operationFactory.Create(argument)));
}
}
private static SourceLocation GetCallerLocation(SyntaxNode syntax, ThreeState enableCallerInfo)
......@@ -1115,7 +1121,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
/// must be passed in, where 'callerMemberName' must not be null if 'parameter.IsCallerMemberName' is 'true'.
/// </summary>
private static BoundExpression GetDefaultParameterValue(
SyntaxNode syntax,
SyntaxNode syntax,
ParameterSymbol parameter,
ThreeState enableCallerInfo,
LocalRewriter localRewriter,
......@@ -1125,8 +1131,8 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
Debug.Assert(localRewriter == null ^ binder == null);
Debug.Assert(diagnostics != null);
bool isLowering;
CSharpCompilation compilation;
bool isLowering;
CSharpCompilation compilation;
if (localRewriter != null)
{
......@@ -1135,8 +1141,8 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
}
else
{
isLowering = false;
compilation = binder.Compilation;
isLowering = false;
compilation = binder.Compilation;
}
// TODO: Ideally, the enableCallerInfo parameter would be of just bool type with only 'true' and 'false' values, and all callers
......@@ -1161,7 +1167,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
if (parameter.IsCallerLineNumber && ((callerSourceLocation = GetCallerLocation(syntax, enableCallerInfo)) != null))
{
int line = callerSourceLocation.SourceTree.GetDisplayLineNumber(callerSourceLocation.SourceSpan);
BoundExpression lineLiteral = MakeLiteral(syntax, ConstantValue.Create(line), compilation.GetSpecialType(SpecialType.System_Int32), localRewriter);
if (parameterType.IsNullableType())
......@@ -1179,7 +1185,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
else
{
defaultValue = MakeConversionNode(lineLiteral, parameterType, @checked: false);
}
}
}
else if (parameter.IsCallerFilePath && ((callerSourceLocation = GetCallerLocation(syntax, enableCallerInfo)) != null))
{
......@@ -1246,20 +1252,20 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
}
}
else
{
memberName = binder.ContainingMember().GetMemberCallerName();
{
memberName = binder.ContainingMember().GetMemberCallerName();
}
BoundExpression memberNameLiteral = MakeLiteral(syntax, ConstantValue.Create(memberName), compilation.GetSpecialType(SpecialType.System_String), localRewriter);
defaultValue = MakeConversionNode(memberNameLiteral, parameterType, @checked: false);
}
else if (defaultConstantValue == ConstantValue.NotAvailable)
{
{
// There is no constant value given for the parameter in source/metadata.
if (parameterType.IsDynamic() || parameterType.SpecialType == SpecialType.System_Object)
{
// We have something like M([Optional] object x). We have special handling for such situations.
defaultValue = isLowering
defaultValue = isLowering
? localRewriter.GetDefaultParameterSpecial(syntax, parameter)
: GetDefaultParameterSpecialForIOperation(syntax, parameter, compilation, diagnostics);
}
......@@ -1293,7 +1299,7 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
syntax,
UnsafeGetNullableMethod(syntax, parameterType, SpecialMember.System_Nullable_T__ctor, compilation, diagnostics),
null,
defaultValue);
defaultValue);
}
else if (defaultConstantValue.IsNull || defaultConstantValue.IsBad)
{
......@@ -1314,19 +1320,19 @@ private BoundExpression GetDefaultParameterValue(SyntaxNode syntax, ParameterSym
BoundExpression MakeConversionNode(BoundExpression operand, TypeSymbol type, bool @checked, bool acceptFailingConversion = false)
{
if (isLowering)
{
{
return localRewriter.MakeConversionNode(operand, type, @checked, acceptFailingConversion);
}
else
{
{
return MakeConversionForIOperation(operand, type, syntax, compilation, diagnostics, @checked, acceptFailingConversion);
}
}
}
}
private BoundExpression GetDefaultParameterSpecial(SyntaxNode syntax, ParameterSymbol parameter)
{
BoundExpression defaultValue = GetDefaultParameterSpecialNoConversion(syntax, parameter, this._compilation);
BoundExpression defaultValue = GetDefaultParameterSpecialNoConversion(syntax, parameter, this._compilation);
return MakeConversionNode(defaultValue, parameter.Type, @checked: false);
}
......@@ -1375,7 +1381,7 @@ private static BoundExpression GetDefaultParameterSpecialNoConversion(SyntaxNode
// Type.Missing
var fieldSymbol = (FieldSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Type__Missing);
defaultValue = new BoundFieldAccess(syntax, null, fieldSymbol, ConstantValue.NotAvailable);
}
}
return defaultValue;
}
......
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
namespace Microsoft.CodeAnalysis.Semantics
{
internal static partial class CSharpOperationFactory
internal partial class CSharpOperationFactory
{
private static Optional<object> ConvertToOptional(ConstantValue value)
{
return value != null ? new Optional<object>(value.Value) : default(Optional<object>);
}
private static ImmutableArray<IOperation> ToStatements(BoundStatement statement)
private ImmutableArray<IOperation> ToStatements(BoundStatement statement)
{
BoundStatementList statementList = statement as BoundStatementList;
var statementList = statement as BoundStatementList;
if (statementList != null)
{
return statementList.Statements.SelectAsArray(n => Create(n));
......@@ -31,11 +29,9 @@ private static ImmutableArray<IOperation> ToStatements(BoundStatement statement)
return ImmutableArray.Create(Create(statement));
}
private static readonly ConditionalWeakTable<BoundIncrementOperator, ILiteralExpression> s_incrementValueMappings = new ConditionalWeakTable<BoundIncrementOperator, ILiteralExpression>();
private static ILiteralExpression CreateIncrementOneLiteralExpression(BoundIncrementOperator boundIncrementOperator)
private ILiteralExpression CreateIncrementOneLiteralExpression(BoundIncrementOperator boundIncrementOperator)
{
return s_incrementValueMappings.GetValue(boundIncrementOperator, (increment) =>
return _cache.GetValue(boundIncrementOperator, nameof(CreateIncrementOneLiteralExpression), (increment) =>
{
string text = increment.Syntax.ToString();
bool isInvalid = false;
......@@ -46,9 +42,6 @@ private static ILiteralExpression CreateIncrementOneLiteralExpression(BoundIncre
});
}
private static readonly ConditionalWeakTable<BoundExpression, IEnumerable<IArgument>> s_callToArgumentsMappings
= new ConditionalWeakTable<BoundExpression, IEnumerable<IArgument>>();
internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterSymbol parameter, IOperation value)
{
return new Argument(kind,
......@@ -59,10 +52,10 @@ internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterS
isInvalid: parameter == null || value.IsInvalid,
syntax: value.Syntax,
type: value.Type,
constantValue: default(Optional<object>));
constantValue: default);
}
private static ImmutableArray<IArgument> DeriveArguments(
private ImmutableArray<IArgument> DeriveArguments(
BoundExpression boundNode,
Binder binder,
Symbol methodOrIndexer,
......@@ -84,8 +77,8 @@ internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterS
return ImmutableArray<IArgument>.Empty;
}
return (ImmutableArray<IArgument>)s_callToArgumentsMappings.GetValue(
boundNode,
return _cache.GetValue(
boundNode, nameof(DeriveArguments),
(n) =>
{
//TODO: https://github.com/dotnet/roslyn/issues/18722
......@@ -99,6 +92,7 @@ internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterS
}
return LocalRewriter.MakeArgumentsInEvaluationOrder(
operationFactory: this,
binder: binder,
syntax: invocationSyntax,
arguments: boundArguments,
......@@ -110,7 +104,7 @@ internal static IArgument CreateArgumentOperation(ArgumentKind kind, IParameterS
});
}
private static ImmutableArray<IOperation> GetObjectCreationInitializers(BoundObjectCreationExpression expression)
private ImmutableArray<IOperation> GetObjectCreationInitializers(BoundObjectCreationExpression expression)
{
return BoundObjectCreationExpression.GetChildInitializers(expression.InitializerExpressionOpt).SelectAsArray(n => Create(n));
}
......@@ -170,25 +164,19 @@ private static ITypeSymbol GetArrayCreationElementType(BoundArrayCreation creati
return null;
}
private static readonly ConditionalWeakTable<BoundBlock, object> s_blockStatementsMappings =
new ConditionalWeakTable<BoundBlock, object>();
private static ImmutableArray<IOperation> GetBlockStatement(BoundBlock block)
private ImmutableArray<IOperation> GetBlockStatement(BoundBlock block)
{
// This is to filter out operations of kind None.
return (ImmutableArray<IOperation>)s_blockStatementsMappings.GetValue(block,
return _cache.GetValue(block, nameof(GetBlockStatement),
blockStatement =>
{
return blockStatement.Statements.Select(s => Create(s)).Where(s => s.Kind != OperationKind.None).ToImmutableArray();
});
}
private static readonly ConditionalWeakTable<BoundSwitchStatement, object> s_switchSectionsMappings =
new ConditionalWeakTable<BoundSwitchStatement, object>();
private static ImmutableArray<ISwitchCase> GetSwitchStatementCases(BoundSwitchStatement statement)
private ImmutableArray<ISwitchCase> GetSwitchStatementCases(BoundSwitchStatement statement)
{
return (ImmutableArray<ISwitchCase>)s_switchSectionsMappings.GetValue(statement,
return _cache.GetValue(statement, nameof(GetSwitchStatementCases),
switchStatement =>
{
return switchStatement.SwitchSections.SelectAsArray(switchSection =>
......@@ -238,33 +226,24 @@ private static BinaryOperationKind GetLabelEqualityKind(BoundSwitchLabel label)
return BinaryOperationKind.None;
}
private static readonly ConditionalWeakTable<BoundLocalDeclaration, object> s_variablesMappings =
new ConditionalWeakTable<BoundLocalDeclaration, object>();
private static ImmutableArray<IVariableDeclaration> GetVariableDeclarationStatementVariables(BoundLocalDeclaration decl)
private ImmutableArray<IVariableDeclaration> GetVariableDeclarationStatementVariables(BoundLocalDeclaration decl)
{
return (ImmutableArray<IVariableDeclaration>)s_variablesMappings.GetValue(decl,
declaration => ImmutableArray.Create<IVariableDeclaration>(
return _cache.GetValue(decl, nameof(GetVariableDeclarationStatementVariables),
declaration => ImmutableArray.Create(
OperationFactory.CreateVariableDeclaration(declaration.LocalSymbol, Create(declaration.InitializerOpt), declaration.Syntax)));
}
private static readonly ConditionalWeakTable<BoundMultipleLocalDeclarations, object> s_multiVariablesMappings =
new ConditionalWeakTable<BoundMultipleLocalDeclarations, object>();
private static ImmutableArray<IVariableDeclaration> GetVariableDeclarationStatementVariables(BoundMultipleLocalDeclarations decl)
private ImmutableArray<IVariableDeclaration> GetVariableMultipleDeclarationStatementVariables(BoundMultipleLocalDeclarations decl)
{
return (ImmutableArray<IVariableDeclaration>)s_multiVariablesMappings.GetValue(decl,
return _cache.GetValue(decl, nameof(GetVariableMultipleDeclarationStatementVariables),
multipleDeclarations =>
multipleDeclarations.LocalDeclarations.SelectAsArray(declaration =>
OperationFactory.CreateVariableDeclaration(declaration.LocalSymbol, Create(declaration.InitializerOpt), declaration.Syntax)));
}
private static readonly ConditionalWeakTable<BoundInterpolatedString, object> s_interpolatedStringExpressionMappings =
new ConditionalWeakTable<BoundInterpolatedString, object>();
private static ImmutableArray<IInterpolatedStringContent> GetInterpolatedStringExpressionParts(BoundInterpolatedString boundInterpolatedString)
private ImmutableArray<IInterpolatedStringContent> GetInterpolatedStringExpressionParts(BoundInterpolatedString boundInterpolatedString)
{
return (ImmutableArray<IInterpolatedStringContent>)s_interpolatedStringExpressionMappings.GetValue(boundInterpolatedString,
return _cache.GetValue(boundInterpolatedString, nameof(GetInterpolatedStringExpressionParts),
interpolatedString =>
interpolatedString.Parts.SelectAsArray(interpolatedStringContent => CreateBoundInterpolatedStringContentOperation(interpolatedStringContent)));
}
......
......@@ -100,6 +100,7 @@
<Compile Include="Operations\IOmittedArgumentExpression.cs" />
<Compile Include="Operations\IOperationWithChildren.cs" />
<Compile Include="Operations\Operation.cs" />
<Compile Include="Operations\OperationCache.cs" />
<Compile Include="Operations\OperationKind.cs" />
<Compile Include="Operations\IParameterInitializer.cs" />
<Compile Include="Operations\IParameterReferenceExpression.cs" />
......
// 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.Concurrent;
namespace Microsoft.CodeAnalysis
{
internal class OperationCache<TBoundNode>
{
private readonly ConcurrentDictionary<(TBoundNode key, string kind), object> _cache =
new ConcurrentDictionary<(TBoundNode key, string kind), object>(concurrencyLevel: 2, capacity: 10);
public TRet GetValue<TNode, TRet>(TNode key, Func<TNode, TRet> creator)
where TNode : TBoundNode
{
return GetValue(key, "Root", creator);
}
public TRet GetValue<TNode, TRet>(TNode key, string kind, Func<TNode, TRet> creator)
where TNode : TBoundNode
{
return (TRet)_cache.GetOrAdd((key, kind), kv => creator((TNode)kv.key));
}
}
}
......@@ -25,6 +25,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly _speculatedPosition As Integer
Private ReadOnly _ignoresAccessibility As Boolean
Private ReadOnly _operationFactory As VisualBasicOperationFactory
Friend Sub New(root As SyntaxNode, rootBinder As Binder, parentSemanticModelOpt As SyntaxTreeSemanticModel, speculatedPosition As Integer, Optional ignoreAccessibility As Boolean = False)
Debug.Assert(parentSemanticModelOpt Is Nothing OrElse Not parentSemanticModelOpt.IsSpeculativeSemanticModel, VBResources.ChainingSpeculativeModelIsNotSupported)
......@@ -33,6 +35,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
_rootBinder = SemanticModelBinder.Mark(rootBinder, ignoreAccessibility)
_parentSemanticModelOpt = parentSemanticModelOpt
_speculatedPosition = speculatedPosition
_operationFactory = New VisualBasicOperationFactory()
End Sub
Friend ReadOnly Property RootBinder As Binder
......@@ -800,7 +804,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
result = summary.LowestBoundNode
End Select
Return VisualBasicOperationFactory.Create(result)
Return _operationFactory.Create(result)
End Function
Friend Overrides Function GetExpressionTypeInfo(node As ExpressionSyntax, Optional cancellationToken As CancellationToken = Nothing) As VisualBasicTypeInfo
......
......@@ -5,7 +5,7 @@ Imports System.Runtime.CompilerServices
Imports Microsoft.CodeAnalysis.VisualBasic
Namespace Microsoft.CodeAnalysis.Semantics
Partial Friend NotInheritable Class VisualBasicOperationFactory
Partial Friend Class VisualBasicOperationFactory
Private Shared Function ConvertToOptional(value As ConstantValue) As [Optional](Of Object)
Return If(value Is Nothing, New [Optional](Of Object)(), New [Optional](Of Object)(value.Value))
End Function
......@@ -34,7 +34,7 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return OperationKind.AssignmentExpression
End Function
Private Shared Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, index As Integer) As IOperation
Private Function GetUserDefinedBinaryOperatorChild([operator] As BoundUserDefinedBinaryOperator, index As Integer) As IOperation
Dim child = Create(GetUserDefinedBinaryOperatorChildBoundNode([operator], index))
If child IsNot Nothing Then
Return child
......@@ -57,7 +57,7 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return GetChildOfBadExpressionBoundNode([operator].UnderlyingExpression, index)
End Function
Friend Shared Function DeriveArguments(boundArguments As ImmutableArray(Of BoundExpression), parameters As ImmutableArray(Of VisualBasic.Symbols.ParameterSymbol)) As ImmutableArray(Of IArgument)
Friend Function DeriveArguments(boundArguments As ImmutableArray(Of BoundExpression), parameters As ImmutableArray(Of VisualBasic.Symbols.ParameterSymbol)) As ImmutableArray(Of IArgument)
Dim argumentsLength As Integer = boundArguments.Length
Debug.Assert(argumentsLength = parameters.Length)
......@@ -69,13 +69,11 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return arguments.ToImmutableAndFree()
End Function
Private Shared ReadOnly s_argumentMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundExpression, IArgument)
Private Shared Function DeriveArgument(index As Integer, argument As BoundExpression, parameters As ImmutableArray(Of VisualBasic.Symbols.ParameterSymbol)) As IArgument
Private Function DeriveArgument(index As Integer, argument As BoundExpression, parameters As ImmutableArray(Of VisualBasic.Symbols.ParameterSymbol)) As IArgument
Select Case argument.Kind
Case BoundKind.ByRefArgumentWithCopyBack
Return s_argumentMappings.GetValue(
argument,
Return _cache.GetValue(
argument, NameOf(DeriveArgument),
Function(argumentValue)
Dim byRefArgument = DirectCast(argumentValue, BoundByRefArgumentWithCopyBack)
Dim parameter = parameters(index)
......@@ -92,8 +90,8 @@ Namespace Microsoft.CodeAnalysis.Semantics
constantValue:=Nothing)
End Function)
Case Else
Return s_argumentMappings.GetValue(
argument,
Return _cache.GetValue(
argument, NameOf(DeriveArgument),
Function(argumentValue)
Dim lastParameterIndex = parameters.Length - 1
If index = lastParameterIndex AndAlso ParameterIsParamArray(parameters(lastParameterIndex)) Then
......@@ -143,7 +141,7 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return If(parameter.IsParamArray AndAlso parameter.Type.Kind = SymbolKind.ArrayType, DirectCast(parameter.Type, VisualBasic.Symbols.ArrayTypeSymbol).IsSZArray, False)
End Function
Private Shared Function GetChildOfBadExpression(parent As BoundNode, index As Integer) As IOperation
Private Function GetChildOfBadExpression(parent As BoundNode, index As Integer) As IOperation
Dim child = Create(GetChildOfBadExpressionBoundNode(parent, index))
If child IsNot Nothing Then
Return child
......@@ -164,14 +162,12 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return Nothing
End Function
Private Shared Function GetObjectCreationInitializers(expression As BoundObjectCreationExpression) As ImmutableArray(Of IOperation)
Private Function GetObjectCreationInitializers(expression As BoundObjectCreationExpression) As ImmutableArray(Of IOperation)
Return If(expression.InitializerOpt IsNot Nothing, expression.InitializerOpt.Initializers.SelectAsArray(Function(n) Create(n)), ImmutableArray(Of IOperation).Empty)
End Function
Private Shared ReadOnly s_caseBlocksMappings As New ConditionalWeakTable(Of BoundSelectStatement, Object)
Private Shared Function GetSwitchStatementCases(statement As BoundSelectStatement) As ImmutableArray(Of ISwitchCase)
Dim cases = s_caseBlocksMappings.GetValue(statement,
Private Function GetSwitchStatementCases(statement As BoundSelectStatement) As ImmutableArray(Of ISwitchCase)
Dim cases = _cache.GetValue(statement, NameOf(GetSwitchStatementCases),
Function(boundSelect)
Return boundSelect.CaseBlocks.SelectAsArray(
Function(boundCaseBlock)
......@@ -199,7 +195,7 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return DirectCast(New SwitchCase(clauses, body, isInvalid, syntax, type:=Nothing, constantValue:=Nothing), ISwitchCase)
End Function)
End Function)
Return DirectCast(cases, ImmutableArray(Of ISwitchCase))
Return cases
End Function
Private Shared Function GetSingleValueCaseClauseValue(clause As BoundSimpleCaseClause) As BoundExpression
......@@ -252,11 +248,9 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return Nothing
End Function
Private Shared ReadOnly s_loopTopMappings As New ConditionalWeakTable(Of BoundForToStatement, Object)
Private Shared Function GetForLoopStatementBefore(boundForToStatement As BoundForToStatement) As ImmutableArray(Of IOperation)
Dim result = s_loopTopMappings.GetValue(
boundForToStatement,
Private Function GetForLoopStatementBefore(boundForToStatement As BoundForToStatement) As ImmutableArray(Of IOperation)
Dim result = _cache.GetValue(
boundForToStatement, NameOf(GetForLoopStatementBefore),
Function(boundFor)
Dim statements As ArrayBuilder(Of IOperation) = ArrayBuilder(Of IOperation).GetInstance()
......@@ -297,14 +291,12 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return statements.ToImmutableAndFree()
End Function)
Return DirectCast(result, ImmutableArray(Of IOperation))
Return result
End Function
Private Shared ReadOnly s_loopBottomMappings As New ConditionalWeakTable(Of BoundForToStatement, Object)
Private Shared Function GetForLoopStatementAtLoopBottom(boundForToStatement As BoundForToStatement) As ImmutableArray(Of IOperation)
Dim result = s_loopBottomMappings.GetValue(
boundForToStatement,
Private Function GetForLoopStatementAtLoopBottom(boundForToStatement As BoundForToStatement) As ImmutableArray(Of IOperation)
Dim result = _cache.GetValue(
boundForToStatement, NameOf(GetForLoopStatementAtLoopBottom),
Function(boundFor)
Dim statements As ArrayBuilder(Of IOperation) = ArrayBuilder(Of IOperation).GetInstance()
Dim operators As BoundForToUserDefinedOperators = boundFor.OperatorsOpt
......@@ -338,15 +330,13 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return statements.ToImmutableAndFree()
End Function)
Return DirectCast(result, ImmutableArray(Of IOperation))
Return result
End Function
Private Shared ReadOnly s_loopConditionMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundForToStatement, IOperation)
Private Shared Function GetForWhileUntilLoopStatmentCondition(boundForToStatement As BoundForToStatement) As IOperation
Return s_loopConditionMappings.GetValue(
boundForToStatement,
Function(boundFor)
Private Function GetForWhileUntilLoopStatmentCondition(boundForToStatement As BoundForToStatement) As IOperation
Return _cache.GetValue(
boundForToStatement, NameOf(GetForWhileUntilLoopStatmentCondition),
Function(boundFor) As IOperation
Dim operationValue = Create(boundFor.LimitValue)
Dim limitValue As IOperation =
If(boundFor.LimitValue.IsConstant,
......@@ -405,23 +395,19 @@ Namespace Microsoft.CodeAnalysis.Semantics
End Function)
End Function
Private Shared ReadOnly s_blockStatementsMappings As New System.Runtime.CompilerServices.ConditionalWeakTable(Of BoundBlock, Object)
Private Shared Function GetBlockStatementStatements(block As BoundBlock) As ImmutableArray(Of IOperation)
Private Function GetBlockStatementStatements(block As BoundBlock) As ImmutableArray(Of IOperation)
' This is to filter out operations of kind None.
Dim statements = s_blockStatementsMappings.GetValue(
block,
Dim statements = _cache.GetValue(
block, NameOf(GetBlockStatementStatements),
Function(boundBlock)
Return boundBlock.Statements.Select(Function(n) Create(n)).Where(Function(s) s.Kind <> OperationKind.None).ToImmutableArray()
End Function)
Return DirectCast(statements, ImmutableArray(Of IOperation))
Return statements
End Function
Private Shared ReadOnly s_variablesMappings As New ConditionalWeakTable(Of BoundDimStatement, Object)
Private Shared Function GetVariableDeclarationStatementVariables(statement As BoundDimStatement) As ImmutableArray(Of IVariableDeclaration)
Dim variables = s_variablesMappings.GetValue(
statement,
Private Function GetVariableDeclarationStatementVariables(statement As BoundDimStatement) As ImmutableArray(Of IVariableDeclaration)
Dim variables = _cache.GetValue(
statement, NameOf(GetVariableDeclarationStatementVariables),
Function(dimStatement)
Dim builder = ArrayBuilder(Of IVariableDeclaration).GetInstance()
For Each base In dimStatement.LocalDeclarations
......@@ -437,14 +423,12 @@ Namespace Microsoft.CodeAnalysis.Semantics
Return builder.ToImmutableAndFree()
End Function
)
Return DirectCast(variables, ImmutableArray(Of IVariableDeclaration))
Return variables
End Function
Private Shared ReadOnly s_variablesDeclMappings As New ConditionalWeakTable(Of BoundUsingStatement, VariableDeclarationStatement)
Private Shared Function GetUsingStatementDeclaration(boundUsingStatement As BoundUsingStatement) As IVariableDeclarationStatement
Return s_variablesDeclMappings.GetValue(
boundUsingStatement,
Private Function GetUsingStatementDeclaration(boundUsingStatement As BoundUsingStatement) As IVariableDeclarationStatement
Return _cache.GetValue(
boundUsingStatement, NameOf(GetUsingStatementDeclaration),
Function(boundUsing)
Dim declaration = If(boundUsing.ResourceList.IsDefaultOrEmpty,
ImmutableArray(Of IVariableDeclaration).Empty,
......@@ -458,12 +442,9 @@ Namespace Microsoft.CodeAnalysis.Semantics
End Function)
End Function
Private Shared ReadOnly s_expressionsMappings As New ConditionalWeakTable(Of BoundAddRemoveHandlerStatement, IEventAssignmentExpression)
Private Shared Function GetAddHandlerStatementExpression(handlerStatement As BoundAddHandlerStatement) As IOperation
Return s_expressionsMappings.GetValue(
handlerStatement,
Private Function GetAddHandlerStatementExpression(handlerStatement As BoundAddHandlerStatement) As IOperation
Return _cache.GetValue(
handlerStatement, NameOf(GetAddHandlerStatementExpression),
Function(statement)
Dim eventAccess As BoundEventAccess = TryCast(statement.EventAccess, BoundEventAccess)
Dim [event] As IEventSymbol = eventAccess?.EventSymbol
......@@ -474,10 +455,9 @@ Namespace Microsoft.CodeAnalysis.Semantics
End Function)
End Function
Private Shared Function GetRemoveStatementExpression(handlerStatement As BoundRemoveHandlerStatement) As IOperation
Return s_expressionsMappings.GetValue(
handlerStatement,
Private Function GetRemoveStatementExpression(handlerStatement As BoundRemoveHandlerStatement) As IOperation
Return _cache.GetValue(
handlerStatement, NameOf(GetRemoveStatementExpression),
Function(statement)
Dim eventAccess As BoundEventAccess = TryCast(statement.EventAccess, BoundEventAccess)
Dim [event] As IEventSymbol = eventAccess?.EventSymbol
......@@ -489,14 +469,12 @@ Namespace Microsoft.CodeAnalysis.Semantics
End Function)
End Function
Private Shared ReadOnly s_interpolatedStringExpressionMappings As New ConditionalWeakTable(Of BoundInterpolatedStringExpression, Object)()
Private Shared Function GetInterpolatedStringExpressionParts(boundInterpolatedString As BoundInterpolatedStringExpression) As ImmutableArray(Of IInterpolatedStringContent)
Return DirectCast(s_interpolatedStringExpressionMappings.GetValue(
boundInterpolatedString,
Private Function GetInterpolatedStringExpressionParts(boundInterpolatedString As BoundInterpolatedStringExpression) As ImmutableArray(Of IInterpolatedStringContent)
Return _cache.GetValue(
boundInterpolatedString, NameOf(GetInterpolatedStringExpressionParts),
Function(interpolatedString)
Return interpolatedString.Contents.SelectAsArray(Function(interpolatedStringContent) CreateBoundInterpolatedStringContentOperation(interpolatedStringContent))
End Function), ImmutableArray(Of IInterpolatedStringContent))
End Function)
End Function
Friend Class Helper
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册