diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 24f3baba16a7c980de6b0f7088a2829731fcdb3f..1492dfcf82f9f8473b78307655e519899387287f 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -474,11 +474,6 @@ internal virtual IOperation GetOperationWorker(CSharpSyntaxNode node, Cancellati return null; } - internal override IOperation CloneOperationCore(IOperation operation) - { - return CSharpOperationCloner.Instance.Visit(operation); - } - #region GetSymbolInfo /// diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationCloner.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationCloner.cs deleted file mode 100644 index 5ac0dd30a9e306c1e89bc5e0911c00f852818b07..0000000000000000000000000000000000000000 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationCloner.cs +++ /dev/null @@ -1,11 +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 Microsoft.CodeAnalysis.Operations; - -namespace Microsoft.CodeAnalysis.CSharp -{ - internal class CSharpOperationCloner : OperationCloner - { - public static OperationCloner Instance { get; } = new CSharpOperationCloner(); - } -} diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 481c2f86093fd34fc59e7070b77b641e9814eac6..0611572d8223d2206ae1d8b002e7f657971c888d 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -36,7 +36,7 @@ public IOperation Create(BoundNode boundNode) // always return cloned one if (boundNode.Kind == BoundKind.ImplicitReceiver) { - return _semanticModel.CloneOperation(CreateInternal(boundNode)); + return OperationCloner.CloneOperation(CreateInternal(boundNode)); } return _cache.GetOrAdd(boundNode, n => CreateInternal(n)); diff --git a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs index 6fbc98d0b336aac73b228030a50aee99aeda76d9..b1ebb58fdcbce8e398f1ed5d6b3f8593f7d6e1eb 100644 --- a/src/Compilers/Core/Portable/Compilation/SemanticModel.cs +++ b/src/Compilers/Core/Portable/Compilation/SemanticModel.cs @@ -86,13 +86,6 @@ public IOperation GetOperation(SyntaxNode node, CancellationToken cancellationTo protected abstract IOperation GetOperationCore(SyntaxNode node, CancellationToken cancellationToken); - /// - /// Deep Clone given IOperation - /// - internal T CloneOperation(T operation) where T : IOperation => (T)CloneOperationCore(operation); - - internal abstract IOperation CloneOperationCore(IOperation operation); - /// /// Returns true if this is a SemanticModel that ignores accessibility rules when answering semantic questions. /// diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index 228345de8f24a1e5d9f0e69bfd2bc11a2e5a735d..d6118f0641b506d202be52092dc081fa2c5b27e6 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -1,13 +1,24 @@ // 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.Immutable; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Operations { - internal abstract class OperationCloner : OperationVisitor + internal sealed class OperationCloner : OperationVisitor { - protected T Visit(T node) where T : IOperation + private static readonly Lazy _lazyInstance = new Lazy(() => new OperationCloner()); + + /// + /// Deep clone given IOperation + /// + public static T CloneOperation(T operation) where T : IOperation + { + return _lazyInstance.Value.Visit(operation); + } + + private T Visit(T node) where T : IOperation { return (T)Visit(node, argument: null); } diff --git a/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb b/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb index e1705d90fcc35a56a4683df98c61c42afa6523ad..13ffbe720c1c7731e412d39cb1be9128b1c790cc 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/SemanticModel.vb @@ -143,10 +143,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return Nothing End Function - Friend Overrides Function CloneOperationCore(operation As IOperation) As IOperation - Return VisualBasicOperationCloner.Instance.Visit(operation) - End Function - ''' ''' Returns what symbol(s), if any, the given expression syntax bound to in the program. ''' diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationCloner.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationCloner.vb deleted file mode 100644 index b1b2a6bdbe73a764e4962fc5e29dbdd17d3980eb..0000000000000000000000000000000000000000 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationCloner.vb +++ /dev/null @@ -1,10 +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. -Imports Microsoft.CodeAnalysis.Operations - -Namespace Microsoft.CodeAnalysis.VisualBasic - Friend Class VisualBasicOperationCloner - Inherits OperationCloner - - Public Shared ReadOnly Property Instance As OperationCloner = New VisualBasicOperationCloner() - End Class -End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 3edd0a5bebe0af78c37e7d5f11056c048528b69e..b2a116d019ecba20cf90cf7c271cc1cda03ae405 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -32,7 +32,7 @@ Namespace Microsoft.CodeAnalysis.Operations ' since same bound node appears in multiple places in the tree ' we can't use bound node to operation map. ' for now, we will just create new operation and return cloned - Return _semanticModel.CloneOperation(CreateInternal(boundNode)) + Return OperationCloner.CloneOperation(CreateInternal(boundNode)) End If ' A BoundUserDefined conversion is always the operand of a BoundConversion, and is handled diff --git a/src/Test/Utilities/Portable/CommonTestBase.cs b/src/Test/Utilities/Portable/CommonTestBase.cs index fef4e561410198a0fc6dad78233a4fd8bbbeb1d1..b794f06ee64d85cb9800894d1335c6af72e999de 100644 --- a/src/Test/Utilities/Portable/CommonTestBase.cs +++ b/src/Test/Utilities/Portable/CommonTestBase.cs @@ -618,7 +618,7 @@ internal static void VerifyClone(SemanticModel model) continue; } - var clonedOperation = model.CloneOperation(operation); + var clonedOperation = OperationCloner.CloneOperation(operation); // check whether cloned IOperation is same as original one var original = OperationTreeVerifier.GetOperationTree(model.Compilation, operation);