diff --git a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj index 513aa1e4f67eb26250c70ff350803682fcb956c3..ad682353572d8ed41e4a0332230c88af52c344bb 100644 --- a/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj +++ b/src/Compilers/CSharp/Portable/CSharpCodeAnalysis.csproj @@ -286,7 +286,7 @@ - + diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs index 77eb87269ec8e67df29c4b91e0f1f82e5f412d91..f1ecf6791e872114bcb9f1a13bd550ee016dee78 100644 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpDefinitionMap.cs @@ -37,23 +37,9 @@ internal sealed partial class CSharpDefinitionMap : DefinitionMap CSharp.MessageProvider.Instance; - protected override VariableSlotAllocator CreateSlotAllocator( - CSharpSymbolMatcher symbolMap, - Func syntaxMap, - IMethodSymbolInternal previousMethod, - DebugId methodId, - ImmutableArray previousLocals, - IReadOnlyDictionary> lambdaMap, - IReadOnlyDictionary closureMap, - string stateMachineTypeNameOpt, - int hoistedLocalSlotCount, - IReadOnlyDictionary hoistedLocalMap, - int awaiterSlotCount, - IReadOnlyDictionary awaiterMap) + protected override ILambdaSyntaxHelper GetLambdaSyntaxHelper() { - return new CSharpEncVariableSlotAllocator(symbolMap, syntaxMap, previousMethod, - methodId, previousLocals, lambdaMap, closureMap, stateMachineTypeNameOpt, - hoistedLocalSlotCount, hoistedLocalMap, awaiterSlotCount, awaiterMap); + return CSharpLambdaSyntaxHelper.Instance; } internal bool TryGetAnonymousTypeName(NamedTypeSymbol template, out string name, out int index) diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpEncVariableSlotAllocator.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpEncVariableSlotAllocator.cs deleted file mode 100644 index 8948ffa925a6fbeb5f141046a2c15d8751f8388d..0000000000000000000000000000000000000000 --- a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpEncVariableSlotAllocator.cs +++ /dev/null @@ -1,46 +0,0 @@ -// 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.Generic; -using System.Collections.Immutable; -using Microsoft.Cci; -using Microsoft.CodeAnalysis.CodeGen; -using Microsoft.CodeAnalysis.Emit; -using Microsoft.CodeAnalysis.Symbols; - -namespace Microsoft.CodeAnalysis.CSharp.Emit -{ - internal class CSharpEncVariableSlotAllocator : EncVariableSlotAllocator - { - public CSharpEncVariableSlotAllocator( - SymbolMatcher symbolMap, - Func syntaxMapOpt, - IMethodSymbolInternal previousTopLevelMethod, - DebugId methodId, - ImmutableArray previousLocals, - IReadOnlyDictionary> lambdaMapOpt, - IReadOnlyDictionary closureMapOpt, - string stateMachineTypeNameOpt, - int hoistedLocalSlotCount, - IReadOnlyDictionary - hoistedLocalSlotsOpt, int awaiterCount, IReadOnlyDictionary awaiterMapOpt) - : base(symbolMap, syntaxMapOpt, previousTopLevelMethod, methodId, - previousLocals, lambdaMapOpt, closureMapOpt, stateMachineTypeNameOpt, - hoistedLocalSlotCount, hoistedLocalSlotsOpt, awaiterCount, awaiterMapOpt) - { - } - - protected override SyntaxNode GetLambda(SyntaxNode lambdaOrLambdaBodySyntax) - { - return LambdaUtilities.GetLambda(lambdaOrLambdaBodySyntax); - } - - protected override SyntaxNode TryGetCorrespondingLambdaBody( - SyntaxNode previousLambdaSyntax, - SyntaxNode lambdaOrLambdaBodySyntax) - { - return LambdaUtilities.TryGetCorrespondingLambdaBody( - lambdaOrLambdaBodySyntax, previousLambdaSyntax); - } - } -} \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpLambdaSyntaxHelper.cs b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpLambdaSyntaxHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..22969160d27305558eea1f81dee3db4713e2a3bc --- /dev/null +++ b/src/Compilers/CSharp/Portable/Emitter/EditAndContinue/CSharpLambdaSyntaxHelper.cs @@ -0,0 +1,28 @@ +// 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 Microsoft.CodeAnalysis.Emit; + +namespace Microsoft.CodeAnalysis.CSharp.Emit +{ + internal class CSharpLambdaSyntaxHelper : ILambdaSyntaxHelper + { + public static readonly ILambdaSyntaxHelper Instance = new CSharpLambdaSyntaxHelper(); + + private CSharpLambdaSyntaxHelper() + { + } + + public SyntaxNode GetLambda(SyntaxNode lambdaOrLambdaBodySyntax) + { + return LambdaUtilities.GetLambda(lambdaOrLambdaBodySyntax); + } + + public SyntaxNode TryGetCorrespondingLambdaBody( + SyntaxNode previousLambdaSyntax, + SyntaxNode lambdaOrLambdaBodySyntax) + { + return LambdaUtilities.TryGetCorrespondingLambdaBody( + lambdaOrLambdaBodySyntax, previousLambdaSyntax); + } + } +} \ No newline at end of file diff --git a/src/Compilers/Core/Portable/CodeAnalysis.csproj b/src/Compilers/Core/Portable/CodeAnalysis.csproj index 324c47776bd754c5561cec2b9bab8eacd5cd0c81..c07387ffdafada5268ff8a090577f0e1a5e6aea9 100644 --- a/src/Compilers/Core/Portable/CodeAnalysis.csproj +++ b/src/Compilers/Core/Portable/CodeAnalysis.csproj @@ -53,6 +53,7 @@ + diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs index 32dc140fa257f9cbf9efbf5dd84c6d19360ef0d0..70d78109d6dc53cf6229ff93d7e716bd1fbffc98 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/DefinitionMap.cs @@ -303,7 +303,7 @@ internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline basel symbolMap = mapToMetadata; } - return CreateSlotAllocator( + return new EncVariableSlotAllocator( symbolMap, mappedMethod.SyntaxMap, mappedMethod.PreviousMethod, @@ -315,10 +315,11 @@ internal VariableSlotAllocator TryCreateVariableSlotAllocator(EmitBaseline basel hoistedLocalSlotCount, hoistedLocalMap, awaiterSlotCount, - awaiterMap); + awaiterMap, + GetLambdaSyntaxHelper()); } - protected abstract VariableSlotAllocator CreateSlotAllocator(TSymbolMatcher symbolMap, Func syntaxMap, IMethodSymbolInternal previousMethod, DebugId methodId, ImmutableArray previousLocals, IReadOnlyDictionary> lambdaMap, IReadOnlyDictionary closureMap, string stateMachineTypeNameOpt, int hoistedLocalSlotCount, IReadOnlyDictionary hoistedLocalMap, int awaiterSlotCount, IReadOnlyDictionary awaiterMap); + protected abstract ILambdaSyntaxHelper GetLambdaSyntaxHelper(); private void ReportMissingStateMachineAttribute(DiagnosticBag diagnostics, IMethodSymbolInternal method, string stateMachineAttributeFullName) { diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/EncVariableSlotAllocator.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/EncVariableSlotAllocator.cs index 823444caea07f80965109a1b404acab587c73341..a6c92ceb4275956bc83bd5a9b3aef155982a5e04 100644 --- a/src/Compilers/Core/Portable/Emit/EditAndContinue/EncVariableSlotAllocator.cs +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/EncVariableSlotAllocator.cs @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.Emit { - internal abstract class EncVariableSlotAllocator : VariableSlotAllocator + internal class EncVariableSlotAllocator : VariableSlotAllocator { // symbols: private readonly SymbolMatcher _symbolMap; @@ -36,7 +36,9 @@ internal abstract class EncVariableSlotAllocator : VariableSlotAllocator private readonly IReadOnlyDictionary> _lambdaMapOpt; // SyntaxOffset -> (Lambda Id, Closure Ordinal) private readonly IReadOnlyDictionary _closureMapOpt; // SyntaxOffset -> Id - protected EncVariableSlotAllocator( + private readonly ILambdaSyntaxHelper _lambdaSyntaxHelper; + + public EncVariableSlotAllocator( SymbolMatcher symbolMap, Func syntaxMapOpt, IMethodSymbolInternal previousTopLevelMethod, @@ -48,7 +50,8 @@ internal abstract class EncVariableSlotAllocator : VariableSlotAllocator int hoistedLocalSlotCount, IReadOnlyDictionary hoistedLocalSlotsOpt, int awaiterCount, - IReadOnlyDictionary awaiterMapOpt) + IReadOnlyDictionary awaiterMapOpt, + ILambdaSyntaxHelper lambdaSyntaxHelper) { Debug.Assert(symbolMap != null); Debug.Assert(previousTopLevelMethod != null); @@ -66,6 +69,7 @@ internal abstract class EncVariableSlotAllocator : VariableSlotAllocator _awaiterMapOpt = awaiterMapOpt; _lambdaMapOpt = lambdaMapOpt; _closureMapOpt = closureMapOpt; + _lambdaSyntaxHelper = lambdaSyntaxHelper; // Create a map from local info to slot. var previousLocalInfoToSlot = new Dictionary(); @@ -249,7 +253,9 @@ private bool TryGetPreviousLambdaSyntaxOffset(SyntaxNode lambdaOrLambdaBodySynta { // Syntax map contains mapping for lambdas, but not their bodies. // Map the lambda first and then determine the corresponding body. - var currentLambdaSyntax = isLambdaBody ? GetLambda(lambdaOrLambdaBodySyntax) : lambdaOrLambdaBodySyntax; + var currentLambdaSyntax = isLambdaBody + ? _lambdaSyntaxHelper.GetLambda(lambdaOrLambdaBodySyntax) + : lambdaOrLambdaBodySyntax; // no syntax map // => the source of the current method is the same as the source of the previous method @@ -265,7 +271,7 @@ private bool TryGetPreviousLambdaSyntaxOffset(SyntaxNode lambdaOrLambdaBodySynta SyntaxNode previousSyntax; if (isLambdaBody) { - previousSyntax = TryGetCorrespondingLambdaBody(previousLambdaSyntax, lambdaOrLambdaBodySyntax); + previousSyntax = _lambdaSyntaxHelper.TryGetCorrespondingLambdaBody(previousLambdaSyntax, lambdaOrLambdaBodySyntax); if (previousSyntax == null) { previousSyntaxOffset = 0; @@ -281,18 +287,6 @@ private bool TryGetPreviousLambdaSyntaxOffset(SyntaxNode lambdaOrLambdaBodySynta return true; } - protected abstract SyntaxNode GetLambda(SyntaxNode lambdaOrLambdaBodySyntax); - - /// - /// When invoked on a node that represents an anonymous function or a query clause [1] - /// with a of another anonymous function or a query clause of the same kind [2], - /// returns the body of the [1] that positionally corresponds to the specified . - /// - /// E.g. join clause declares left expression and right expression -- each of these expressions is a lambda body. - /// JoinClause1.GetCorrespondingLambdaBody(JoinClause2.RightExpression) returns JoinClause1.RightExpression. - /// - protected abstract SyntaxNode TryGetCorrespondingLambdaBody(SyntaxNode previousLambdaSyntax, SyntaxNode lambdaOrLambdaBodySyntax); - public override bool TryGetPreviousClosure(SyntaxNode scopeSyntax, out DebugId closureId) { int syntaxOffset; diff --git a/src/Compilers/Core/Portable/Emit/EditAndContinue/ILambdaHelper.cs b/src/Compilers/Core/Portable/Emit/EditAndContinue/ILambdaHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..4ab174f84f498a2a6d9ff7314812655f6750cd58 --- /dev/null +++ b/src/Compilers/Core/Portable/Emit/EditAndContinue/ILambdaHelper.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.CodeAnalysis.Emit +{ + internal interface ILambdaSyntaxHelper + { + SyntaxNode GetLambda(SyntaxNode lambdaOrLambdaBodySyntax); + + /// + /// When invoked on a node that represents an anonymous function or a query clause [1] + /// with a of another anonymous function or a query clause of the same kind [2], + /// returns the body of the [1] that positionally corresponds to the specified . + /// + /// E.g. join clause declares left expression and right expression -- each of these expressions is a lambda body. + /// JoinClause1.GetCorrespondingLambdaBody(JoinClause2.RightExpression) returns JoinClause1.RightExpression. + /// + SyntaxNode TryGetCorrespondingLambdaBody(SyntaxNode previousLambdaSyntax, SyntaxNode lambdaOrLambdaBodySyntax); + } +} \ No newline at end of file diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicDefinitionMap.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicDefinitionMap.vb index af626e844addf66159bf8b0a1bbc8a78389d257d..4e65122fe307dc1af6358560fafd48c79a80cc09 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicDefinitionMap.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicDefinitionMap.vb @@ -39,10 +39,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit End Get End Property - Protected Overrides Function CreateSlotAllocator(symbolMap As VisualBasicSymbolMatcher, syntaxMap As Func(Of SyntaxNode, SyntaxNode), previousMethod As IMethodSymbolInternal, methodId As DebugId, previousLocals As ImmutableArray(Of EncLocalInfo), lambdaMap As IReadOnlyDictionary(Of Integer, KeyValuePair(Of DebugId, Integer)), closureMap As IReadOnlyDictionary(Of Integer, DebugId), stateMachineTypeNameOpt As String, hoistedLocalSlotCount As Integer, hoistedLocalMap As IReadOnlyDictionary(Of EncHoistedLocalInfo, Integer), awaiterSlotCount As Integer, awaiterMap As IReadOnlyDictionary(Of ITypeReference, Integer)) As VariableSlotAllocator - Return New VisualBasicEncVariableSlotAllocator(symbolMap, syntaxMap, previousMethod, - methodId, previousLocals, lambdaMap, closureMap, stateMachineTypeNameOpt, - hoistedLocalSlotCount, hoistedLocalMap, awaiterSlotCount, awaiterMap) + Protected Overrides Function GetLambdaSyntaxHelper() As ILambdaSyntaxHelper + Return VisualBasicLambdaSyntaxHelper.Instance End Function Friend Function TryGetAnonymousTypeName(template As NamedTypeSymbol, ByRef name As String, ByRef index As Integer) As Boolean diff --git a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicEncVariableSlotAllocator.vb b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicEncVariableSlotAllocator.vb index 111375007f6c926218a7351cf348ea8e5fa3b459..a5c4b9b80ca1de03e423f46d66b49701d5983ad5 100644 --- a/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicEncVariableSlotAllocator.vb +++ b/src/Compilers/VisualBasic/Portable/Emit/EditAndContinue/VisualBasicEncVariableSlotAllocator.vb @@ -7,31 +7,19 @@ Imports Microsoft.CodeAnalysis.Emit Imports Microsoft.CodeAnalysis.Symbols Namespace Microsoft.CodeAnalysis.VisualBasic.Emit - Friend Class VisualBasicEncVariableSlotAllocator - Inherits EncVariableSlotAllocator + Friend Class VisualBasicLambdaSyntaxHelper + Implements ILambdaSyntaxHelper - Public Sub New(symbolMap As SymbolMatcher, - syntaxMapOpt As Func(Of SyntaxNode, SyntaxNode), - previousTopLevelMethod As IMethodSymbolInternal, - methodId As DebugId, - previousLocals As ImmutableArray(Of EncLocalInfo), - lambdaMapOpt As IReadOnlyDictionary(Of Integer, KeyValuePair(Of DebugId, Integer)), - closureMapOpt As IReadOnlyDictionary(Of Integer, DebugId), - stateMachineTypeNameOpt As String, - hoistedLocalSlotCount As Integer, - hoistedLocalSlotsOpt As IReadOnlyDictionary(Of EncHoistedLocalInfo, Integer), - awaiterCount As Integer, - awaiterMapOpt As IReadOnlyDictionary(Of ITypeReference, Integer)) - MyBase.New(symbolMap, syntaxMapOpt, previousTopLevelMethod, methodId, - previousLocals, lambdaMapOpt, closureMapOpt, stateMachineTypeNameOpt, - hoistedLocalSlotCount, hoistedLocalSlotsOpt, awaiterCount, awaiterMapOpt) + Public Shared ReadOnly Instance As ILambdaSyntaxHelper = New VisualBasicLambdaSyntaxHelper() + + Private Sub New() End Sub - Protected Overrides Function GetLambda(lambdaOrLambdaBodySyntax As SyntaxNode) As SyntaxNode + Public Function GetLambda(lambdaOrLambdaBodySyntax As SyntaxNode) As SyntaxNode Implements ILambdaSyntaxHelper.GetLambda Return LambdaUtilities.GetLambda(lambdaOrLambdaBodySyntax) End Function - Protected Overrides Function TryGetCorrespondingLambdaBody(previousLambdaSyntax As SyntaxNode, lambdaOrLambdaBodySyntax As SyntaxNode) As SyntaxNode + Public Function TryGetCorrespondingLambdaBody(previousLambdaSyntax As SyntaxNode, lambdaOrLambdaBodySyntax As SyntaxNode) As SyntaxNode Implements ILambdaSyntaxHelper.TryGetCorrespondingLambdaBody Return LambdaUtilities.GetCorrespondingLambdaBody(lambdaOrLambdaBodySyntax, previousLambdaSyntax) End Function End Class