diff --git a/build/Targets/Packages.props b/build/Targets/Packages.props index 078b18b4a32dd..1a70204d60e87 100644 --- a/build/Targets/Packages.props +++ b/build/Targets/Packages.props @@ -8,7 +8,7 @@ 8.0.1 8.0.0 0.9.2 - 3.0.0-unstable0090 + 3.0.0 0.22.0 0.2.0 1.0.0 @@ -106,6 +106,7 @@ 12.1.30328 14.3.25407 15.0.26606-alpha + 15.0.26606 8.0.50727 9.0.30729 15.0.26606-alpha @@ -231,4 +232,4 @@ 1.0.41 - + \ No newline at end of file diff --git a/build/config/SignToolData.json b/build/config/SignToolData.json index 1d6bfc3ed7269..a79c0812b76a5 100644 --- a/build/config/SignToolData.json +++ b/build/config/SignToolData.json @@ -102,7 +102,7 @@ "Vsix\\VisualStudioSetup.Next\\Roslyn.VisualStudio.Setup.Next.vsix", "Vsix\\VisualStudioSetup\\Roslyn.VisualStudio.Setup.vsix", "Vsix\\Roslyn\\RoslynDeployment.vsix", - "Vsix\\Templates\\Roslyn Templates\\Release\\Roslyn SDK.vsix" + "Vsix\\Templates\\Roslyn SDK.vsix" ] } ], diff --git a/build/scripts/run_perf.ps1 b/build/scripts/run_perf.ps1 index 5bca5dcfcabe4..4aa558a7e7f40 100644 --- a/build/scripts/run_perf.ps1 +++ b/build/scripts/run_perf.ps1 @@ -16,7 +16,7 @@ Invoke-WebRequest -Uri http://dotnetci.blob.core.windows.net/roslyn-perf/cpc.zip [Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null [IO.Compression.ZipFile]::ExtractToDirectory('cpc.zip', $CPCLocation) -./build/scripts/cibuild.ps1 -release -testPerfRun +./build/scripts/cibuild.cmd -release -testPerfRun if ( -not $? ) { diff --git a/netci.groovy b/netci.groovy index 46ac6eb09bcde..e69bbaf1373dc 100644 --- a/netci.groovy +++ b/netci.groovy @@ -226,7 +226,7 @@ commitPullList.each { isPr -> def triggerPhraseOnly = false def triggerPhraseExtra = "" - Utilities.setMachineAffinity(myJob, 'Windows_NT', 'latest-dev15-3-preview7') + Utilities.setMachineAffinity(myJob, 'Windows_NT', 'latest-dev15-3') Utilities.addXUnitDotNETResults(myJob, '**/xUnitResults/*.xml') addRoslynJob(myJob, jobName, branchName, isPr, triggerPhraseExtra, triggerPhraseOnly) } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index b2ee2024f606f..9492de04d8f01 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -627,15 +627,14 @@ private static bool HasApplicableConditionalMethod(OverloadResolutionResult + /// Looks up a localized string similar to Cannot pass argument with dynamic type to generic local function '{0}' with inferred type arguments.. + /// + internal static string ERR_DynamicLocalFunctionTypeParameter { + get { + return ResourceManager.GetString("ERR_DynamicLocalFunctionTypeParameter", resourceCulture); + } + } + /// /// Looks up a localized string similar to One or more types required to compile a dynamic expression cannot be found. Are you missing a reference?. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 96ca274ec8e9f..d34a38358f788 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5111,4 +5111,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ {0} is not a valid C# conversion expression + + Cannot pass argument with dynamic type to generic local function '{0}' with inferred type arguments. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index db7e38ebf5ef0..5275822f95b00 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1496,6 +1496,7 @@ internal enum ErrorCode #region diagnostics introduced for C# 7.2 ERR_FeatureNotAvailableInVersion7_2 = 8320, WRN_UnreferencedLocalFunction = 8321, + ERR_DynamicLocalFunctionTypeParameter = 8322, #endregion diagnostics introduced for C# 7.2 } } diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs index 98a3179932f70..216cca9ee6d9e 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.Analysis.cs @@ -246,9 +246,13 @@ private void InlineThisOnlyEnvironments() } else { - // Class-based 'this' closures can move member functions - // to the top-level type and environments which capture - // the 'this' environment can capture 'this' directly + // Class-based 'this' closures can move member functions to + // the top-level type and environments which capture the 'this' + // environment can capture 'this' directly. + // Note: the top-level type is treated as the initial containing + // environment, so by removing the 'this' environment, all + // nested environments which captured a pointer to the 'this' + // environment will now capture 'this' RemoveEnv(); VisitClosures(ScopeTree, (scope, closure) => { @@ -257,35 +261,6 @@ private void InlineThisOnlyEnvironments() closure.ContainingEnvironmentOpt = null; } }); - - // Find all environments in the scope below that could - // capture the parent. If there are any, add 'this' to - // the list of captured variables and remove the parent - // link - VisitFirstLevelScopes(ScopeTree); - void VisitFirstLevelScopes(Scope scope) - { - var classEnvs = scope.DeclaredEnvironments.Where(e => !e.IsStruct); - if (classEnvs.IsEmpty()) - { - // Keep looking for nested environments - foreach (var nested in scope.NestedScopes) - { - VisitFirstLevelScopes(nested); - } - } - else - { - foreach (var declEnv in classEnvs) - { - if (declEnv.CapturesParent) - { - declEnv.CapturedVariables.Insert(0, thisParam); - declEnv.CapturesParent = false; - } - } - } - } } void RemoveEnv() diff --git a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs index 1e4c9b4c98d11..9a8c3dc5de783 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LambdaRewriter/LambdaRewriter.cs @@ -187,8 +187,7 @@ public MappedLocalFunction(SynthesizedLambdaMethod symbol, ClosureKind closureKi _assignLocals = assignLocals; _currentTypeParameters = method.TypeParameters; _currentLambdaBodyTypeMap = TypeMap.Empty; - _innermostFramePointer = null; - _currentFrameThis = thisParameterOpt; + _innermostFramePointer = _currentFrameThis = thisParameterOpt; _framePointers[thisType] = thisParameterOpt; _seenBaseCall = method.MethodKind != MethodKind.Constructor; // only used for ctors _synthesizedFieldNameIdDispenser = 1; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs index 075e417394dde..89e9ed6096d24 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Conversion.cs @@ -650,16 +650,8 @@ private BoundExpression MakeImplicitConversion(BoundExpression rewrittenOperand, for (int i = 0; i < numElements; i++) { - var field = srcElementFields[i]; - - DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic(); - if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error) - { - Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location); - } - var fieldAccess = MakeTupleFieldAccess(syntax, field, savedTuple, null, LookupResultKind.Empty); + var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(savedTuple, syntax, srcElementFields[i]); var convertedFieldAccess = MakeConversionNode(syntax, fieldAccess, elementConversions[i], destElementTypes[i], @checked, explicitCastInCode); - fieldAccessorsBuilder.Add(convertedFieldAccess); } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs index 2265088d8a49e..a8ab8094cce5b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_DeconstructionAssignmentOperator.cs @@ -221,18 +221,7 @@ private static bool IsTupleExpression(BoundKind kind) var builder = ArrayBuilder.GetInstance(numElements); for (int i = 0; i < numElements; i++) { - var field = fields[i]; - - // Use default field rather than implicitly named fields since - // fields from inferred names are not usable in C# 7.0. - field = field.CorrespondingTupleField ?? field; - - DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic(); - if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error) - { - Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, expression.Syntax.Location); - } - var fieldAccess = MakeTupleFieldAccess(expression.Syntax, field, tuple, null, LookupResultKind.Empty); + var fieldAccess = MakeTupleFieldAccessAndReportUseSiteDiagnostics(tuple, expression.Syntax, fields[i]); builder.Add(fieldAccess); } return builder.ToImmutableAndFree(); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs index 92942a3872be5..f178d2737224d 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_Field.cs @@ -1,7 +1,6 @@ // 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.CSharp.Symbols; -using System.Diagnostics; namespace Microsoft.CodeAnalysis.CSharp { @@ -90,5 +89,20 @@ public override BoundNode VisitFieldAccess(BoundFieldAccess node) // make a field access for the most local access return _factory.Field(rewrittenReceiver, underlyingField); } + + private BoundExpression MakeTupleFieldAccessAndReportUseSiteDiagnostics(BoundExpression tuple, SyntaxNode syntax, FieldSymbol field) + { + // Use default field rather than implicitly named fields since + // fields from inferred names are not usable in C# 7.0. + field = field.CorrespondingTupleField ?? field; + + DiagnosticInfo useSiteInfo = field.GetUseSiteDiagnostic(); + if ((object)useSiteInfo != null && useSiteInfo.Severity == DiagnosticSeverity.Error) + { + Symbol.ReportUseSiteDiagnostic(useSiteInfo, _diagnostics, syntax.Location); + } + + return MakeTupleFieldAccess(syntax, field, tuple, null, LookupResultKind.Empty); + } } } diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index 5310867a48741..c0e0ec2d2dc7a 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -634,23 +634,23 @@ private IOperation CreateUnboundLambdaOperation(UnboundLambda unboundLambda) // We are counting on the fact that will do the error recovery and actually create the BoundLambda node appropriate for // this syntax node. var lambdaOperation = _semanticModel.GetOperationInternal(unboundLambda.Syntax); - Debug.Assert(lambdaOperation.Kind == OperationKind.LambdaExpression); + Debug.Assert(lambdaOperation.Kind == OperationKind.AnonymousFunctionExpression); return lambdaOperation; } - private ILambdaExpression CreateBoundLambdaOperation(BoundLambda boundLambda) + private IAnonymousFunctionExpression CreateBoundLambdaOperation(BoundLambda boundLambda) { - IMethodSymbol signature = boundLambda.Symbol; + IMethodSymbol symbol = boundLambda.Symbol; Lazy body = new Lazy(() => (IBlockStatement)Create(boundLambda.Body)); SyntaxNode syntax = boundLambda.Syntax; // This matches the SemanticModel implementation. This is because in VB, lambdas by themselves // do not have a type. To get the type of a lambda expression in the SemanticModel, you need to look at // TypeInfo.ConvertedType, rather than TypeInfo.Type. We replicate that behavior here. To get the type of - // an ILambdaExpression, you need to look at the parent IConversionExpression. + // an IAnonymousFunctionExpression, you need to look at the parent IConversionExpression. ITypeSymbol type = null; Optional constantValue = ConvertToOptional(boundLambda.ConstantValue); bool isImplicit = boundLambda.WasCompilerGenerated; - return new LazyLambdaExpression(signature, body, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyAnonymousFunctionExpression(symbol, body, _semanticModel, syntax, type, constantValue, isImplicit); } private ILocalFunctionStatement CreateBoundLocalFunctionStatementOperation(BoundLocalFunctionStatement boundLocalFunctionStatement) @@ -913,15 +913,15 @@ private IConditionalChoiceExpression CreateBoundConditionalOperatorOperation(Bou return new LazyConditionalChoiceExpression(condition, ifTrueValue, ifFalseValue, _semanticModel, syntax, type, constantValue, isImplicit); } - private INullCoalescingExpression CreateBoundNullCoalescingOperatorOperation(BoundNullCoalescingOperator boundNullCoalescingOperator) + private ICoalesceExpression CreateBoundNullCoalescingOperatorOperation(BoundNullCoalescingOperator boundNullCoalescingOperator) { - Lazy primaryOperand = new Lazy(() => Create(boundNullCoalescingOperator.LeftOperand)); - Lazy secondaryOperand = new Lazy(() => Create(boundNullCoalescingOperator.RightOperand)); + Lazy expression = new Lazy(() => Create(boundNullCoalescingOperator.LeftOperand)); + Lazy whenNull = new Lazy(() => Create(boundNullCoalescingOperator.RightOperand)); SyntaxNode syntax = boundNullCoalescingOperator.Syntax; ITypeSymbol type = boundNullCoalescingOperator.Type; Optional constantValue = ConvertToOptional(boundNullCoalescingOperator.ConstantValue); bool isImplicit = boundNullCoalescingOperator.WasCompilerGenerated; - return new LazyNullCoalescingExpression(primaryOperand, secondaryOperand, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyCoalesceExpression(expression, whenNull, _semanticModel, syntax, type, constantValue, isImplicit); } private IAwaitExpression CreateBoundAwaitExpressionOperation(BoundAwaitExpression boundAwaitExpression) @@ -1266,14 +1266,16 @@ private IUsingStatement CreateBoundUsingStatementOperation(BoundUsingStatement b return new LazyUsingStatement(body, declaration, value, _semanticModel, syntax, type, constantValue, isImplicit); } - private IThrowStatement CreateBoundThrowStatementOperation(BoundThrowStatement boundThrowStatement) + private IExpressionStatement CreateBoundThrowStatementOperation(BoundThrowStatement boundThrowStatement) { Lazy thrownObject = new Lazy(() => Create(boundThrowStatement.ExpressionOpt)); SyntaxNode syntax = boundThrowStatement.Syntax; - ITypeSymbol type = null; + ITypeSymbol throwExpressionType = boundThrowStatement.ExpressionOpt?.Type; + ITypeSymbol statementType = null; Optional constantValue = default(Optional); bool isImplicit = boundThrowStatement.WasCompilerGenerated; - return new LazyThrowStatement(thrownObject, _semanticModel, syntax, type, constantValue, isImplicit); + IOperation throwExpression = new LazyThrowExpression(thrownObject, _semanticModel, syntax, throwExpressionType, constantValue, isImplicit); + return new ExpressionStatement(throwExpression, _semanticModel, syntax, statementType, constantValue, isImplicit); } private IReturnStatement CreateBoundReturnStatementOperation(BoundReturnStatement boundReturnStatement) @@ -1298,14 +1300,14 @@ private IReturnStatement CreateBoundYieldReturnStatementOperation(BoundYieldRetu private ILockStatement CreateBoundLockStatementOperation(BoundLockStatement boundLockStatement) { - Lazy lockedObject = new Lazy(() => Create(boundLockStatement.Argument)); + Lazy expression = new Lazy(() => Create(boundLockStatement.Argument)); Lazy body = new Lazy(() => Create(boundLockStatement.Body)); SyntaxNode syntax = boundLockStatement.Syntax; ITypeSymbol type = null; Optional constantValue = default(Optional); bool isImplicit = boundLockStatement.WasCompilerGenerated; - return new LazyLockStatement(lockedObject, body, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyLockStatement(expression, body, _semanticModel, syntax, type, constantValue, isImplicit); } private IInvalidStatement CreateBoundBadStatementOperation(BoundBadStatement boundBadStatement) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs index 95631d9d75a73..efc27dfc74c8f 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenLocalFunctionTests.cs @@ -30,6 +30,72 @@ public static IMethodSymbol FindLocalFunction(this CompilationVerifier verifier, [CompilerTrait(CompilerFeature.LocalFunctions)] public class CodeGenLocalFunctionTests : CSharpTestBase { + [Fact] + public void CaptureThisInDifferentScopes() + { + CompileAndVerify(@" +using System; +class C +{ + int _x; + void M() + { + { + int y = 0; + Func f1 = () => _x + y; + } + { + int y = 0; + Func f2 = () => _x + y; + } + } +}"); + } + + [Fact] + public void CaptureThisInDifferentScopes2() + { + CompileAndVerify(@" +using System; +class C +{ + int _x; + void M() + { + { + int y = 0; + int L1() => _x + y; + } + { + int y = 0; + int L2() => _x + y; + } + } +}"); + } + + [Fact] + public void CaptureFramePointerInDifferentScopes() + { + CompileAndVerify(@" +using System; +class C +{ + void M(int x) + { + Func f1 = () => x; + { + int z = 0; + Func f2 = () => x + z; + } + { + int z = 0; + Func f3 = () => x + z; + } + } +}"); + } + [Fact] public void EnvironmentChainContainsStructEnvironment() { @@ -3558,6 +3624,121 @@ Action L5(int x) 00222"); } + [Fact] + [WorkItem(21317, "https://github.com/dotnet/roslyn/issues/21317")] + [CompilerTrait(CompilerFeature.Dynamic)] + public void DynamicGenericArg() + { + var src = @" +void L1(T x) +{ + Console.WriteLine($""{x}: {typeof(T)}""); +} +dynamic val = 2; +L1(val); +L1(val); +L1(val); +L1(4); + +void L2(int x, T y) => Console.WriteLine($""{x}, {y}: {typeof(T)}""); +L2(val, 3.0f); + +List listOfDynamic = new List { 1, 2, 3 }; +void L3(List x) => Console.WriteLine($""{string.Join("", "", x)}: {typeof(T)}""); +L3(listOfDynamic); + +void L4(T x, params int[] y) => Console.WriteLine($""{x}, {string.Join("", "", y)}: {typeof(T)}""); +L4(val, 3, 4); +L4(val, 3, 4); +L4(1, 3, val); + +void L5(int x, params T[] y) => Console.WriteLine($""{x}, {string.Join("", "", y)}: {typeof(T)}""); +L5(val, 3, 4); +L5(1, 3, val); +L5(1, 3, val); +"; + var output = @" +2: System.Object +2: System.Int32 +2: System.Object +4: System.Object +2, 3: System.Single +1, 2, 3: System.Object +2, 3, 4: System.Object +2, 3, 4: System.Int32 +1, 3, 2: System.Int32 +2, 3, 4: System.Int32 +1, 3, 2: System.Int32 +1, 3, 2: System.Object +"; + VerifyOutputInMain(src, output, "System", "System.Collections.Generic"); + } + + [Fact] + [WorkItem(21317, "https://github.com/dotnet/roslyn/issues/21317")] + [CompilerTrait(CompilerFeature.Dynamic)] + public void DynamicGenericClassMethod() + { + var src = @" +using System; +class C1 +{ + public static void M1() + { + void F(int x) + { + Console.WriteLine($""C1<{typeof(T1)}>.M1<{typeof(T2)}>.F({x})""); + } + F((dynamic)2); + } + public static void M2() + { + void F(int x) + { + Console.WriteLine($""C1<{typeof(T1)}>.M2.F({x})""); + } + F((dynamic)2); + } +} +class C2 +{ + public static void M1() + { + void F(int x) + { + Console.WriteLine($""C2.M1<{typeof(T2)}>.F({x})""); + } + F((dynamic)2); + } + public static void M2() + { + void F(int x) + { + Console.WriteLine($""C2.M2.F({x})""); + } + F((dynamic)2); + } +} +class Program +{ + static void Main() + { + C1.M1(); + C1.M2(); + C2.M1(); + C2.M2(); + } +} +"; + var output = @" +C1.M1.F(2) +C1.M2.F(2) +C2.M1.F(2) +C2.M2.F(2) +"; + VerifyOutput(src, output); + } + [Fact] [CompilerTrait(CompilerFeature.Dynamic, CompilerFeature.Params)] public void DynamicArgsAndParams() diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 76b8f3d52aa8f..197b78458000c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -3938,6 +3938,29 @@ static class Extension verifier7_1.VerifyDiagnostics(); } + [WorkItem(21518, "https://github.com/dotnet/roslyn/issues/21518")] + [Fact] + public void InferredName_Conversion() + { + var source = +@"using System.Collections.Generic; +class C +{ + static void F((int, IList) items) + { + } + static void Test() + { + var items = new List(); + var group = (1, items); + F(group); + } +}"; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7), + references: new[] { MscorlibRef, ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef }); + comp.VerifyEmitDiagnostics(); + } + [Fact] public void LongTupleWithArgumentEvaluation() { diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILambdaExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IAnonymousFunctionExpression.cs similarity index 82% rename from src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILambdaExpression.cs rename to src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IAnonymousFunctionExpression.cs index 24ba5e3ae4b5c..d03618490dd96 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILambdaExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IAnonymousFunctionExpression.cs @@ -12,7 +12,7 @@ public partial class IOperationTests : SemanticModelTestBase { [CompilerTrait(CompilerFeature.IOperation)] [Fact] - public void ILambdaExpression_BoundLambda_HasValidLambdaExpressionTree() + public void IAnonymousFunctionExpression_BoundLambda_HasValidLambdaExpressionTree() { string source = @" using System; @@ -35,7 +35,7 @@ static void F() Variables: Local_1: System.Action x Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '() => F()') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => F()') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => F()') IBlockStatement (2 statements) (OperationKind.BlockStatement) (Syntax: 'F()') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'F()') Expression: IInvocationExpression (void Program.F()) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'F()') @@ -51,7 +51,7 @@ static void F() [CompilerTrait(CompilerFeature.IOperation)] [Fact] - public void ILambdaExpression_UnboundLambdaAsVar_HasValidLambdaExpressionTree() + public void IAnonymousFunctionExpression_UnboundLambdaAsVar_HasValidLambdaExpressionTree() { string source = @" using System; @@ -72,7 +72,7 @@ static void F() IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var x /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'var x /**/;') Variables: Local_1: var x - Initializer: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => F()') + Initializer: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() => F()') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'F()') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: 'F()') Expression: IInvocationExpression (void Program.F()) (OperationKind.InvocationExpression, Type: System.Void, IsInvalid) (Syntax: 'F()') @@ -90,7 +90,7 @@ static void F() [CompilerTrait(CompilerFeature.IOperation)] [Fact] - public void ILambdaExpression_UnboundLambdaAsDelegate_HasValidLambdaExpressionTree() + public void IAnonymousFunctionExpression_UnboundLambdaAsDelegate_HasValidLambdaExpressionTree() { string source = @" using System; @@ -113,7 +113,7 @@ static void F() Variables: Local_1: System.Action x Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '() => F()') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => F()') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() => F()') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'F()') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: 'F()') Expression: IInvocationExpression (void Program.F()) (OperationKind.InvocationExpression, Type: System.Void, IsInvalid) (Syntax: 'F()') @@ -131,7 +131,7 @@ static void F() [CompilerTrait(CompilerFeature.IOperation)] [Fact] - public void ILambdaExpression_UnboundLambda_ReferenceEquality() + public void IAnonymousFunctionExpression_UnboundLambda_ReferenceEquality() { string source = @" using System; @@ -157,19 +157,19 @@ static void F() var lambdaSyntax = (LambdaExpressionSyntax)variableDeclaration.Variables.Single().Initializer.Value; var variableDeclarationOperation = (IVariableDeclarationStatement)semanticModel.GetOperationInternal(variableDeclaration); - var variableTreeLambdaOperation = (ILambdaExpression)variableDeclarationOperation.Declarations.Single().Initializer; - var lambdaOperation = (ILambdaExpression)semanticModel.GetOperationInternal(lambdaSyntax); + var variableTreeLambdaOperation = (IAnonymousFunctionExpression)variableDeclarationOperation.Declarations.Single().Initializer; + var lambdaOperation = (IAnonymousFunctionExpression)semanticModel.GetOperationInternal(lambdaSyntax); // Assert that both ways of getting to the lambda (requesting the lambda directly, and requesting via the lambda syntax) // return the same bound node. Assert.Same(variableTreeLambdaOperation, lambdaOperation); var variableDeclarationOperationSecondRequest = (IVariableDeclarationStatement)semanticModel.GetOperationInternal(variableDeclaration); - var variableTreeLambdaOperationSecondRequest = (ILambdaExpression)variableDeclarationOperation.Declarations.Single().Initializer; - var lambdaOperationSecondRequest = (ILambdaExpression)semanticModel.GetOperationInternal(lambdaSyntax); + var variableTreeLambdaOperationSecondRequest = (IAnonymousFunctionExpression)variableDeclarationOperation.Declarations.Single().Initializer; + var lambdaOperationSecondRequest = (IAnonymousFunctionExpression)semanticModel.GetOperationInternal(lambdaSyntax); // Assert that, when request the variable declaration or the lambda for a second time, there is no rebinding of the - // underlying UnboundLambda, and we get the same ILambdaExpression as before + // underlying UnboundLambda, and we get the same IAnonymousFunctionExpression as before Assert.Same(variableTreeLambdaOperation, variableTreeLambdaOperationSecondRequest); Assert.Same(lambdaOperation, lambdaOperationSecondRequest); } diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs index 048723ff60a0c..e3be27f39a8f2 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IConversionExpression.cs @@ -318,11 +318,11 @@ static void Main(string[] args) IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'object /**/;') Variables: Local_1: System.Object o - Initializer: INullCoalescingExpression (OperationKind.NullCoalescingExpression, Type: System.Object) (Syntax: 'new object( ... Exception()') - Left: IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') + Initializer: ICoalesceExpression (OperationKind.CoalesceExpression, Type: System.Object) (Syntax: 'new object( ... Exception()') + Expression: IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') Arguments(0) Initializer: null - Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'throw new Exception()') + WhenNull: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'throw new Exception()') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: IThrowExpression (OperationKind.ThrowExpression, Type: null) (Syntax: 'throw new Exception()') IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new Exception()') @@ -342,7 +342,7 @@ static void Main(string[] args) OperationSelector = (operation) => { var initializer = ((IVariableDeclarationStatement)operation).Declarations.Single().Initializer; - return (IConversionExpression)((INullCoalescingExpression)initializer).SecondaryOperand; + return (IConversionExpression)((ICoalesceExpression)initializer).WhenNull; } }.Verify); } @@ -1614,7 +1614,7 @@ void Main() Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: Program.DType) (Syntax: '() => { }') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -1645,7 +1645,7 @@ void Main() Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: Program.DType, IsInvalid) (Syntax: '(string s) => { }') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { @@ -1679,7 +1679,7 @@ void Main() Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: Program.DType, IsInvalid) (Syntax: '() =>/**/') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() =>/**/') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() =>/**/') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '') Expression: IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') @@ -1719,7 +1719,7 @@ static void Main(string[] args) string expectedOperationTree = @" IOperation: (OperationKind.None) (Syntax: 'new Action(() => { })') Children(1): - ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') + IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -2989,7 +2989,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: 'delegate { }') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'delegate { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'delegate { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -3021,7 +3021,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: 'delegate(int i) { }') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'delegate(int i) { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'delegate(int i) { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -3053,7 +3053,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: 'delegate() { }') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'delegate() { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'delegate() { }') IBlockStatement (0 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { @@ -3217,7 +3217,7 @@ static void Main(string[] args) Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'num => num < 5') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'num => num < 5') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'num => num < 5') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'num < 5') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'num < 5') ReturnedValue: IBinaryOperatorExpression (BinaryOperationKind.IntegerLessThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'num < 5') @@ -3250,7 +3250,7 @@ static void Main(string[] args) IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Expression< ... **/;') Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>, IsInvalid) (Syntax: 'num => num') - ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'num => num') + IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'num => num') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'num') IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'num') IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: 'num') @@ -3293,7 +3293,7 @@ static void Main(string[] args) Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>, IsInvalid) (Syntax: 'num =>/**/') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'num =>/**/') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'num =>/**/') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '') IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: '') ReturnedValue: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: '') @@ -4902,7 +4902,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '(Action)(() => { })') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -4933,7 +4933,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)(() => 1)') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => 1') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() => 1') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '1') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '1') Expression: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') @@ -4970,7 +4970,7 @@ void M1() Variables: Local_1: System.Action a Initializer: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)((s ... s) => { })') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { @@ -5002,7 +5002,7 @@ void M1() Children(1): IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '(Action)(() => { })') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') ReturnedValue: null @@ -5032,7 +5032,7 @@ void M1() Children(1): IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)(() => 1)') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => 1') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() => 1') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '1') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '1') Expression: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1') @@ -5068,7 +5068,7 @@ void M1() Children(1): IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)((s ... s) => { })') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs index a0ede9d2fe3cd..13bcaaa99976e 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IDynamicObjectCreationExpression.cs @@ -310,7 +310,7 @@ public C(Action a, Action y) ApplicableSymbols(1): Symbol: C..ctor(System.Action a, System.Action y) Arguments(2): - ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'delegate { }') + IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'delegate { }') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: '{ }') ReturnedValue: null diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs index a6dedbfee5c7e..c9c5cec3b1966 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.cs @@ -724,7 +724,7 @@ static void Main(string[] args) } } "; -string expectedOperationTree = @" + string expectedOperationTree = @" IForEachLoopStatement (Iteration variable: System.String x) (LoopKind.ForEach) (OperationKind.LoopStatement) (Syntax: 'foreach (st ... e)args) { }') Collection: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Collections.IEnumerable) (Syntax: '(IEnumerable)args') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) @@ -770,14 +770,15 @@ static void Main() Left: ILocalReferenceExpression: num (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'num') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 3) (Syntax: '3') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'throw new S ... ""testing"");') - ThrownObject: IObjectCreationExpression (Constructor: System.Exception..ctor(System.String message)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System. ... (""testing"")') - Arguments(1): - IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '""testing""') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""testing"") (Syntax: '""testing""') - InConversion: null - OutConversion: null - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'throw new S ... ""testing"");') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'throw new S ... ""testing"");') + IObjectCreationExpression (Constructor: System.Exception..ctor(System.String message)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System. ... (""testing"")') + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '""testing""') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""testing"") (Syntax: '""testing""') + InConversion: null + OutConversion: null + Initializer: null IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'System.Cons ... eLine(num);') Expression: IInvocationExpression (void System.Console.WriteLine(System.Int32 value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'System.Cons ... teLine(num)') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs index 105d673c913d8..d1674ff693698 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IForLoopStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// 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.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -973,10 +973,11 @@ static void Main(string[] args) Initializer: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') AtLoopBottom(0) Body: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'throw new S ... xception();') - ThrownObject: IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System.Exception()') - Arguments(0) - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'throw new S ... xception();') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'throw new S ... xception();') + IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System.Exception()') + Arguments(0) + Initializer: null "; VerifyOperationTreeForTest(source, expectedOperationTree); } @@ -1400,7 +1401,7 @@ static void Main(string[] args) IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'x.ToString()') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func>) (Syntax: 'x.ToString()') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'x.ToString()') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'x.ToString()') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'x.ToString()') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'x.ToString()') ReturnedValue: IObjectCreationExpression (Constructor: ..ctor(System.Char x, System.String z)) (OperationKind.ObjectCreationExpression, Type: ) (Syntax: 'let z = x.ToString()') @@ -1423,7 +1424,7 @@ static void Main(string[] args) IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'z') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func<, System.String>) (Syntax: 'z') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'z') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'z') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'z') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'z') ReturnedValue: IOperation: (OperationKind.None) (Syntax: 'z') @@ -1434,7 +1435,7 @@ static void Main(string[] args) IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'w') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func) (Syntax: 'w') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'w') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'w') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'w') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'w') ReturnedValue: IOperation: (OperationKind.None) (Syntax: 'w') @@ -1540,7 +1541,7 @@ private static IEnumerable fun() IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'x.ToString()') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func>) (Syntax: 'x.ToString()') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'x.ToString()') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'x.ToString()') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'x.ToString()') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'x.ToString()') ReturnedValue: IObjectCreationExpression (Constructor: ..ctor(System.Char x, System.String z)) (OperationKind.ObjectCreationExpression, Type: ) (Syntax: 'let z = x.ToString()') @@ -1563,7 +1564,7 @@ private static IEnumerable fun() IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'z') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func<, System.String>) (Syntax: 'z') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'z') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'z') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'z') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'z') ReturnedValue: IOperation: (OperationKind.None) (Syntax: 'z') @@ -1574,7 +1575,7 @@ private static IEnumerable fun() IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'w') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func) (Syntax: 'w') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'w') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'w') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'w') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'w') ReturnedValue: IOperation: (OperationKind.None) (Syntax: 'w') @@ -1615,7 +1616,7 @@ static void Main(string[] args) Left: ILocalReferenceExpression: e (OperationKind.LocalReferenceExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'e') Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'x => x * x') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'x => x * x') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'x => x * x') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'x * x') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'x * x') ReturnedValue: IBinaryOperatorExpression (BinaryOperationKind.IntegerMultiply) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'x * x') @@ -1687,7 +1688,7 @@ static void Main(string[] args) Left: ILocalReferenceExpression: e (OperationKind.LocalReferenceExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'e') Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'x => x * x') Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'x => x * x') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'x => x * x') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'x * x') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'x * x') ReturnedValue: IBinaryOperatorExpression (BinaryOperationKind.IntegerMultiply) (OperationKind.BinaryOperatorExpression, Type: System.Int32) (Syntax: 'x * x') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs new file mode 100644 index 0000000000000..9495e676c4831 --- /dev/null +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILockStatement.cs @@ -0,0 +1,347 @@ +// 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.CSharp.Syntax; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests +{ + public partial class IOperationTests : SemanticModelTestBase + { + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ObjectLock_FieldReference() + { + string source = @" +public class C1 +{ + object o = new object(); + + public void M() + { + /**/lock (o) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (o) ... }') + Expression: IFieldReferenceExpression: System.Object C1.o (OperationKind.FieldReferenceExpression, Type: System.Object) (Syntax: 'o') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'o') + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ObjectLock_LocalReference() + { + string source = @" +public class C1 +{ + public void M() + { + object o = new object(); + /**/lock (o) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (o) ... }') + Expression: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ObjectLock_Null() + { + string source = @" +public class C1 +{ + public void M() + { + /**/lock (null) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (null) ... }') + Expression: ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ObjectLock_NonReferenceType() + { + string source = @" +public class C1 +{ + public void M() + { + int i = 1; + /**/lock (i) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement, IsInvalid) (Syntax: 'lock (i) ... }') + Expression: ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32, IsInvalid) (Syntax: 'i') + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0185: 'int' is not a reference type as required by the lock statement + // /**/lock (i) + Diagnostic(ErrorCode.ERR_LockNeedsReference, "i").WithArguments("int").WithLocation(7, 25) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_MissingLockExpression() + { + string source = @" +public class C1 +{ + public void M() + { + /**/lock () + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement, IsInvalid) (Syntax: 'lock () ... }') + Expression: IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') + Children(0) + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1525: Invalid expression term ')' + // /**/lock () + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(6, 25) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_InvalidLockStatement() + { + string source = @" +using System; + +public class C1 +{ + public void M() + { + /**/lock (invalidReference) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement, IsInvalid) (Syntax: 'lock (inval ... }') + Expression: IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: 'invalidReference') + Children(0) + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0103: The name 'invalidReference' does not exist in the current context + // /**/lock (invalidReference) + Diagnostic(ErrorCode.ERR_NameNotInContext, "invalidReference").WithArguments("invalidReference").WithLocation(8, 25) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_MissingBody() + { + string source = @" +public class C1 +{ + public void M() + { + object o = new object(); + /**/lock (o) +/**/ } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement, IsInvalid) (Syntax: 'lock (o) +') + Expression: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') + Body: IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: '') + Expression: IInvalidExpression (OperationKind.InvalidExpression, Type: ?) (Syntax: '') + Children(0) +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS1525: Invalid expression term '}' + // /**/lock (o) + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("}").WithLocation(7, 27), + // CS1002: ; expected + // /**/lock (o) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(7, 27) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ExpressionLock_ObjectMethodCall() + { + string source = @" +public class C1 +{ + public void M() + { + object o = new object(); + /**/lock (o.ToString()) + { + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (o.ToS ... }') + Expression: IInvocationExpression (virtual System.String System.Object.ToString()) (OperationKind.InvocationExpression, Type: System.String) (Syntax: 'o.ToString()') + Instance Receiver: ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') + Arguments(0) + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ExpressionLock_ClassMethodCall() + { + string source = @" +public class C1 +{ + public void M() + { + /**/lock (M2()) + { + }/**/ + } + + public object M2() + { + return new object(); + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (M2()) ... }') + Expression: IInvocationExpression ( System.Object C1.M2()) (OperationKind.InvocationExpression, Type: System.Object) (Syntax: 'M2()') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'M2') + Arguments(0) + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_ExpressionCall_VoidMethodCall() + { + string source = @" +public class C1 +{ + public void M() + { + /**/lock (M2()) + { + }/**/ + } + + public void M2() { } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement, IsInvalid) (Syntax: 'lock (M2()) ... }') + Expression: IInvocationExpression ( void C1.M2()) (OperationKind.InvocationExpression, Type: System.Void, IsInvalid) (Syntax: 'M2()') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1, IsInvalid) (Syntax: 'M2') + Arguments(0) + Body: IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') +"; + var expectedDiagnostics = new DiagnosticDescription[] { + // CS0185: 'void' is not a reference type as required by the lock statement + // /**/lock (M2()) + Diagnostic(ErrorCode.ERR_LockNeedsReference, "M2()").WithArguments("void").WithLocation(6, 25) + }; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void ILockStatement_NonEmptybody() + { + string source = @" +using System; + +public class C1 +{ + public void M() + { + /**/lock (new object()) + { + Console.WriteLine(""Hello World!""); + }/**/ + } +} +"; + string expectedOperationTree = @" +ILockStatement (OperationKind.LockStatement) (Syntax: 'lock (new o ... }') + Expression: IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') + Arguments(0) + Initializer: null + Body: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Wri ... o World!"");') + Expression: IInvocationExpression (void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Wri ... lo World!"")') + Instance Receiver: null + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: '""Hello World!""') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""Hello World!"") (Syntax: '""Hello World!""') + InConversion: null + OutConversion: null +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); + } + } +} diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs index df796164d7cde..cad16b56fad9e 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.cs @@ -161,7 +161,7 @@ public void M(List customers) IArgument (ArgumentKind.Explicit, Matching Parameter: selector) (OperationKind.Argument) (Syntax: 'cust.Name') IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func) (Syntax: 'cust.Name') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'cust.Name') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'cust.Name') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'cust.Name') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'cust.Name') ReturnedValue: IPropertyReferenceExpression: System.String Customer.Name { get; set; } (OperationKind.PropertyReferenceExpression, Type: System.String) (Syntax: 'cust.Name') @@ -263,7 +263,7 @@ public void UsedParameterMethod1(Action a) string expectedOperationTree = @" IOperation: (OperationKind.None) (Syntax: 'new Action( ... })') Children(1): - ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => ... }') + IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => ... }') IBlockStatement (2 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'a();') Expression: IInvocationExpression (virtual void System.Action.Invoke()) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'a()') diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs index 58994807d9c58..3d47f936d0887 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// 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.CSharp.Syntax; using Microsoft.CodeAnalysis.Test.Utilities; @@ -241,14 +241,15 @@ static void Main() Left: ILocalReferenceExpression: value (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'value') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 100) (Syntax: '100') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'throw new E ... ever hit"");') - ThrownObject: IObjectCreationExpression (Constructor: System.Exception..ctor(System.String message)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new Excepti ... Never hit"")') - Arguments(1): - IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '""Never hit""') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""Never hit"") (Syntax: '""Never hit""') - InConversion: null - OutConversion: null - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'throw new E ... ever hit"");') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'throw new E ... ever hit"");') + IObjectCreationExpression (Constructor: System.Exception..ctor(System.String message)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new Excepti ... Never hit"")') + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '""Never hit""') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: ""Never hit"") (Syntax: '""Never hit""') + InConversion: null + OutConversion: null + Initializer: null IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.Wri ... tatement"");') Expression: IInvocationExpression (void System.Console.WriteLine(System.String value)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.Wri ... statement"")') @@ -314,6 +315,7 @@ static void Main() IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'value--;') Expression: IIncrementExpression (UnaryOperandKind.IntegerPostfixDecrement) (OperationKind.IncrementExpression, Type: System.Int32) (Syntax: 'value--') Left: ILocalReferenceExpression: value (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'value') + "; VerifyOperationTreeForTest(source, expectedOperationTree); } @@ -334,7 +336,7 @@ static void Main() } } "; -string expectedOperationTree = @" + string expectedOperationTree = @" IWhileUntilLoopStatement (IsTopTest: True, IsWhile: True) (LoopKind.WhileUntil) (OperationKind.LoopStatement, IsInvalid) (Syntax: 'while (numb ... }') Condition: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: 'number') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) @@ -908,10 +910,11 @@ public void TryMethod() Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') Catch clauses(0) Finally: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ ... }') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'throw new S ... xception();') - ThrownObject: IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System.Exception()') - Arguments(0) - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'throw new S ... xception();') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'throw new S ... xception();') + IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new System.Exception()') + Arguments(0) + Initializer: null "; VerifyOperationTreeForTest(source, expectedOperationTree); } diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidExpression.cs index a92e6824fc3e5..75062cd087eba 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_InvalidExpression.cs @@ -328,7 +328,7 @@ static void F() IVariableDeclarationStatement (1 variables) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'var x /**/;') IVariableDeclaration: var x (OperationKind.VariableDeclaration) (Syntax: 'var x /**/;') Initializer: IUnboundLambdaExpression (OperationKind.UnboundLambdaExpression, Type: null) (Syntax: '() => F() - ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => F()') + IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => F()') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'F()') IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'F()') IInvocationExpression (static void Program.F()) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'F()')') @@ -362,7 +362,7 @@ static void F() } "; string expectedOperationTree = @" -ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => F()') +IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: '() => F()') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'F()') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: 'F()') Expression: IInvocationExpression (void Program.F()) (OperationKind.InvocationExpression, Type: System.Void, IsInvalid) (Syntax: 'F()') diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index a5a761ddf1dd3..d2890d43c4a32 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -3136,7 +3136,10 @@ static void M() comp.VerifyEmitDiagnostics( // (8,18): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. // L(m => L(d => d, m), null); - Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "d => d").WithLocation(8, 18)); + Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "d => d").WithLocation(8, 18), + // (8,16): error CS8322: Cannot pass argument with dynamic type to generic local function 'L' with inferred type arguments. + // L(m => L(d => d, m), null); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L(d => d, m)").WithArguments("L").WithLocation(8, 16)); } [Fact] @@ -3159,9 +3162,74 @@ async Task L(Func t, object p) // (8,37): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. // => await L(async m => L(async d => await d, m), p); Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "async d => await d").WithLocation(8, 37), + // (8,35): error CS8322: Cannot pass argument with dynamic type to generic local function 'L' with inferred type arguments. + // => await L(async m => L(async d => await d, m), p); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L(async d => await d, m)").WithArguments("L").WithLocation(8, 35), // (8,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. // => await L(async m => L(async d => await d, m), p); Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(8, 32)); } + + [Fact] + [WorkItem(21317, "https://github.com/dotnet/roslyn/issues/21317")] + [CompilerTrait(CompilerFeature.Dynamic)] + public void DynamicGenericArg() + { + var src = @" +using System.Collections.Generic; +class C +{ + static void M() + { + dynamic val = 2; + dynamic dynamicList = new List(); + + void L1(T x) { } + L1(val); + + void L2(int x, T y) { } + L2(1, val); + L2(val, 3.0f); + + void L3(List x) { } + L3(dynamicList); + + void L4(int x, params T[] y) { } + L4(1, 2, val); + L4(val, 3, 4); + + void L5(T x, params int[] y) { } + L5(val, 1, 2); + L5(1, 3, val); + } +} +"; + VerifyDiagnostics(src, + // (11,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L1'. Try specifying the type arguments explicitly. + // L1(val); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L1(val)").WithArguments("L1").WithLocation(11, 9), + // (14,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L2'. Try specifying the type arguments explicitly. + // L2(1, val); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L2(1, val)").WithArguments("L2").WithLocation(14, 9), + // (15,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L2'. Try specifying the type arguments explicitly. + // L2(val, 3.0f); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L2(val, 3.0f)").WithArguments("L2").WithLocation(15, 9), + // (18,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L3'. Try specifying the type arguments explicitly. + // L3(dynamicList); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L3(dynamicList)").WithArguments("L3").WithLocation(18, 9), + // (21,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L4'. Try specifying the type arguments explicitly. + // L4(1, 2, val); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L4(1, 2, val)").WithArguments("L4").WithLocation(21, 9), + // (22,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L4'. Try specifying the type arguments explicitly. + // L4(val, 3, 4); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L4(val, 3, 4)").WithArguments("L4").WithLocation(22, 9), + // (25,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L5'. Try specifying the type arguments explicitly. + // L5(val, 1, 2); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L5(val, 1, 2)").WithArguments("L5").WithLocation(25, 9), + // (26,9): error CS8322: Cannot pass argument with dynamic type to generic local function 'L5'. Try specifying the type arguments explicitly. + // L5(1, 3, val); + Diagnostic(ErrorCode.ERR_DynamicLocalFunctionTypeParameter, "L5(1, 3, val)").WithArguments("L5").WithLocation(26, 9) + ); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSemanticsTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSemanticsTests.cs index d33c259e5a35e..d6903da9b8d48 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSemanticsTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/AnonymousTypesSemanticsTests.cs @@ -349,7 +349,7 @@ void Main() Instance Receiver: null Right: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: D1) (Syntax: '(D1)(() => false)') Conversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => false') + Operand: IAnonymousFunctionExpression (Symbol: lambda expression) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: '() => false') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'false') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'false') ReturnedValue: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Boolean, Constant: False) (Syntax: 'false') diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 47aeb6b9fb9ca..076ac7b14de22 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -2645,20 +2645,14 @@ public LazyLabelStatement(ILabelSymbol label, Lazy labeledStatement, protected override IOperation LabeledStatementImpl => _lazyLabeledStatement.Value; } - /// - /// Represents a lambda expression. - /// - internal abstract partial class BaseLambdaExpression : Operation, ILambdaExpression + internal abstract partial class BaseAnonymousFunctionExpression : Operation, IAnonymousFunctionExpression { - protected BaseLambdaExpression(IMethodSymbol signature, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.LambdaExpression, semanticModel, syntax, type, constantValue, isImplicit) + protected BaseAnonymousFunctionExpression(IMethodSymbol symbol, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.AnonymousFunctionExpression, semanticModel, syntax, type, constantValue, isImplicit) { - Signature = signature; + Symbol = symbol; } - /// - /// Signature of the lambda. - /// - public IMethodSymbol Signature { get; } + public IMethodSymbol Symbol { get; } protected abstract IBlockStatement BodyImpl { get; } public override IEnumerable Children { @@ -2667,27 +2661,21 @@ public override IEnumerable Children yield return Body; } } - /// - /// Body of the lambda. - /// public IBlockStatement Body => Operation.SetParentOperation(BodyImpl, this); public override void Accept(OperationVisitor visitor) { - visitor.VisitLambdaExpression(this); + visitor.VisitAnonymousFunctionExpression(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitLambdaExpression(this, argument); + return visitor.VisitAnonymousFunctionExpression(this, argument); } } - /// - /// Represents a lambda expression. - /// - internal sealed partial class LambdaExpression : BaseLambdaExpression, ILambdaExpression + internal sealed partial class AnonymousFunctionExpression : BaseAnonymousFunctionExpression, IAnonymousFunctionExpression { - public LambdaExpression(IMethodSymbol signature, IBlockStatement body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(signature, semanticModel, syntax, type, constantValue, isImplicit) + public AnonymousFunctionExpression(IMethodSymbol symbol, IBlockStatement body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(symbol, semanticModel, syntax, type, constantValue, isImplicit) { BodyImpl = body; } @@ -2695,14 +2683,11 @@ internal sealed partial class LambdaExpression : BaseLambdaExpression, ILambdaEx protected override IBlockStatement BodyImpl { get; } } - /// - /// Represents a lambda expression. - /// - internal sealed partial class LazyLambdaExpression : BaseLambdaExpression, ILambdaExpression + internal sealed partial class LazyAnonymousFunctionExpression : BaseAnonymousFunctionExpression, IAnonymousFunctionExpression { private readonly Lazy _lazyBody; - public LazyLambdaExpression(IMethodSymbol signature, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(signature, semanticModel, syntax, type, constantValue, isImplicit) + public LazyAnonymousFunctionExpression(IMethodSymbol symbol, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(symbol, semanticModel, syntax, type, constantValue, isImplicit) { _lazyBody = body ?? throw new System.ArgumentNullException(nameof(body)); } @@ -2856,20 +2841,20 @@ internal abstract partial class BaseLockStatement : Operation, ILockStatement { } - protected abstract IOperation LockedObjectImpl { get; } + protected abstract IOperation ExpressionImpl { get; } protected abstract IOperation BodyImpl { get; } public override IEnumerable Children { get { - yield return LockedObject; + yield return Expression; yield return Body; } } /// - /// Value to be locked. + /// Expression producing a value to be locked. /// - public IOperation LockedObject => Operation.SetParentOperation(LockedObjectImpl, this); + public IOperation Expression => Operation.SetParentOperation(ExpressionImpl, this); /// /// Body of the lock, to be executed while holding the lock. /// @@ -2889,14 +2874,14 @@ public override void Accept(OperationVisitor visitor) /// internal sealed partial class LockStatement : BaseLockStatement, ILockStatement { - public LockStatement(IOperation lockedObject, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public LockStatement(IOperation expression, IOperation body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { - LockedObjectImpl = lockedObject; + ExpressionImpl = expression; BodyImpl = body; } - protected override IOperation LockedObjectImpl { get; } + protected override IOperation ExpressionImpl { get; } protected override IOperation BodyImpl { get; } } @@ -2905,16 +2890,16 @@ internal sealed partial class LockStatement : BaseLockStatement, ILockStatement /// internal sealed partial class LazyLockStatement : BaseLockStatement, ILockStatement { - private readonly Lazy _lazyLockedObject; + private readonly Lazy _lazyExpression; private readonly Lazy _lazyBody; public LazyLockStatement(Lazy lockedObject, Lazy body, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { - _lazyLockedObject = lockedObject ?? throw new System.ArgumentNullException(nameof(lockedObject)); + _lazyExpression = lockedObject ?? throw new System.ArgumentNullException(nameof(lockedObject)); _lazyBody = body ?? throw new System.ArgumentNullException(nameof(body)); } - protected override IOperation LockedObjectImpl => _lazyLockedObject.Value; + protected override IOperation ExpressionImpl => _lazyExpression.Value; protected override IOperation BodyImpl => _lazyBody.Value; } @@ -3034,74 +3019,74 @@ internal sealed partial class LazyMethodBindingExpression : BaseMethodBindingExp /// /// Represents a null-coalescing expression. /// - internal abstract partial class BaseNullCoalescingExpression : Operation, INullCoalescingExpression + internal abstract partial class BaseCoalesceExpression : Operation, ICoalesceExpression { - protected BaseNullCoalescingExpression(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.NullCoalescingExpression, semanticModel, syntax, type, constantValue, isImplicit) + protected BaseCoalesceExpression(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(OperationKind.CoalesceExpression, semanticModel, syntax, type, constantValue, isImplicit) { } - protected abstract IOperation PrimaryOperandImpl { get; } - protected abstract IOperation SecondaryOperandImpl { get; } + protected abstract IOperation ExpressionImpl { get; } + protected abstract IOperation WhenNullImpl { get; } public override IEnumerable Children { get { - yield return PrimaryOperand; - yield return SecondaryOperand; + yield return Expression; + yield return WhenNull; } } /// /// Value to be unconditionally evaluated. /// - public IOperation PrimaryOperand => Operation.SetParentOperation(PrimaryOperandImpl, this); + public IOperation Expression => Operation.SetParentOperation(ExpressionImpl, this); /// - /// Value to be evaluated if Primary evaluates to null/Nothing. + /// Value to be evaluated if evaluates to null/Nothing. /// - public IOperation SecondaryOperand => Operation.SetParentOperation(SecondaryOperandImpl, this); + public IOperation WhenNull => Operation.SetParentOperation(WhenNullImpl, this); public override void Accept(OperationVisitor visitor) { - visitor.VisitNullCoalescingExpression(this); + visitor.VisitCoalesceExpression(this); } public override TResult Accept(OperationVisitor visitor, TArgument argument) { - return visitor.VisitNullCoalescingExpression(this, argument); + return visitor.VisitCoalesceExpression(this, argument); } } /// /// Represents a null-coalescing expression. /// - internal sealed partial class NullCoalescingExpression : BaseNullCoalescingExpression, INullCoalescingExpression + internal sealed partial class CoalesceExpression : BaseCoalesceExpression, ICoalesceExpression { - public NullCoalescingExpression(IOperation primaryOperand, IOperation secondaryOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public CoalesceExpression(IOperation expression, IOperation whenNull, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { - PrimaryOperandImpl = primaryOperand; - SecondaryOperandImpl = secondaryOperand; + ExpressionImpl = expression; + WhenNullImpl = whenNull; } - protected override IOperation PrimaryOperandImpl { get; } - protected override IOperation SecondaryOperandImpl { get; } + protected override IOperation ExpressionImpl { get; } + protected override IOperation WhenNullImpl { get; } } /// /// Represents a null-coalescing expression. /// - internal sealed partial class LazyNullCoalescingExpression : BaseNullCoalescingExpression, INullCoalescingExpression + internal sealed partial class LazyCoalesceExpression : BaseCoalesceExpression, ICoalesceExpression { - private readonly Lazy _lazyPrimaryOperand; - private readonly Lazy _lazySecondaryOperand; + private readonly Lazy _lazyExpression; + private readonly Lazy _lazyWhenNull; - public LazyNullCoalescingExpression(Lazy primaryOperand, Lazy secondaryOperand, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) + public LazyCoalesceExpression(Lazy expression, Lazy whenNull, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) { - _lazyPrimaryOperand = primaryOperand ?? throw new System.ArgumentNullException(nameof(primaryOperand)); - _lazySecondaryOperand = secondaryOperand ?? throw new System.ArgumentNullException(nameof(secondaryOperand)); + _lazyExpression = expression ?? throw new System.ArgumentNullException(nameof(expression)); + _lazyWhenNull = whenNull ?? throw new System.ArgumentNullException(nameof(whenNull)); } - protected override IOperation PrimaryOperandImpl => _lazyPrimaryOperand.Value; + protected override IOperation ExpressionImpl => _lazyExpression.Value; - protected override IOperation SecondaryOperandImpl => _lazySecondaryOperand.Value; + protected override IOperation WhenNullImpl => _lazyWhenNull.Value; } /// @@ -4266,67 +4251,6 @@ internal sealed partial class LazySyntheticLocalReferenceExpression : BaseSynthe } } - /// - /// Represents a C# throw or a VB Throw statement. - /// - internal abstract partial class BaseThrowStatement : Operation, IThrowStatement - { - protected BaseThrowStatement(SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(OperationKind.ThrowStatement, semanticModel, syntax, type, constantValue, isImplicit) - { - } - - protected abstract IOperation ThrownObjectImpl { get; } - public override IEnumerable Children - { - get - { - yield return ThrownObject; - } - } - /// - /// Value to be thrown. - /// - public IOperation ThrownObject => Operation.SetParentOperation(ThrownObjectImpl, this); - public override void Accept(OperationVisitor visitor) - { - visitor.VisitThrowStatement(this); - } - public override TResult Accept(OperationVisitor visitor, TArgument argument) - { - return visitor.VisitThrowStatement(this, argument); - } - } - - /// - /// Represents a C# throw or a VB Throw statement. - /// - internal sealed partial class ThrowStatement : BaseThrowStatement, IThrowStatement - { - public ThrowStatement(IOperation thrownObject, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(semanticModel, syntax, type, constantValue, isImplicit) - { - ThrownObjectImpl = thrownObject; - } - - protected override IOperation ThrownObjectImpl { get; } - } - - /// - /// Represents a C# throw or a VB Throw statement. - /// - internal sealed partial class LazyThrowStatement : BaseThrowStatement, IThrowStatement - { - private readonly Lazy _lazyThrownObject; - - public LazyThrowStatement(Lazy thrownObject, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(semanticModel, syntax, type, constantValue, isImplicit) - { - _lazyThrownObject = thrownObject ?? throw new System.ArgumentNullException(nameof(thrownObject)); - } - - protected override IOperation ThrownObjectImpl => _lazyThrownObject.Value; - } - /// /// Represents a C# try or a VB Try statement. /// diff --git a/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs b/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs index 08ac4dcd6c0c0..929f6ce36efa0 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/EnumerableExtensions.cs @@ -3,9 +3,11 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; +using Microsoft.CodeAnalysis.PooledObjects; namespace Roslyn.Utilities { @@ -242,6 +244,19 @@ public static IEnumerable WhereNotNull(this IEnumerable source) return source.Where((Func)s_notNullTest); } + public static ImmutableArray SelectAsArray(this IEnumerable source, Func selector) + { + if (source == null) + { + return ImmutableArray.Empty; + } + + var builder = ArrayBuilder.GetInstance(); + builder.AddRange(source.Select(selector)); + + return builder.ToImmutableAndFree(); + } + public static bool All(this IEnumerable source) { if (source == null) diff --git a/src/Compilers/Core/Portable/Operations/ILambdaExpression.cs b/src/Compilers/Core/Portable/Operations/IAnonymousFunctionExpression.cs similarity index 67% rename from src/Compilers/Core/Portable/Operations/ILambdaExpression.cs rename to src/Compilers/Core/Portable/Operations/IAnonymousFunctionExpression.cs index d39c83b44bca9..580502bc74737 100644 --- a/src/Compilers/Core/Portable/Operations/ILambdaExpression.cs +++ b/src/Compilers/Core/Portable/Operations/IAnonymousFunctionExpression.cs @@ -5,20 +5,20 @@ namespace Microsoft.CodeAnalysis.Semantics { /// - /// Represents a lambda expression. + /// Represents an anonymous function expression, such as a lambda or anonymous delegate. /// /// /// This interface is reserved for implementation by its associated APIs. We reserve the right to /// change it in the future. /// - public interface ILambdaExpression : IOperation + public interface IAnonymousFunctionExpression : IOperation { /// - /// Signature of the lambda. + /// Symbol of the anonymous function. /// - IMethodSymbol Signature { get; } + IMethodSymbol Symbol { get; } /// - /// Body of the lambda. + /// Body of the anonymous function. /// IBlockStatement Body { get; } } diff --git a/src/Compilers/Core/Portable/Operations/INullCoalescingExpression.cs b/src/Compilers/Core/Portable/Operations/ICoalesceExpression.cs similarity index 75% rename from src/Compilers/Core/Portable/Operations/INullCoalescingExpression.cs rename to src/Compilers/Core/Portable/Operations/ICoalesceExpression.cs index 9f64b19bf8df0..197933ede9db0 100644 --- a/src/Compilers/Core/Portable/Operations/INullCoalescingExpression.cs +++ b/src/Compilers/Core/Portable/Operations/ICoalesceExpression.cs @@ -11,16 +11,16 @@ namespace Microsoft.CodeAnalysis.Semantics /// This interface is reserved for implementation by its associated APIs. We reserve the right to /// change it in the future. /// - public interface INullCoalescingExpression : IOperation + public interface ICoalesceExpression : IOperation { /// /// Value to be unconditionally evaluated. /// - IOperation PrimaryOperand { get; } + IOperation Expression { get; } /// - /// Value to be evaluated if Primary evaluates to null/Nothing. + /// Value to be evaluated if evaluates to null/Nothing. /// - IOperation SecondaryOperand { get; } + IOperation WhenNull { get; } } } diff --git a/src/Compilers/Core/Portable/Operations/ILockStatement.cs b/src/Compilers/Core/Portable/Operations/ILockStatement.cs index 7d1c893782837..d433f2c709af5 100644 --- a/src/Compilers/Core/Portable/Operations/ILockStatement.cs +++ b/src/Compilers/Core/Portable/Operations/ILockStatement.cs @@ -14,9 +14,9 @@ namespace Microsoft.CodeAnalysis.Semantics public interface ILockStatement : IOperation { /// - /// Value to be locked. + /// Expression producing a value to be locked. /// - IOperation LockedObject { get; } + IOperation Expression { get; } /// /// Body of the lock, to be executed while holding the lock. /// diff --git a/src/Compilers/Core/Portable/Operations/IThrowStatement.cs b/src/Compilers/Core/Portable/Operations/IThrowStatement.cs deleted file mode 100644 index e77669ae6ea93..0000000000000 --- a/src/Compilers/Core/Portable/Operations/IThrowStatement.cs +++ /dev/null @@ -1,22 +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.Collections.Immutable; - -namespace Microsoft.CodeAnalysis.Semantics -{ - /// - /// Represents a C# throw or a VB Throw statement. - /// - /// - /// This interface is reserved for implementation by its associated APIs. We reserve the right to - /// change it in the future. - /// - public interface IThrowStatement : IOperation - { - /// - /// Value to be thrown. - /// - IOperation ThrownObject { get; } - } -} - diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index e889bc7ca15fd..8adc6f487f9e4 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -119,11 +119,6 @@ public override IOperation VisitEmptyStatement(IEmptyStatement operation, object return new EmptyStatement(((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } - public override IOperation VisitThrowStatement(IThrowStatement operation, object argument) - { - return new ThrowStatement(Visit(operation.ThrownObject), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); - } - public override IOperation VisitReturnStatement(IReturnStatement operation, object argument) { return new ReturnStatement(operation.Kind, Visit(operation.ReturnedValue), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); @@ -131,7 +126,7 @@ public override IOperation VisitReturnStatement(IReturnStatement operation, obje public override IOperation VisitLockStatement(ILockStatement operation, object argument) { - return new LockStatement(Visit(operation.LockedObject), Visit(operation.Body), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new LockStatement(Visit(operation.Expression), Visit(operation.Body), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitTryStatement(ITryStatement operation, object argument) @@ -274,9 +269,9 @@ public override IOperation VisitConditionalChoiceExpression(IConditionalChoiceEx return new ConditionalChoiceExpression(Visit(operation.Condition), Visit(operation.IfTrueValue), Visit(operation.IfFalseValue), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } - public override IOperation VisitNullCoalescingExpression(INullCoalescingExpression operation, object argument) + public override IOperation VisitCoalesceExpression(ICoalesceExpression operation, object argument) { - return new NullCoalescingExpression(Visit(operation.PrimaryOperand), Visit(operation.SecondaryOperand), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new CoalesceExpression(Visit(operation.Expression), Visit(operation.WhenNull), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitIsTypeExpression(IIsTypeExpression operation, object argument) @@ -294,9 +289,9 @@ public override IOperation VisitTypeOfExpression(ITypeOfExpression operation, ob return new TypeOfExpression(operation.TypeOperand, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } - public override IOperation VisitLambdaExpression(ILambdaExpression operation, object argument) + public override IOperation VisitAnonymousFunctionExpression(IAnonymousFunctionExpression operation, object argument) { - return new LambdaExpression(operation.Signature, Visit(operation.Body), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new AnonymousFunctionExpression(operation.Symbol, Visit(operation.Body), ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitLiteralExpression(ILiteralExpression operation, object argument) diff --git a/src/Compilers/Core/Portable/Operations/OperationKind.cs b/src/Compilers/Core/Portable/Operations/OperationKind.cs index f0a17227330cd..bb279bbb78fed 100644 --- a/src/Compilers/Core/Portable/Operations/OperationKind.cs +++ b/src/Compilers/Core/Portable/Operations/OperationKind.cs @@ -31,8 +31,7 @@ public enum OperationKind BranchStatement = 0x8, /// Indicates an . EmptyStatement = 0x9, - /// Indicates an . - ThrowStatement = 0xa, + // 0xa open for usage, was IThrowStatement. /// Indicates an . ReturnStatement = 0xb, /// Indicates an . @@ -96,10 +95,10 @@ public enum OperationKind BinaryOperatorExpression = 0x10e, /// Indicates an . ConditionalChoiceExpression = 0x10f, - /// Indicates an . - NullCoalescingExpression = 0x110, - /// Indicates an . - LambdaExpression = 0x111, + /// Indicates an . + CoalesceExpression = 0x110, + /// Indicates an . + AnonymousFunctionExpression = 0x111, /// Indicates an . ObjectCreationExpression = 0x112, /// Indicates an . diff --git a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs index 56c1f3b4db093..67c08801e9739 100644 --- a/src/Compilers/Core/Portable/Operations/OperationVisitor.cs +++ b/src/Compilers/Core/Portable/Operations/OperationVisitor.cs @@ -110,11 +110,6 @@ public virtual void VisitEmptyStatement(IEmptyStatement operation) DefaultVisit(operation); } - public virtual void VisitThrowStatement(IThrowStatement operation) - { - DefaultVisit(operation); - } - public virtual void VisitReturnStatement(IReturnStatement operation) { DefaultVisit(operation); @@ -270,7 +265,7 @@ public virtual void VisitConditionalChoiceExpression(IConditionalChoiceExpressio DefaultVisit(operation); } - public virtual void VisitNullCoalescingExpression(INullCoalescingExpression operation) + public virtual void VisitCoalesceExpression(ICoalesceExpression operation) { DefaultVisit(operation); } @@ -290,7 +285,7 @@ public virtual void VisitTypeOfExpression(ITypeOfExpression operation) DefaultVisit(operation); } - public virtual void VisitLambdaExpression(ILambdaExpression operation) + public virtual void VisitAnonymousFunctionExpression(IAnonymousFunctionExpression operation) { DefaultVisit(operation); } @@ -580,11 +575,6 @@ public virtual TResult VisitEmptyStatement(IEmptyStatement operation, TArgument return DefaultVisit(operation, argument); } - public virtual TResult VisitThrowStatement(IThrowStatement operation, TArgument argument) - { - return DefaultVisit(operation, argument); - } - public virtual TResult VisitReturnStatement(IReturnStatement operation, TArgument argument) { return DefaultVisit(operation, argument); @@ -740,7 +730,7 @@ public virtual TResult VisitConditionalChoiceExpression(IConditionalChoiceExpres return DefaultVisit(operation, argument); } - public virtual TResult VisitNullCoalescingExpression(INullCoalescingExpression operation, TArgument argument) + public virtual TResult VisitCoalesceExpression(ICoalesceExpression operation, TArgument argument) { return DefaultVisit(operation, argument); } @@ -760,7 +750,7 @@ public virtual TResult VisitTypeOfExpression(ITypeOfExpression operation, TArgum return DefaultVisit(operation, argument); } - public virtual TResult VisitLambdaExpression(ILambdaExpression operation, TArgument argument) + public virtual TResult VisitAnonymousFunctionExpression(IAnonymousFunctionExpression operation, TArgument argument) { return DefaultVisit(operation, argument); } diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 0e096aad6bcb9..8af4797ee56eb 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -91,7 +91,7 @@ Microsoft.CodeAnalysis.OperationKind.InvocationExpression = 259 -> Microsoft.Cod Microsoft.CodeAnalysis.OperationKind.IsPatternExpression = 517 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.IsTypeExpression = 278 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LabelStatement = 7 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.OperationKind.LambdaExpression = 273 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.AnonymousFunctionExpression = 273 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LiteralExpression = 257 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LocalFunctionStatement = 49 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.LocalReferenceExpression = 261 -> Microsoft.CodeAnalysis.OperationKind @@ -101,7 +101,7 @@ Microsoft.CodeAnalysis.OperationKind.MemberInitializerExpression = 289 -> Micros Microsoft.CodeAnalysis.OperationKind.MethodBindingExpression = 265 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.NameOfExpression = 291 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.None = 0 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.OperationKind.NullCoalescingExpression = 272 -> Microsoft.CodeAnalysis.OperationKind +Microsoft.CodeAnalysis.OperationKind.CoalesceExpression = 272 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ObjectCreationExpression = 274 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ObjectOrCollectionInitializerExpression = 288 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.OmittedArgumentExpression = 768 -> Microsoft.CodeAnalysis.OperationKind @@ -124,7 +124,6 @@ Microsoft.CodeAnalysis.OperationKind.SwitchCase = 1033 -> Microsoft.CodeAnalysis Microsoft.CodeAnalysis.OperationKind.SwitchStatement = 4 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.SyntheticLocalReferenceExpression = 263 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.ThrowExpression = 519 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.OperationKind.ThrowStatement = 10 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.TryStatement = 14 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.TupleExpression = 292 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.OperationKind.TypeOfExpression = 513 -> Microsoft.CodeAnalysis.OperationKind @@ -485,9 +484,9 @@ Microsoft.CodeAnalysis.Semantics.IIsTypeExpression.Operand.get -> Microsoft.Code Microsoft.CodeAnalysis.Semantics.ILabelStatement Microsoft.CodeAnalysis.Semantics.ILabelStatement.Label.get -> Microsoft.CodeAnalysis.ILabelSymbol Microsoft.CodeAnalysis.Semantics.ILabelStatement.LabeledStatement.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.ILambdaExpression -Microsoft.CodeAnalysis.Semantics.ILambdaExpression.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement -Microsoft.CodeAnalysis.Semantics.ILambdaExpression.Signature.get -> Microsoft.CodeAnalysis.IMethodSymbol +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement +Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression.Symbol.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.ILiteralExpression Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement @@ -496,7 +495,7 @@ Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression.Local.get -> Microsoft.CodeAnalysis.ILocalSymbol Microsoft.CodeAnalysis.Semantics.ILockStatement Microsoft.CodeAnalysis.Semantics.ILockStatement.Body.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.ILockStatement.LockedObject.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.ILockStatement.Expression.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ILoopStatement Microsoft.CodeAnalysis.Semantics.ILoopStatement.Body.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ILoopStatement.LoopKind.get -> Microsoft.CodeAnalysis.Semantics.LoopKind @@ -511,9 +510,9 @@ Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression.IsVirtual.get -> bool Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression.Method.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.INameOfExpression Microsoft.CodeAnalysis.Semantics.INameOfExpression.Argument.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.INullCoalescingExpression -Microsoft.CodeAnalysis.Semantics.INullCoalescingExpression.PrimaryOperand.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.INullCoalescingExpression.SecondaryOperand.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.Expression.get -> Microsoft.CodeAnalysis.IOperation +Microsoft.CodeAnalysis.Semantics.ICoalesceExpression.WhenNull.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression.Constructor.get -> Microsoft.CodeAnalysis.IMethodSymbol Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression.Initializer.get -> Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression @@ -564,8 +563,6 @@ Microsoft.CodeAnalysis.Semantics.ISyntheticLocalReferenceExpression Microsoft.CodeAnalysis.Semantics.ISyntheticLocalReferenceExpression.SyntheticLocalKind.get -> Microsoft.CodeAnalysis.Semantics.SyntheticLocalKind Microsoft.CodeAnalysis.Semantics.IThrowExpression Microsoft.CodeAnalysis.Semantics.IThrowExpression.Expression.get -> Microsoft.CodeAnalysis.IOperation -Microsoft.CodeAnalysis.Semantics.IThrowStatement -Microsoft.CodeAnalysis.Semantics.IThrowStatement.ThrownObject.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.ITryStatement Microsoft.CodeAnalysis.Semantics.ITryStatement.Body.get -> Microsoft.CodeAnalysis.Semantics.IBlockStatement Microsoft.CodeAnalysis.Semantics.ITryStatement.Catches.get -> System.Collections.Immutable.ImmutableArray @@ -819,7 +816,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitInvocationExpress virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation) -> void -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation) -> void @@ -827,7 +824,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLockStatement(Mic virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMemberInitializerExpression(Microsoft.CodeAnalysis.Semantics.IMemberInitializerExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMethodBindingExpression(Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNameOfExpression(Microsoft.CodeAnalysis.Semantics.INameOfExpression operation) -> void -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNullCoalescingExpression(Microsoft.CodeAnalysis.Semantics.INullCoalescingExpression operation) -> void +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectOrCollectionInitializerExpression(Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitOmittedArgumentExpression(Microsoft.CodeAnalysis.Semantics.IOmittedArgumentExpression operation) -> void @@ -850,7 +847,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSwitchCase(Micros virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSwitchStatement(Microsoft.CodeAnalysis.Semantics.ISwitchStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSyntheticLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ISyntheticLocalReferenceExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitThrowExpression(Microsoft.CodeAnalysis.Semantics.IThrowExpression operation) -> void -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitThrowStatement(Microsoft.CodeAnalysis.Semantics.IThrowStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTryStatement(Microsoft.CodeAnalysis.Semantics.ITryStatement operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTupleExpression(Microsoft.CodeAnalysis.Semantics.ITupleExpression operation) -> void virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTypeOfExpression(Microsoft.CodeAnalysis.Semantics.ITypeOfExpression operation) -> void @@ -909,7 +905,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsPatternExpression(Microsoft.CodeAnalysis.Semantics.IIsPatternExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitIsTypeExpression(Microsoft.CodeAnalysis.Semantics.IIsTypeExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLabelStatement(Microsoft.CodeAnalysis.Semantics.ILabelStatement operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLambdaExpression(Microsoft.CodeAnalysis.Semantics.ILambdaExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitAnonymousFunctionExpression(Microsoft.CodeAnalysis.Semantics.IAnonymousFunctionExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLiteralExpression(Microsoft.CodeAnalysis.Semantics.ILiteralExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalFunctionStatement(Microsoft.CodeAnalysis.Semantics.ILocalFunctionStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ILocalReferenceExpression operation, TArgument argument) -> TResult @@ -917,7 +913,7 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMemberInitializerExpression(Microsoft.CodeAnalysis.Semantics.IMemberInitializerExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitMethodBindingExpression(Microsoft.CodeAnalysis.Semantics.IMethodBindingExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNameOfExpression(Microsoft.CodeAnalysis.Semantics.INameOfExpression operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitNullCoalescingExpression(Microsoft.CodeAnalysis.Semantics.INullCoalescingExpression operation, TArgument argument) -> TResult +virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitCoalesceExpression(Microsoft.CodeAnalysis.Semantics.ICoalesceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectCreationExpression(Microsoft.CodeAnalysis.Semantics.IObjectCreationExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitObjectOrCollectionInitializerExpression(Microsoft.CodeAnalysis.Semantics.IObjectOrCollectionInitializerExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitOmittedArgumentExpression(Microsoft.CodeAnalysis.Semantics.IOmittedArgumentExpression operation, TArgument argument) -> TResult @@ -940,7 +936,6 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.Vi virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSwitchStatement(Microsoft.CodeAnalysis.Semantics.ISwitchStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitSyntheticLocalReferenceExpression(Microsoft.CodeAnalysis.Semantics.ISyntheticLocalReferenceExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitThrowExpression(Microsoft.CodeAnalysis.Semantics.IThrowExpression operation, TArgument argument) -> TResult -virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitThrowStatement(Microsoft.CodeAnalysis.Semantics.IThrowStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTryStatement(Microsoft.CodeAnalysis.Semantics.ITryStatement operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTupleExpression(Microsoft.CodeAnalysis.Semantics.ITupleExpression operation, TArgument argument) -> TResult virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor.VisitTypeOfExpression(Microsoft.CodeAnalysis.Semantics.ITypeOfExpression operation, TArgument argument) -> TResult diff --git a/src/Compilers/Extension/CompilerExtension.csproj b/src/Compilers/Extension/CompilerExtension.csproj index 864ce605cc9a0..ab9465b39cab3 100644 --- a/src/Compilers/Extension/CompilerExtension.csproj +++ b/src/Compilers/Extension/CompilerExtension.csproj @@ -128,6 +128,7 @@ + diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index 21988b54e960d..6bc718abb7245 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -338,14 +338,14 @@ Namespace Microsoft.CodeAnalysis.Semantics Return New LazyNameOfExpression(argument, _semanticModel, syntax, type, constantValue, isImplicit) End Function - Private Function CreateBoundLambdaOperation(boundLambda As BoundLambda) As ILambdaExpression - Dim signature As IMethodSymbol = boundLambda.LambdaSymbol + Private Function CreateBoundLambdaOperation(boundLambda As BoundLambda) As IAnonymousFunctionExpression + Dim symbol As IMethodSymbol = boundLambda.LambdaSymbol Dim body As Lazy(Of IBlockStatement) = New Lazy(Of IBlockStatement)(Function() DirectCast(Create(boundLambda.Body), IBlockStatement)) Dim syntax As SyntaxNode = boundLambda.Syntax Dim type As ITypeSymbol = boundLambda.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundLambda.ConstantValueOpt) Dim isImplicit As Boolean = boundLambda.WasCompilerGenerated - Return New LazyLambdaExpression(signature, body, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyAnonymousFunctionExpression(symbol, body, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundCallOperation(boundCall As BoundCall) As IInvocationExpression @@ -459,14 +459,14 @@ Namespace Microsoft.CodeAnalysis.Semantics Return New LazyBinaryOperatorExpression(binaryOperationKind, leftOperand, rightOperand, isLifted, usesOperatorMethod, operatorMethod, _semanticModel, syntax, type, constantValue, isImplicit) End Function - Private Function CreateBoundBinaryConditionalExpressionOperation(boundBinaryConditionalExpression As BoundBinaryConditionalExpression) As INullCoalescingExpression - Dim primaryOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryConditionalExpression.TestExpression)) - Dim secondaryOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryConditionalExpression.ElseExpression)) + Private Function CreateBoundBinaryConditionalExpressionOperation(boundBinaryConditionalExpression As BoundBinaryConditionalExpression) As ICoalesceExpression + Dim expression As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryConditionalExpression.TestExpression)) + Dim whenNull As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundBinaryConditionalExpression.ElseExpression)) Dim syntax As SyntaxNode = boundBinaryConditionalExpression.Syntax Dim type As ITypeSymbol = boundBinaryConditionalExpression.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundBinaryConditionalExpression.ConstantValueOpt) Dim isImplicit As Boolean = boundBinaryConditionalExpression.WasCompilerGenerated - Return New LazyNullCoalescingExpression(primaryOperand, secondaryOperand, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyCoalesceExpression(expression, whenNull, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundUserDefinedShortCircuitingOperatorOperation(boundUserDefinedShortCircuitingOperator As BoundUserDefinedShortCircuitingOperator) As IBinaryOperatorExpression @@ -1020,13 +1020,15 @@ Namespace Microsoft.CodeAnalysis.Semantics Return New LazyReturnStatement(OperationKind.ReturnStatement, returnedValue, _semanticModel, syntax, type, constantValue, isImplicit) End Function - Private Function CreateBoundThrowStatementOperation(boundThrowStatement As BoundThrowStatement) As IThrowStatement + Private Function CreateBoundThrowStatementOperation(boundThrowStatement As BoundThrowStatement) As IExpressionStatement Dim thrownObject As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundThrowStatement.ExpressionOpt)) Dim syntax As SyntaxNode = boundThrowStatement.Syntax - Dim type As ITypeSymbol = Nothing + Dim expressionType As ITypeSymbol = boundThrowStatement.ExpressionOpt?.Type + Dim statementType As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundThrowStatement.WasCompilerGenerated - Return New LazyThrowStatement(thrownObject, _semanticModel, syntax, type, constantValue, isImplicit) + Dim throwExpression As IOperation = New LazyThrowExpression(thrownObject, _semanticModel, syntax, expressionType, constantValue, isImplicit) + Return New ExpressionStatement(throwExpression, _semanticModel, syntax, statementType, constantValue, isImplicit) End Function Private Function CreateBoundWhileStatementOperation(boundWhileStatement As BoundWhileStatement) As IWhileUntilLoopStatement @@ -1101,13 +1103,13 @@ Namespace Microsoft.CodeAnalysis.Semantics End Function Private Function CreateBoundSyncLockStatementOperation(boundSyncLockStatement As BoundSyncLockStatement) As ILockStatement - Dim lockedObject As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSyncLockStatement.LockExpression)) + Dim expression As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSyncLockStatement.LockExpression)) Dim body As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundSyncLockStatement.Body)) Dim syntax As SyntaxNode = boundSyncLockStatement.Syntax Dim type As ITypeSymbol = Nothing Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)() Dim isImplicit As Boolean = boundSyncLockStatement.WasCompilerGenerated - Return New LazyLockStatement(lockedObject, body, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyLockStatement(expression, body, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundNoOpStatementOperation(boundNoOpStatement As BoundNoOpStatement) As IEmptyStatement diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb index c31232399d2ff..361e61e4a8647 100644 --- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb +++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb @@ -6277,6 +6277,28 @@ BC37289: Tuple element name 'M' is inferred. Please use language version 15.3 or verifier15_3.VerifyDiagnostics() End Sub + + Public Sub InferredName_Conversion() + Dim source = + +Imports System.Collections.Generic +Class C + Shared Sub F(items As (Integer, IList(Of Object))) + End Sub + Shared Sub Test() + Dim items = New List(Of Object)() + Dim group = (1, items) + F(group) + End Sub +End Class + + + Dim comp = CreateCompilationWithMscorlibAndVBRuntime(source, + additionalRefs:={ValueTupleRef, SystemRuntimeFacadeRef, SystemCoreRef}, + parseOptions:=TestOptions.Regular.WithLanguageVersion(LanguageVersion.VisualBasic15)) + comp.AssertTheseEmitDiagnostics() + End Sub + Public Sub LongTupleWithArgumentEvaluation() @@ -7564,7 +7586,7 @@ BC36625: Lambda expression cannot be converted to 'Integer' because 'Integer' is End Sub - Public Sub TupleInferredLambdStrictOn() + Public Sub TupleInferredLambdaStrictOn() Dim comp = CreateCompilationWithMscorlibAndVBRuntime( @@ -7600,7 +7622,7 @@ BC36642: Option Strict On requires each lambda expression parameter to be declar End Sub - Public Sub TupleInferredLambdStrictOff() + Public Sub TupleInferredLambdaStrictOff() Dim verifier = CompileAndVerify( diff --git a/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingObjectInitializerTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingObjectInitializerTests.vb index 9ff7fdc89d264..09930cbc34cb5 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingObjectInitializerTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Binding/BindingObjectInitializerTests.vb @@ -1125,7 +1125,7 @@ IObjectCreationExpression (Constructor: Sub C1..ctor()) (OperationKind.ObjectCre Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'New C1 With ... d Function}') Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.Int32)) (Syntax: 'Function() ... nd Function') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Int32) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Int32) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.Int32 IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'Return .Field') @@ -1395,7 +1395,7 @@ IObjectCreationExpression (Constructor: Sub C2..ctor()) (OperationKind.ObjectCre Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'As New C2 W ... d Function}') Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.Object)) (Syntax: 'Function()' ... nd Function') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Object) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function()' ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Object) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function()' ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function()' ... nd Function') Locals: Local_1: As System.Object IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'Return .Field') @@ -1412,7 +1412,7 @@ IObjectCreationExpression (Constructor: Sub C2..ctor()) (OperationKind.ObjectCre Instance Receiver: IOperation: (OperationKind.None) (Syntax: 'As New C2 W ... d Function}') Right: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.Object)) (Syntax: 'Function() ... nd Function') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Object) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Object) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.Object IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'Return .Field') diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb index cddb496434752..586832777bf20 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IConversionExpression.vb @@ -758,7 +758,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Action(Of System.Int32) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action(Of System.Int32)) (Syntax: 'Sub(i As In ... End Sub') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Sub (i As System.Int32)) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Sub(i As In ... End Sub') + Operand: IAnonymousFunctionExpression (Symbol: Sub (i As System.Int32)) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Sub(i As In ... End Sub') IBlockStatement (2 statements) (OperationKind.BlockStatement) (Syntax: 'Sub(i As In ... End Sub') ILabelStatement (Label: exit) (OperationKind.LabelStatement) (Syntax: 'End Sub') LabeledStatement: null @@ -791,7 +791,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Action(Of System.Int32) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action(Of System.Int32)) (Syntax: 'Sub()'BIND: ... End Sub') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Sub ()) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Sub()'BIND: ... End Sub') + Operand: IAnonymousFunctionExpression (Symbol: Sub ()) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Sub()'BIND: ... End Sub') IBlockStatement (2 statements) (OperationKind.BlockStatement) (Syntax: 'Sub()'BIND: ... End Sub') ILabelStatement (Label: exit) (OperationKind.LabelStatement) (Syntax: 'End Sub') LabeledStatement: null @@ -824,7 +824,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Action Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: 'Sub(i As In ... End Sub') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Sub (i As System.Int32)) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Sub(i As In ... End Sub') + Operand: IAnonymousFunctionExpression (Symbol: Sub (i As System.Int32)) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Sub(i As In ... End Sub') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Sub(i As In ... End Sub') ILabelStatement (Label: exit) (OperationKind.LabelStatement, IsInvalid) (Syntax: 'End Sub') LabeledStatement: null @@ -862,7 +862,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Func(Of System.Int64) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.Int64)) (Syntax: 'Function() ... nd Function') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Int32) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Int32) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.Int32 IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'Return 1') @@ -898,7 +898,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Action(Of System.Int32) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Action(Of System.Int32)) (Syntax: 'Function() ... nd Function') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Int32) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Int32) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.Int32 IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'Return 1') @@ -933,7 +933,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: a As System.Func(Of System.Int32) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.Int32), IsInvalid) (Syntax: 'Sub()'BIND: ... End Sub') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Sub ()) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Sub()'BIND: ... End Sub') + Operand: IAnonymousFunctionExpression (Symbol: Sub ()) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Sub()'BIND: ... End Sub') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Sub()'BIND: ... End Sub') ILabelStatement (Label: exit) (OperationKind.LabelStatement, IsInvalid) (Syntax: 'End Sub') LabeledStatement: null @@ -2086,7 +2086,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: expr As System.Linq.Expressions.Expression(Of System.Func(Of System.Int32, System.Boolean)) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression(Of System.Func(Of System.Int32, System.Boolean))) (Syntax: 'Function(num) num < 5') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function (num As System.Int32) As System.Boolean) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function(num) num < 5') + Operand: IAnonymousFunctionExpression (Symbol: Function (num As System.Int32) As System.Boolean) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function(num) num < 5') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function(num) num < 5') Locals: Local_1: As System.Boolean IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'num < 5') @@ -2125,7 +2125,7 @@ IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclaratio Variables: Local_1: expr As System.Linq.Expressions.Expression(Of System.Func(Of System.Int32, System.Boolean)) Initializer: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression(Of System.Func(Of System.Int32, System.Boolean)), IsInvalid) (Syntax: 'Function(num) num') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function (num As System.Int32) As System.Boolean) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function(num) num') + Operand: IAnonymousFunctionExpression (Symbol: Function (num As System.Int32) As System.Boolean) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function(num) num') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function(num) num') Locals: Local_1: As System.Boolean IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'num') diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.vb index 53c7109a0e28a..0f3208919e570 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IForEachLoopStatement.vb @@ -751,10 +751,11 @@ IForEachLoopStatement (Iteration variable: null) (LoopKind.ForEach) (OperationKi Left: ILocalReferenceExpression: s (OperationKind.LocalReferenceExpression, Type: System.String) (Syntax: 's') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: "one") (Syntax: '"one"') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'If (s = "on ... End If') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'Throw New Exception') - ThrownObject: IObjectCreationExpression (Constructor: Sub System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New Exception') - Arguments(0) - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Throw New Exception') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'Throw New Exception') + IObjectCreationExpression (Constructor: Sub System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New Exception') + Arguments(0) + Initializer: null IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Console.WriteLine(s)') Expression: IInvocationExpression (Sub System.Console.WriteLine(value As System.String)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'Console.WriteLine(s)') @@ -763,8 +764,7 @@ IForEachLoopStatement (Iteration variable: null) (LoopKind.ForEach) (OperationKi IArgument (ArgumentKind.Explicit, Matching Parameter: value) (OperationKind.Argument) (Syntax: 's') ILocalReferenceExpression: s (OperationKind.LocalReferenceExpression, Type: System.String) (Syntax: 's') InConversion: null - OutConversion: null -]]>.Value + OutConversion: null]]>.Value VerifyOperationTreeForTest(Of ForEachBlockSyntax)(source, expectedOperationTree) End Sub diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ILockStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ILockStatement.vb new file mode 100644 index 0000000000000..cede38039493e --- /dev/null +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ILockStatement.vb @@ -0,0 +1,335 @@ +' 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.Test.Utilities +Imports Microsoft.CodeAnalysis.VisualBasic.Syntax + +Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics + Partial Public Class IOperationTests + Inherits SemanticModelTestBase + + + + Public Sub ILockStatement_ObjectLock_FieldReference() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ObjectLock_LocalReference() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ObjectLock_Nothing() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ObjectLock_NonReferenceType() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_MissingLockExpression() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_InvalidLockExpression() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_MissingEndLock() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ExpressionBody_ObjectCall() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ExpressionLock_ClassMethodCall() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_ExpressionBody_SubMethod() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = .Value + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + + + + Public Sub ILockStatement_NonEmptyBody() + Dim source = .Value + + Dim expectedOperationTree = .Value + + Dim expectedDiagnostics = String.Empty + + VerifyOperationTreeAndDiagnosticsForTest(Of SyncLockBlockSyntax)(source, expectedOperationTree, expectedDiagnostics) + End Sub + End Class +End Namespace diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb index 1628dbcf77c73..92626a6254de9 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IParameterReferenceExpression.vb @@ -379,7 +379,7 @@ End Class]]>.Value Dim expectedOperationTree = As System.Object IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'x') diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.vb index 7fe9c3481bb8f..f8935ee52e10e 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_IWhileUntilLoopStatement.vb @@ -234,14 +234,15 @@ IWhileUntilLoopStatement (IsTopTest: True, IsWhile: True) (LoopKind.WhileUntil) Left: ILocalReferenceExpression: value (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'value') Right: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 100) (Syntax: '100') IfTrue: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'If value > ... End If') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'Throw New S ... occurred.")') - ThrownObject: IObjectCreationExpression (Constructor: Sub System.Exception..ctor(message As System.String)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New System. ... occurred.")') - Arguments(1): - IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '"An excepti ... occurred."') - ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: "An exception has occurred.") (Syntax: '"An excepti ... occurred."') - InConversion: null - OutConversion: null - Initializer: null + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Throw New S ... occurred.")') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'Throw New S ... occurred.")') + IObjectCreationExpression (Constructor: Sub System.Exception..ctor(message As System.String)) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New System. ... occurred.")') + Arguments(1): + IArgument (ArgumentKind.Explicit, Matching Parameter: message) (OperationKind.Argument) (Syntax: '"An excepti ... occurred."') + ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: "An exception has occurred.") (Syntax: '"An excepti ... occurred."') + InConversion: null + OutConversion: null + Initializer: null IfFalse: null IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'System.Cons ... statement")') Expression: IInvocationExpression (Sub System.Console.WriteLine(value As System.String)) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'System.Cons ... statement")') @@ -888,10 +889,11 @@ IWhileUntilLoopStatement (IsTopTest: True, IsWhile: True) (LoopKind.WhileUntil) Operand: ILiteralExpression (OperationKind.LiteralExpression, Type: System.Int32, Constant: 2) (Syntax: '2') Catch clauses(0) Finally: IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'Finally ... Exception()') - IThrowStatement (OperationKind.ThrowStatement) (Syntax: 'Throw New S ... Exception()') - ThrownObject: IObjectCreationExpression (Constructor: Sub System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New System.Exception()') - Arguments(0) - Initializer: null]]>.Value + IExpressionStatement (OperationKind.ExpressionStatement) (Syntax: 'Throw New S ... Exception()') + Expression: IThrowExpression (OperationKind.ThrowExpression, Type: System.Exception) (Syntax: 'Throw New S ... Exception()') + IObjectCreationExpression (Constructor: Sub System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'New System.Exception()') + Arguments(0) + Initializer: null]]>.Value VerifyOperationTreeForTest(Of WhileBlockSyntax)(source, expectedOperationTree) End Sub diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_InvalidExpression.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_InvalidExpression.vb index 14dd4141127e8..8b0d845b21d95 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_InvalidExpression.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_InvalidExpression.vb @@ -278,7 +278,7 @@ End Class]]>.Value Dim expectedOperationTree = () As ?, IsInvalid) (Syntax: 'Function() F()') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As ?) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() F()') + Operand: IAnonymousFunctionExpression (Symbol: Function () As ?) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() F()') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() F()') Locals: Local_1: As ? IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'F()') diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/AnonymousTypesTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/AnonymousTypesTests.vb index edf6d9f77752b..5c3363c05ba0d 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/AnonymousTypesTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/AnonymousTypesTests.vb @@ -812,7 +812,7 @@ Module Program End Sub End Module]]>.Value - ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within ILambdaExpression. + ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within IAnonymousFunctionExpression. ' See https://github.com/dotnet/roslyn/issues/20357. Dim expectedOperationTree = , IsInvalid) (Syntax: 'New With {' ... ).Invoke()}') @@ -827,7 +827,7 @@ IAnonymousObjectCreationExpression (OperationKind.AnonymousObjectCreationExpress Right: IInvocationExpression (virtual Function System.Func(Of System.String).Invoke() As System.String) (OperationKind.InvocationExpression, Type: System.String, IsInvalid) (Syntax: 'DirectCast( ... )).Invoke()') Instance Receiver: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.String), IsInvalid) (Syntax: 'DirectCast( ... Of String))') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.String) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.String) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.String IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'Return .x.ToString()') @@ -864,7 +864,7 @@ Module Program End Sub End Module]]>.Value - ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within ILambdaExpression. + ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within IAnonymousFunctionExpression. ' See https://github.com/dotnet/roslyn/issues/20357. Dim expectedOperationTree = , IsInvalid) (Syntax: 'New With {' ... ).Invoke()}') @@ -875,7 +875,7 @@ IAnonymousObjectCreationExpression (OperationKind.AnonymousObjectCreationExpress Right: IInvocationExpression (virtual Function System.Func(Of System.String).Invoke() As System.String) (OperationKind.InvocationExpression, Type: System.String, IsInvalid) (Syntax: 'DirectCast( ... )).Invoke()') Instance Receiver: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.String), IsInvalid) (Syntax: 'DirectCast( ... Of String))') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.String) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.String) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.String IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'Return .a.ToString()') @@ -918,7 +918,7 @@ Module Program End Sub End Module]]>.Value - ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within ILambdaExpression. + ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within IAnonymousFunctionExpression. ' See https://github.com/dotnet/roslyn/issues/20357. Dim expectedOperationTree = , IsInvalid) (Syntax: 'New With {' ... ).Invoke()}') @@ -929,7 +929,7 @@ IAnonymousObjectCreationExpression (OperationKind.AnonymousObjectCreationExpress Right: IInvocationExpression (virtual Function System.Func(Of System.String).Invoke() As System.String) (OperationKind.InvocationExpression, Type: System.String, IsInvalid) (Syntax: 'DirectCast( ... )).Invoke()') Instance Receiver: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.String), IsInvalid) (Syntax: 'DirectCast( ... Of String))') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.String) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.String) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.String IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'Return .x.ToString()') @@ -974,7 +974,7 @@ Module Program End Sub End Module]]>.Value - ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within ILambdaExpression. + ' The IOperation tree for this test seems to have an unexpected ILocalReferenceExpression within IAnonymousFunctionExpression. ' See https://github.com/dotnet/roslyn/issues/20357. Dim expectedOperationTree = , IsInvalid) (Syntax: 'New With {' ... ).Invoke()}') @@ -985,14 +985,14 @@ IAnonymousObjectCreationExpression (OperationKind.AnonymousObjectCreationExpress Right: IInvocationExpression (virtual Function System.Func(Of System.String).Invoke() As System.String) (OperationKind.InvocationExpression, Type: System.String, IsInvalid) (Syntax: 'DirectCast( ... )).Invoke()') Instance Receiver: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.String), IsInvalid) (Syntax: 'DirectCast( ... Of String))') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.String) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.String) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.String IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'Return Dire ... )).Invoke()') ReturnedValue: IInvocationExpression (virtual Function System.Func(Of System.String).Invoke() As System.String) (OperationKind.InvocationExpression, Type: System.String, IsInvalid) (Syntax: 'DirectCast( ... )).Invoke()') Instance Receiver: IConversionExpression (Explicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: System.Func(Of System.String), IsInvalid) (Syntax: 'DirectCast( ... Of String))') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.String) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.String) (OperationKind.AnonymousFunctionExpression, Type: null, IsInvalid) (Syntax: 'Function() ... nd Function') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'Function() ... nd Function') Locals: Local_1: As System.String IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'Return .x.ToString()') diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTests.vb index 116586952412b..a6c34a3c805d2 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/SelectCaseTests.vb @@ -592,7 +592,7 @@ ISwitchStatement (2 cases) (OperationKind.SwitchStatement) (Syntax: 'Select Case Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) Operand: IConversionExpression (Implicit, TryCast: False, Unchecked) (OperationKind.ConversionExpression, Type: Function () As System.Int32) (Syntax: 'Function() 5') Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null) - Operand: ILambdaExpression (Signature: Function () As System.Int32) (OperationKind.LambdaExpression, Type: null) (Syntax: 'Function() 5') + Operand: IAnonymousFunctionExpression (Symbol: Function () As System.Int32) (OperationKind.AnonymousFunctionExpression, Type: null) (Syntax: 'Function() 5') IBlockStatement (3 statements, 1 locals) (OperationKind.BlockStatement) (Syntax: 'Function() 5') Locals: Local_1: As System.Int32 IReturnStatement (OperationKind.ReturnStatement) (Syntax: '5') diff --git a/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionService.cs b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionService.cs index 6077e22eb3bcb..54a281a955ec3 100644 --- a/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionService.cs +++ b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionService.cs @@ -18,10 +18,5 @@ internal class CSharpGoToDefinitionService : AbstractGoToDefinitionService : base(streamingPresenters) { } - - protected override ISymbol FindRelatedExplicitlyDeclaredSymbol(ISymbol symbol, Compilation compilation) - { - return symbol; - } } } diff --git a/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionSymbolService.cs b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionSymbolService.cs new file mode 100644 index 0000000000000..d87c74057b0eb --- /dev/null +++ b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToDefinitionSymbolService.cs @@ -0,0 +1,20 @@ +// 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.Composition; +using Microsoft.CodeAnalysis.Editor.GoToDefinition; +using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.GoToDefinition +{ + [ExportLanguageService(typeof(IGoToDefinitionSymbolService), LanguageNames.CSharp), Shared] + internal class CSharpGoToDefinitionSymbolService : AbstractGoToDefinitionSymbolService + { + protected override ISymbol FindRelatedExplicitlyDeclaredSymbol(ISymbol symbol, Compilation compilation) + { + return symbol; + } + } +} diff --git a/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToSymbolService.cs b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToSymbolService.cs new file mode 100644 index 0000000000000..dad65c608e34a --- /dev/null +++ b/src/EditorFeatures/CSharp/GoToDefinition/CSharpGoToSymbolService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Composition; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.GoToDefinition; +using Microsoft.CodeAnalysis.Host.Mef; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.GoToDefinition +{ + [ExportLanguageService(typeof(IGoToSymbolService), LanguageNames.CSharp), Shared] + internal class CSharpGoToSymbolService : AbstractGoToSymbolService + { + } +} diff --git a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs index 3ae80b428f51f..9d12f9d4f9cc0 100644 --- a/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs +++ b/src/EditorFeatures/CSharpTest/AddUsing/AddUsingTests_NuGet.cs @@ -257,7 +257,7 @@ public async Task TestFailedInstallRollsBackFile() installerServiceMock.Verify(); } - private Task> CreateSearchResult( + private Task> CreateSearchResult( string packageName, string typeName, ImmutableArray containingNamespaceNames) { return CreateSearchResult(new PackageWithTypeResult( @@ -265,8 +265,8 @@ public async Task TestFailedInstallRollsBackFile() rank: 0, containingNamespaceNames: containingNamespaceNames)); } - private Task> CreateSearchResult(params PackageWithTypeResult[] results) - => Task.FromResult(ImmutableArray.Create(results)); + private Task> CreateSearchResult(params PackageWithTypeResult[] results) + => Task.FromResult>(ImmutableArray.Create(results)); private ImmutableArray CreateNameParts(params string[] parts) => parts.ToImmutableArray(); } diff --git a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs index 16c9b9b7722fe..292557f34f343 100644 --- a/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs +++ b/src/EditorFeatures/CSharpTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.cs @@ -179,6 +179,7 @@ class Class2 { }"; var destinationDocumentText = @"// Banner Text using System; + class Class1 { void Print(int x) @@ -230,6 +231,7 @@ void Print(int x) var destinationDocumentText = @"// Banner Text using System; + class Class1 { void Print(int x) @@ -998,7 +1000,8 @@ static void Main() var expectedDocumentName = "Inner.cs"; var destinationDocumentText = -@"#if true +@" +#if true public class Inner { @@ -1066,5 +1069,111 @@ public class Inner await TestMoveTypeToNewFileAsync( code, codeAfterMove, expectedDocumentName, destinationDocumentText, ignoreTrivia: false); } + + [WorkItem(21456, "https://github.com/dotnet/roslyn/issues/21456")] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)] + public async Task TestLeadingBlankLines1() + { + var code = +@"// Banner Text +using System; + +[||]class Class1 +{ + void Foo() + { + Console.WriteLine(); + } +} + +class Class2 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + var codeAfterMove = @"// Banner Text +using System; + +class Class2 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + + var expectedDocumentName = "Class1.cs"; + var destinationDocumentText = @"// Banner Text +using System; + +class Class1 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + + await TestMoveTypeToNewFileAsync( + code, codeAfterMove, expectedDocumentName, destinationDocumentText); + } + + [WorkItem(21456, "https://github.com/dotnet/roslyn/issues/21456")] + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsMoveType)] + public async Task TestLeadingBlankLines2() + { + var code = +@"// Banner Text +using System; + +class Class1 +{ + void Foo() + { + Console.WriteLine(); + } +} + +[||]class Class2 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + var codeAfterMove = @"// Banner Text +using System; + +class Class1 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + + var expectedDocumentName = "Class2.cs"; + var destinationDocumentText = @"// Banner Text +using System; + +class Class2 +{ + void Foo() + { + Console.WriteLine(); + } +} +"; + + await TestMoveTypeToNewFileAsync( + code, codeAfterMove, expectedDocumentName, destinationDocumentText); + } } } diff --git a/src/EditorFeatures/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs b/src/EditorFeatures/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs new file mode 100644 index 0000000000000..88ca6484e24a6 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.cs @@ -0,0 +1,412 @@ +// 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.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.ReplaceDocCommentTextWithTag; +using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ReplaceDocCommentTextWithTag +{ + public class ReplaceDocCommentTextWithTagTests : AbstractCSharpCodeActionTest + { + protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters) + => new CSharpReplaceDocCommentTextWithTagCodeRefactoringProvider(); + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfKeyword() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable [||]interface. +class C +{ +}", + +@" +/// TKey must implement the System.IDisposable . +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestEndOfKeyword() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable interface[||]. +class C +{ +}", + +@" +/// TKey must implement the System.IDisposable . +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestEndOfKeyword_NewLineFollowing() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable interface[||] +class C +{ +}", + +@" +/// TKey must implement the System.IDisposable +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestSelectedKeyword() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable [|interface|]. +class C +{ +}", + +@" +/// TKey must implement the System.IDisposable . +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestInsideKeyword() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable int[||]erface. +class C +{ +}", + +@" +/// TKey must implement the System.IDisposable . +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestNotInsideKeywordIfNonEmptySpan() + { + await TestMissingAsync( +@" +/// TKey must implement the System.IDisposable int[|erf|]ace +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfFullyQualifiedTypeName_Start() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the [||]System.IDisposable interface. +class C +{ +}", + +@" +/// TKey must implement the interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfFullyQualifiedTypeName_Mid1() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System[||].IDisposable interface. +class C +{ +}", + +@" +/// TKey must implement the interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfFullyQualifiedTypeName_Mid2() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.[||]IDisposable interface. +class C +{ +}", + +@" +/// TKey must implement the interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfFullyQualifiedTypeName_End() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the System.IDisposable[||] interface. +class C +{ +}", + +@" +/// TKey must implement the interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestStartOfFullyQualifiedTypeName_Selected() + { + await TestInRegularAndScriptAsync( +@" +/// TKey must implement the [|System.IDisposable|] interface. +class C +{ +}", + +@" +/// TKey must implement the interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestTypeParameterReference() + { + await TestInRegularAndScriptAsync( +@" +/// [||]TKey must implement the System.IDisposable interface. +class C +{ +}", + +@" +/// must implement the System.IDisposable interface. +class C +{ +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestTypeParameterReference_EmptyClassBody() + { + await TestInRegularAndScriptAsync( +@" +/// [||]TKey must implement the System.IDisposable interface. +class C{}", + +@" +/// must implement the System.IDisposable interface. +class C{}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestCanSeeInnerMethod() + { + await TestInRegularAndScriptAsync( +@" +/// Use WriteLine[||] as a Console.WriteLine replacement +class C +{ + void WriteLine(TKey value) { } +}", + +@" +/// Use as a Console.WriteLine replacement +class C +{ + void WriteLine(TKey value) { } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestNotOnMispelledName() + { + await TestMissingAsync( +@" +/// Use WriteLine1[||] as a Console.WriteLine replacement +class C +{ + void WriteLine(TKey value) { } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodTypeParameterSymbol() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value has type TKey[||] so we don't box primitives. + void WriteLine(TKey value) { } +}", + +@" +class C +{ + /// value has type so we don't box primitives. + void WriteLine(TKey value) { } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodTypeParameterSymbol_EmptyBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value has type TKey[||] so we don't box primitives. + void WriteLine(TKey value){} +}", + +@" +class C +{ + /// value has type so we don't box primitives. + void WriteLine(TKey value){} +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodTypeParameterSymbol_ExpressionBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value has type TKey[||] so we don't box primitives. + object WriteLine(TKey value) => null; +}", + +@" +class C +{ + /// value has type so we don't box primitives. + object WriteLine(TKey value) => null; +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodTypeParameter_SemicolonBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value has type TKey[||] so we don't box primitives. + void WriteLine(TKey value); +}", + +@" +class C +{ + /// value has type so we don't box primitives. + void WriteLine(TKey value); +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodParameterSymbol() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value[||] has type TKey so we don't box primitives. + void WriteLine(TKey value) { } +}", + +@" +class C +{ + /// has type TKey so we don't box primitives. + void WriteLine(TKey value) { } +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodParameterSymbol_EmptyBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value[||] has type TKey so we don't box primitives. + void WriteLine(TKey value){} +}", + +@" +class C +{ + /// has type TKey so we don't box primitives. + void WriteLine(TKey value){} +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodParameterSymbol_ExpressionBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value[||] has type TKey so we don't box primitives. + object WriteLine(TKey value) => null; +}", + +@" +class C +{ + /// has type TKey so we don't box primitives. + object WriteLine(TKey value) => null; +}"); + } + + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsReplaceDocCommentTextWithTag)] + public async Task TestMethodParameterSymbol_SemicolonBody() + { + await TestInRegularAndScriptAsync( +@" +class C +{ + /// value[||] has type TKey so we don't box primitives. + void WriteLine(TKey value); +}", + +@" +class C +{ + /// has type TKey so we don't box primitives. + void WriteLine(TKey value); +}"); + } + + } +} diff --git a/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs b/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs index 3617e587702d8..b67b909c603e9 100644 --- a/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs +++ b/src/EditorFeatures/Core/FindReferences/FindReferencesCommandHandler.cs @@ -53,15 +53,23 @@ public CommandState GetCommandState(FindReferencesCommandArgs args, Func= 0) + // Get the selection that user has in our buffer (this also works if there + // is no selection and the caret is just at a single position). If we + // can't get the selection, or there are multiple spans for it (i.e. a + // box selection), then don't do anything. + var snapshotSpans = args.TextView.Selection.GetSnapshotSpansOnBuffer(args.SubjectBuffer); + if (snapshotSpans.Count == 1) { + var selectedSpan = snapshotSpans[0]; var snapshot = args.SubjectBuffer.CurrentSnapshot; var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document != null) { - if (TryExecuteCommand(caretPosition, document)) + // Do a find-refs at the *start* of the selection. That way if the + // user has selected a symbol that has another symbol touching it + // on the right (i.e. Goo++ ), then we'll do the find-refs on the + // symbol selected, not the symbol following. + if (TryExecuteCommand(selectedSpan.Start, document)) { return; } diff --git a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionService.cs b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionService.cs index e96091c18688b..0181b7c8ef9a7 100644 --- a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionService.cs +++ b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionService.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Editor.Host; -using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Navigation; using Microsoft.CodeAnalysis.Shared.Extensions; @@ -18,42 +17,17 @@ internal abstract class AbstractGoToDefinitionService : IGoToDefinitionService { private readonly IEnumerable> _streamingPresenters; - protected abstract ISymbol FindRelatedExplicitlyDeclaredSymbol(ISymbol symbol, Compilation compilation); - protected AbstractGoToDefinitionService( IEnumerable> streamingPresenters) { _streamingPresenters = streamingPresenters; } - private async Task FindSymbolAsync(Document document, int position, CancellationToken cancellationToken) - { - if (!document.SupportsSemanticModel) - { - return null; - } - - var workspace = document.Project.Solution.Workspace; - - var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync(semanticModel, position, workspace, cancellationToken).ConfigureAwait(false); - - // prefer references to declarations. It's more likely that the user is attempting to - // go to a definition at some other location, rather than the definition they're on. - // This can happen when a token is at a location that is both a reference and a definition. - // For example, on an anonymous type member declaration. - var symbol = semanticInfo.AliasSymbol ?? - semanticInfo.ReferencedSymbols.FirstOrDefault() ?? - semanticInfo.DeclaredSymbol ?? - semanticInfo.Type; - - return FindRelatedExplicitlyDeclaredSymbol(symbol, semanticModel.Compilation); - } - public async Task> FindDefinitionsAsync( Document document, int position, CancellationToken cancellationToken) { - var symbol = await FindSymbolAsync(document, position, cancellationToken).ConfigureAwait(false); + var symbolService = document.GetLanguageService(); + var (symbol, span) = await symbolService.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).ConfigureAwait(false); // Try to compute source definitions from symbol. var items = symbol != null @@ -68,7 +42,8 @@ private async Task FindSymbolAsync(Document document, int position, Can public bool TryGoToDefinition(Document document, int position, CancellationToken cancellationToken) { // First try to compute the referenced symbol and attempt to go to definition for the symbol. - var symbol = FindSymbolAsync(document, position, cancellationToken).WaitAndGetResult(cancellationToken); + var symbolService = document.GetLanguageService(); + var (symbol, span) = symbolService.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).WaitAndGetResult(cancellationToken); if (symbol == null) { return false; diff --git a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionSymbolService.cs b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionSymbolService.cs new file mode 100644 index 0000000000000..f6c7eece0f552 --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToDefinitionSymbolService.cs @@ -0,0 +1,34 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.FindSymbols; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.Editor.GoToDefinition +{ + internal abstract class AbstractGoToDefinitionSymbolService : IGoToDefinitionSymbolService + { + protected abstract ISymbol FindRelatedExplicitlyDeclaredSymbol(ISymbol symbol, Compilation compilation); + + public async Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken) + { + var workspace = document.Project.Solution.Workspace; + + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync(semanticModel, position, workspace, cancellationToken).ConfigureAwait(false); + + // prefer references to declarations. It's more likely that the user is attempting to + // go to a definition at some other location, rather than the definition they're on. + // This can happen when a token is at a location that is both a reference and a definition. + // For example, on an anonymous type member declaration. + var symbol = semanticInfo.AliasSymbol ?? + semanticInfo.ReferencedSymbols.FirstOrDefault() ?? + semanticInfo.DeclaredSymbol ?? + semanticInfo.Type; + + return (FindRelatedExplicitlyDeclaredSymbol(symbol, semanticModel.Compilation), semanticInfo.Span); + } + } +} diff --git a/src/EditorFeatures/Core/GoToDefinition/AbstractGoToSymbolService.cs b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToSymbolService.cs new file mode 100644 index 0000000000000..4e0488a7485bc --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/AbstractGoToSymbolService.cs @@ -0,0 +1,43 @@ +// 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.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; +using Microsoft.CodeAnalysis.Shared.Extensions; + +namespace Microsoft.CodeAnalysis.Editor.GoToDefinition +{ + internal abstract class AbstractGoToSymbolService : ForegroundThreadAffinitizedObject, IGoToSymbolService + { + public async Task GetSymbolsAsync(GoToSymbolContext context) + { + var document = context.Document; + var position = context.Position; + var cancellationToken = context.CancellationToken; + + var service = document.GetLanguageService(); + var (symbol, span) = await service.GetSymbolAndBoundSpanAsync(document, position, cancellationToken).ConfigureAwait(false); + + if (symbol == null) + { + return; + } + + // We want ctrl-click GTD to be as close to regular GTD as possible. + // This means we have to query for "third party navigation", from + // XAML, etc. That call has to be done on the UI thread. + var definitions = await Task.Factory.StartNew(() => + GoToDefinitionHelpers.GetDefinitions(symbol, document.Project, thirdPartyNavigationAllowed: true, cancellationToken: cancellationToken) + .WhereAsArray(d => d.CanNavigateTo(document.Project.Solution.Workspace)), + cancellationToken, + TaskCreationOptions.None, + ForegroundTaskScheduler).ConfigureAwait(false); + + foreach (var definition in definitions) + { + context.AddItem(WellKnownSymbolTypes.Definition, definition); + } + + context.Span = span; + } + } +} diff --git a/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs b/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs index db07d3584e0ea..8d230be26b1e5 100644 --- a/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs +++ b/src/EditorFeatures/Core/GoToDefinition/GoToDefinitionHelpers.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Editor.FindUsages; @@ -16,13 +17,11 @@ namespace Microsoft.CodeAnalysis.Editor.GoToDefinition { internal static class GoToDefinitionHelpers { - public static bool TryGoToDefinition( + public static ImmutableArray GetDefinitions( ISymbol symbol, Project project, - IEnumerable> streamingPresenters, - CancellationToken cancellationToken, - bool thirdPartyNavigationAllowed = true, - bool throwOnHiddenDefinition = false) + bool thirdPartyNavigationAllowed, + CancellationToken cancellationToken) { var alias = symbol as IAliasSymbol; if (alias != null) @@ -30,7 +29,7 @@ internal static class GoToDefinitionHelpers var ns = alias.Target as INamespaceSymbol; if (ns != null && ns.IsGlobalNamespace) { - return false; + return ImmutableArray.Create(); } } @@ -92,13 +91,43 @@ internal static class GoToDefinitionHelpers } definitions.Add(definitionItem); + return definitions.ToImmutableAndFree(); + } + + public static bool TryGoToDefinition( + ISymbol symbol, + Project project, + IEnumerable> streamingPresenters, + CancellationToken cancellationToken, + bool thirdPartyNavigationAllowed = true, + bool throwOnHiddenDefinition = false) + { + var definitions = GetDefinitions(symbol, project, thirdPartyNavigationAllowed, cancellationToken); var presenter = streamingPresenters.FirstOrDefault()?.Value; var title = string.Format(EditorFeaturesResources._0_declarations, FindUsagesHelpers.GetDisplayName(symbol)); return presenter.TryNavigateToOrPresentItemsAsync( - project.Solution.Workspace, title, definitions.ToImmutableAndFree()).WaitAndGetResult(cancellationToken); + project.Solution.Workspace, title, definitions).WaitAndGetResult(cancellationToken); + } + + public static bool TryGoToDefinition( + ImmutableArray definitions, + Project project, + string title, + IEnumerable> streamingPresenters, + CancellationToken cancellationToken) + { + if (definitions.IsDefaultOrEmpty) + { + return false; + } + + var presenter = streamingPresenters.FirstOrDefault()?.Value; + + return presenter.TryNavigateToOrPresentItemsAsync( + project.Solution.Workspace, title, definitions).WaitAndGetResult(cancellationToken); } } } diff --git a/src/EditorFeatures/Core/GoToDefinition/GoToSymbolContext.cs b/src/EditorFeatures/Core/GoToDefinition/GoToSymbolContext.cs new file mode 100644 index 0000000000000..9703951cf4441 --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/GoToSymbolContext.cs @@ -0,0 +1,54 @@ +// 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.Threading; +using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.CodeAnalysis.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.GoToDefinition +{ + internal class GoToSymbolContext + { + private readonly object _gate = new object(); + + private readonly MultiDictionary _items = new MultiDictionary(); + + public GoToSymbolContext(Document document, int position, CancellationToken cancellationToken) + { + Document = document; + Position = position; + CancellationToken = cancellationToken; + } + + public Document Document { get; } + public int Position { get; } + public CancellationToken CancellationToken { get; } + + public TextSpan Span { get; set; } + + internal bool TryGetItems(string key, out IEnumerable items) + { + if (_items.ContainsKey(key)) + { + // Multidictionary valuesets are structs so we can't + // just check for null + items = _items[key]; + return true; + } + else + { + items = null; + return false; + } + } + + public void AddItem(string key, DefinitionItem item) + { + lock (_gate) + { + _items.Add(key, item); + } + } + } +} diff --git a/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionService.cs b/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionService.cs index 2afa5b41f2f73..a8fda42a08a4b 100644 --- a/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionService.cs +++ b/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionService.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Navigation; -using Microsoft.CodeAnalysis.Options; namespace Microsoft.CodeAnalysis.Editor { diff --git a/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionSymbolService.cs b/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionSymbolService.cs new file mode 100644 index 0000000000000..99a30194235f7 --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/IGoToDefinitionSymbolService.cs @@ -0,0 +1,14 @@ +// 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.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.Editor.GoToDefinition +{ + internal interface IGoToDefinitionSymbolService : ILanguageService + { + Task<(ISymbol, TextSpan)> GetSymbolAndBoundSpanAsync(Document document, int position, CancellationToken cancellationToken); + } +} diff --git a/src/EditorFeatures/Core/GoToDefinition/IGoToSymbolService.cs b/src/EditorFeatures/Core/GoToDefinition/IGoToSymbolService.cs new file mode 100644 index 0000000000000..5fa0496599fd2 --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/IGoToSymbolService.cs @@ -0,0 +1,12 @@ +// 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.Threading.Tasks; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.CodeAnalysis.Editor.GoToDefinition +{ + internal interface IGoToSymbolService : ILanguageService + { + Task GetSymbolsAsync(GoToSymbolContext context); + } +} diff --git a/src/EditorFeatures/Core/GoToDefinition/WellKnownSymbolTypes.cs b/src/EditorFeatures/Core/GoToDefinition/WellKnownSymbolTypes.cs new file mode 100644 index 0000000000000..b50ea7f313c72 --- /dev/null +++ b/src/EditorFeatures/Core/GoToDefinition/WellKnownSymbolTypes.cs @@ -0,0 +1,9 @@ +// 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.Editor.GoToDefinition +{ + internal class WellKnownSymbolTypes + { + public const string Definition = nameof(Definition); + } +} diff --git a/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs b/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs index d5ce2846d3955..885810047e5b8 100644 --- a/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs +++ b/src/EditorFeatures/Core/Implementation/CodeFixes/CodeFixService.cs @@ -73,7 +73,7 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode _fixAllProviderMap = ImmutableDictionary.Empty; } - public async Task GetFirstDiagnosticWithFixAsync( + public async Task GetMostSevereFixableDiagnostic( Document document, TextSpan range, CancellationToken cancellationToken) { if (document == null || !document.IsOpen()) @@ -83,32 +83,61 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode using (var diagnostics = SharedPools.Default>().GetPooledObject()) { - var fullResult = await _diagnosticService.TryAppendDiagnosticsForSpanAsync(document, range, diagnostics.Object, cancellationToken: cancellationToken).ConfigureAwait(false); - foreach (var diagnostic in diagnostics.Object) + using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) { - cancellationToken.ThrowIfCancellationRequested(); - - if (!range.IntersectsWith(diagnostic.TextSpan)) - { - continue; - } + var linkedToken = linkedTokenSource.Token; + + // This flag is used by SuggestedActionsSource to track what solution is was + // last able to get "full results" for. + var isFullResult = await _diagnosticService.TryAppendDiagnosticsForSpanAsync( + document, range, diagnostics.Object, cancellationToken: linkedToken).ConfigureAwait(false); + + var errorDiagnostics = diagnostics.Object.Where(d => d.Severity == DiagnosticSeverity.Error); + var otherDiagnostics = diagnostics.Object.Where(d => d.Severity != DiagnosticSeverity.Error); + + // Kick off a task that will determine there's an Error Diagnostic with a fixer + var errorDiagnosticsTask = Task.Run( + () => GetFirstDiagnosticWithFixAsync(document, errorDiagnostics, range, linkedToken), + linkedToken); + + // Kick off a task that will determine if any non-Error Diagnostic has a fixer + var otherDiagnosticsTask = Task.Run( + () => GetFirstDiagnosticWithFixAsync(document, otherDiagnostics, range, linkedToken), + linkedToken); + + // If the error diagnostics task happens to complete with a non-null result before + // the other diagnostics task, we can cancel the other task. + var diagnostic = await errorDiagnosticsTask.ConfigureAwait(false) + ?? await otherDiagnosticsTask.ConfigureAwait(false); + linkedTokenSource.Cancel(); + + return new FirstDiagnosticResult(partialResult: !isFullResult, + hasFix: diagnostic != null, + diagnostic: diagnostic); + } + } + } - // REVIEW: 2 possible designs. - // 1. find the first fix and then return right away. if the lightbulb is actually expanded, find all fixes for the line synchronously. or - // 2. kick off a task that finds all fixes for the given range here but return once we find the first one. - // at the same time, let the task to run to finish. if the lightbulb is expanded, we just simply use the task to get all fixes. - // - // first approach is simpler, so I will implement that first. if the first approach turns out to be not good enough, then - // I will try the second approach which will be more complex but quicker - var hasFix = await ContainsAnyFix(document, diagnostic, cancellationToken).ConfigureAwait(false); - if (hasFix) - { - return new FirstDiagnosticResult(!fullResult, hasFix, diagnostic); - } + private async Task GetFirstDiagnosticWithFixAsync( + Document document, + IEnumerable severityGroup, + TextSpan range, + CancellationToken cancellationToken) + { + foreach (var diagnostic in severityGroup) + { + if (!range.IntersectsWith(diagnostic.TextSpan)) + { + continue; } - return new FirstDiagnosticResult(!fullResult, false, default); + if (await ContainsAnyFixAsync(document, diagnostic, cancellationToken).ConfigureAwait(false)) + { + return diagnostic; + } } + + return null; } public async Task> GetFixesAsync(Document document, TextSpan range, bool includeSuppressionFixes, CancellationToken cancellationToken) @@ -142,7 +171,7 @@ public async Task> GetFixesAsync(Document docu foreach (var spanAndDiagnostic in aggregatedDiagnostics) { await AppendFixesAsync( - document, spanAndDiagnostic.Key, spanAndDiagnostic.Value, + document, spanAndDiagnostic.Key, spanAndDiagnostic.Value, result, cancellationToken).ConfigureAwait(false); } @@ -176,7 +205,7 @@ public async Task> GetFixesAsync(Document docu foreach (var spanAndDiagnostic in aggregatedDiagnostics) { await AppendSuppressionsAsync( - document, spanAndDiagnostic.Key, spanAndDiagnostic.Value, + document, spanAndDiagnostic.Key, spanAndDiagnostic.Value, result, cancellationToken).ConfigureAwait(false); } } @@ -267,7 +296,7 @@ public async Task> GetFixesAsync(Document docu } private async Task AppendSuppressionsAsync( - Document document, TextSpan span, IEnumerable diagnostics, + Document document, TextSpan span, IEnumerable diagnostics, ArrayBuilder result, CancellationToken cancellationToken) { if (!_suppressionProvidersMap.TryGetValue(document.Project.Language, out var lazySuppressionProvider) || lazySuppressionProvider.Value == null) @@ -276,10 +305,10 @@ public async Task> GetFixesAsync(Document docu } await AppendFixesOrSuppressionsAsync( - document, span, diagnostics, result, lazySuppressionProvider.Value, + document, span, diagnostics, result, lazySuppressionProvider.Value, hasFix: d => lazySuppressionProvider.Value.CanBeSuppressedOrUnsuppressed(d), getFixes: dxs => lazySuppressionProvider.Value.GetSuppressionsAsync( - document, span, dxs, cancellationToken), + document, span, dxs, cancellationToken), cancellationToken: cancellationToken).ConfigureAwait(false); } @@ -293,7 +322,7 @@ public async Task> GetFixesAsync(Document docu Func, Task>> getFixes, CancellationToken cancellationToken) { - var allDiagnostics = + var allDiagnostics = await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity) .ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false); var diagnostics = allDiagnostics.WhereAsArray(hasFix); @@ -395,7 +424,7 @@ private async Task> GetProjectDiagnosticsAsync(Project p } } - private async Task ContainsAnyFix( + private async Task ContainsAnyFixAsync( Document document, DiagnosticData diagnostic, CancellationToken cancellationToken) { var workspaceFixers = ImmutableArray.Empty; @@ -410,7 +439,7 @@ private async Task> GetProjectDiagnosticsAsync(Project p } Lazy lazySuppressionProvider = null; - var hasSuppressionFixer = + var hasSuppressionFixer = _suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) && lazySuppressionProvider.Value != null; diff --git a/src/EditorFeatures/Core/Implementation/CodeFixes/ICodeFixService.cs b/src/EditorFeatures/Core/Implementation/CodeFixes/ICodeFixService.cs index a1e7ff485a0fb..af2ba5c48e44a 100644 --- a/src/EditorFeatures/Core/Implementation/CodeFixes/ICodeFixService.cs +++ b/src/EditorFeatures/Core/Implementation/CodeFixes/ICodeFixService.cs @@ -10,9 +10,8 @@ namespace Microsoft.CodeAnalysis.CodeFixes { internal interface ICodeFixService { - Task GetFirstDiagnosticWithFixAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken); - Task> GetFixesAsync(Document document, TextSpan textSpan, bool includeSuppressionFixes, CancellationToken cancellationToken); CodeFixProvider GetSuppressionFixer(string language, IEnumerable diagnosticIds); + Task GetMostSevereFixableDiagnostic(Document document, TextSpan range, CancellationToken cancellationToken); } } diff --git a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSource.cs index bfcd590116c79..a0bbe9a8a77f2 100644 --- a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSource.cs @@ -25,14 +25,17 @@ using Microsoft.VisualStudio.Text.Editor; using Roslyn.Utilities; +using CodeFixGroupKey = System.Tuple; + namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions { - using CodeFixGroupKey = Tuple; internal partial class SuggestedActionsSourceProvider { - private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISuggestedActionsSource + private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISuggestedActionsSource2 { + private readonly ISuggestedActionCategoryRegistryService _suggestedActionCategoryRegistry; + // state that will be only reset when source is disposed. private SuggestedActionsSourceProvider _owner; private ITextView _textView; @@ -45,12 +48,17 @@ private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISugge public event EventHandler SuggestedActionsChanged; - public SuggestedActionsSource(SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer) + public SuggestedActionsSource( + SuggestedActionsSourceProvider owner, + ITextView textView, + ITextBuffer textBuffer, + ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistry) { _owner = owner; _textView = textView; _textView.Closed += OnTextViewClosed; _subjectBuffer = textBuffer; + _suggestedActionCategoryRegistry = suggestedActionCategoryRegistry; _registration = Workspace.GetWorkspaceRegistration(textBuffer.AsTextContainer()); _lastSolutionVersionReported = InvalidSolutionVersion; @@ -222,7 +230,7 @@ private SuggestedActionSet FilterActionSetByTitle(SuggestedActionSet set, HashSe { return actions.Count == 0 ? null - : new SuggestedActionSet(actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan); + : new SuggestedActionSet(set.CategoryName, actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan); } finally { @@ -262,7 +270,11 @@ private SuggestedActionSet InlineActions(SuggestedActionSet actionSet) } return new SuggestedActionSet( - newActions.ToImmutableAndFree(), actionSet.Title, actionSet.Priority, actionSet.ApplicableToSpan); + actionSet.CategoryName, + newActions.ToImmutableAndFree(), + actionSet.Title, + actionSet.Priority, + actionSet.ApplicableToSpan); } private ImmutableArray GetCodeFixes( @@ -530,13 +542,29 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace // diagnostic from things like build shouldn't reach here since we don't support LB for those diagnostics Contract.Requires(diag.Item1.HasTextSpan); - sets.Add(new SuggestedActionSet(group, priority, diag.Item1.TextSpan.ToSpan())); + var category = GetFixCategory(diag.Item1.Severity); + sets.Add(new SuggestedActionSet(category, group, priority: priority, applicableToSpan: diag.Item1.TextSpan.ToSpan())); } } return sets.ToImmutableAndFree(); } + private static string GetFixCategory(DiagnosticSeverity severity) + { + switch (severity) + { + case DiagnosticSeverity.Hidden: + case DiagnosticSeverity.Info: + case DiagnosticSeverity.Warning: + return PredefinedSuggestedActionCategoryNames.CodeFix; + case DiagnosticSeverity.Error: + return PredefinedSuggestedActionCategoryNames.ErrorFix; + default: + throw ExceptionUtilities.Unreachable; + }; + } + private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActionPriority key) { switch (key) @@ -620,92 +648,86 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi } return new SuggestedActionSet( + PredefinedSuggestedActionCategoryNames.Refactoring, refactoringSuggestedActions.ToImmutableAndFree(), - SuggestedActionSetPriority.Low, - applicableSpan); + priority: SuggestedActionSetPriority.Low, + applicableToSpan: applicableSpan); } - public async Task HasSuggestedActionsAsync( + public Task HasSuggestedActionsAsync( ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) { - var provider = _owner; + // We implement GetSuggestedActionCategoriesAsync so this should not be called + throw new NotImplementedException($"We implement {nameof(GetSuggestedActionCategoriesAsync)}. This should not be called."); + } - if (IsDisposed) + private async Task GetSpanAsync(SnapshotSpan range) + { + // First, ensure that the snapshot we're being asked about is for an actual + // roslyn document. This can fail, for example, in projection scenarios where + // we are called with a range snapshot that refers to the projection buffer + // and not the actual roslyn code that is being projected into it. + var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); + if (document == null) { - // We've already been disposed. No point in continuing. - return false; + return null; } - - using (var asyncToken = _owner.OperationListener.BeginAsyncOperation("HasSuggestedActionsAsync")) - { - // First, ensure that the snapshot we're being asked about is for an actual - // roslyn document. This can fail, for example, in projection scenarios where - // we are called with a range snapshot that refers to the projection buffer - // and not the actual roslyn code that is being projected into it. - var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); - if (document == null) + + // Also make sure the range is from the same buffer that this source was created for + Contract.ThrowIfFalse( + range.Snapshot.TextBuffer.Equals(_subjectBuffer), + $"Invalid text buffer passed to {nameof(HasSuggestedActionsAsync)}"); + + // Next, before we do any async work, acquire the user's selection, directly grabbing + // it from the UI thread if htat's what we're on. That way we don't have any reentrancy + // blocking concerns if VS wants to block on this call (for example, if the user + // explicitly invokes the 'show smart tag' command). + // + // This work must happen on the UI thread as it needs to access the _textView's mutable + // state. + // + // Note: we may be called in one of two VS scenarios: + // 1) User has moved caret to a new line. In this case VS will call into us in the + // bg to see if we have any suggested actions for this line. In order to figure + // this out, we need to see what selectoin the user has (for refactorings), which + // necessitates going back to the fg. + // + // 2) User moves to a line and immediately hits ctrl-dot. In this case, on the UI + // thread VS will kick us off and then immediately block to get the results so + // that they can expand the lightbulb. In this case we cannot do BG work first, + // then call back into the UI thread to try to get the user selection. This will + // deadlock as the UI thread is blocked on us. + // + // There are two solution to '2'. Either introduce reentrancy (which we really don't + // like to do), or just ensure that we acquire and get the users selection up front. + // This means that when we're called from the UI therad, we never try to go back to the + // UI thread. + TextSpan? selection = null; + if (IsForeground()) + { + selection = TryGetCodeRefactoringSelection(range); + } + else + { + await InvokeBelowInputPriority(() => { - return false; - } - - // Also make sure the range is from the same buffer that this source was created for - Contract.ThrowIfFalse( - range.Snapshot.TextBuffer.Equals(_subjectBuffer), - $"Invalid text buffer passed to {nameof(HasSuggestedActionsAsync)}"); - - // Next, before we do any async work, acquire the user's selection, directly grabbing - // it from the UI thread if htat's what we're on. That way we don't have any reentrancy - // blocking concerns if VS wants to block on this call (for example, if the user - // explicitly invokes the 'show smart tag' command). - // - // This work must happen on the UI thread as it needs to access the _textView's mutable - // state. - // - // Note: we may be called in one of two VS scenarios: - // 1) User has moved caret to a new line. In this case VS will call into us in the - // bg to see if we have any suggested actions for this line. In order to figure - // this out, we need to see what selectoin the user has (for refactorings), which - // necessitates going back to the fg. - // - // 2) User moves to a line and immediately hits ctrl-dot. In this case, on the UI - // thread VS will kick us off and then immediately block to get the results so - // that they can expand the lightbulb. In this case we cannot do BG work first, - // then call back into the UI thread to try to get the user selection. This will - // deadlock as the UI thread is blocked on us. - // - // There are two solution to '2'. Either introduce reentrancy (which we really don't - // like to do), or just ensure that we acquire and get the users selection up front. - // This means that when we're called from the UI therad, we never try to go back to the - // UI thread. - TextSpan? selection = null; - if (IsForeground()) - { - selection = TryGetCodeRefactoringSelection(range); - } - else - { - await InvokeBelowInputPriority(() => + // Make sure we were not disposed between kicking off this work and getting + // to this point. + if (IsDisposed) { - // Make sure we were not disposed between kicking off this work and getting - // to this point. - if (IsDisposed) - { - return; - } - - selection = TryGetCodeRefactoringSelection(range); - }).ConfigureAwait(false); - } + return; + } - return - await HasFixesAsync(provider, document, range, cancellationToken).ConfigureAwait(false) || - await HasRefactoringsAsync(provider, document, selection, cancellationToken).ConfigureAwait(false); + selection = TryGetCodeRefactoringSelection(range); + }).ConfigureAwait(false); } + + return selection; } - private async Task HasFixesAsync( + private async Task GetFixLevelAsync( SuggestedActionsSourceProvider provider, Document document, SnapshotSpan range, @@ -718,28 +740,28 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi supportsFeatureService.SupportsCodeFixes(document)) { var result = await Task.Run( - () => provider._codeFixService.GetFirstDiagnosticWithFixAsync( + () => provider._codeFixService.GetMostSevereFixableDiagnostic( document, range.Span.ToTextSpan(), cancellationToken), cancellationToken).ConfigureAwait(false); if (result.HasFix) { Logger.Log(FunctionId.SuggestedActions_HasSuggestedActionsAsync); - return true; + return GetFixCategory(result.Diagnostic.Severity); } if (result.PartialResult) { // reset solution version number so that we can raise suggested action changed event Volatile.Write(ref _lastSolutionVersionReported, InvalidSolutionVersion); - return false; + return null; } } - return false; + return null; } - private async Task HasRefactoringsAsync( + private async Task TryGetRefactoringSuggestedActionCategoryAsync( SuggestedActionsSourceProvider provider, Document document, TextSpan? selection, @@ -749,7 +771,7 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi { // this is here to fail test and see why it is failed. Trace.WriteLine("given range is not current"); - return false; + return null; } var workspace = document.Project.Solution.Workspace; @@ -759,13 +781,16 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi provider._codeRefactoringService != null && supportsFeatureService.SupportsRefactorings(document)) { - return await Task.Run( + if (await Task.Run( () => provider._codeRefactoringService.HasRefactoringsAsync( document, selection.Value, cancellationToken), - cancellationToken).ConfigureAwait(false); + cancellationToken).ConfigureAwait(false)) + { + return PredefinedSuggestedActionCategoryNames.Refactoring; + } } - return false; + return null; } private TextSpan? TryGetCodeRefactoringSelection(SnapshotSpan range) @@ -866,6 +891,40 @@ private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId cu Volatile.Write(ref _lastSolutionVersionReported, solutionVersion); } + + public async Task GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken) + { + var provider = _owner; + using (var asyncToken = _owner.OperationListener.BeginAsyncOperation(nameof(GetSuggestedActionCategoriesAsync))) + { + var selection = await GetSpanAsync(range).ConfigureAwait(false); + if (selection != null) + { + var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); + using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken)) + { + var linkedToken = linkedTokenSource.Token; + + var errorTask = Task.Run( + () => GetFixLevelAsync(provider, document, range, linkedToken), linkedToken); + + var refactoringTask = Task.Run( + () => TryGetRefactoringSuggestedActionCategoryAsync(provider, document, selection, linkedToken), + linkedToken); + + // If we happen to get the result of the error task before the refactoring task, + // and that result is non-null, we can just cancel the refactoring task. + var result = await errorTask.ConfigureAwait(false) ?? await refactoringTask.ConfigureAwait(false); + linkedTokenSource.Cancel(); + return result == null + ? null + : _suggestedActionCategoryRegistry.CreateSuggestedActionCategorySet(result); + } + } + } + + return null; + } } } } diff --git a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSourceProvider.cs b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSourceProvider.cs index 82576e3cef50a..d02730d9ae24f 100644 --- a/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSourceProvider.cs +++ b/src/EditorFeatures/Core/Implementation/Suggestions/SuggestedActionsSourceProvider.cs @@ -35,6 +35,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP private readonly ICodeRefactoringService _codeRefactoringService; private readonly IDiagnosticAnalyzerService _diagnosticService; private readonly ICodeFixService _codeFixService; + private readonly ISuggestedActionCategoryRegistryService _suggestedActionCategoryRegistry; public readonly ICodeActionEditHandlerService EditHandler; public readonly IAsynchronousOperationListener OperationListener; @@ -50,6 +51,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP ICodeFixService codeFixService, ICodeActionEditHandlerService editHandler, IWaitIndicator waitIndicator, + ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistry, [ImportMany] IEnumerable> asyncListeners, [ImportMany] IEnumerable> imageMonikerServices, [ImportMany] IEnumerable> actionCallbacks) @@ -57,6 +59,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP _codeRefactoringService = codeRefactoringService; _diagnosticService = diagnosticService; _codeFixService = codeFixService; + _suggestedActionCategoryRegistry = suggestedActionCategoryRegistry; ActionCallbacks = actionCallbacks.ToImmutableArray(); EditHandler = editHandler; WaitIndicator = waitIndicator; @@ -70,7 +73,7 @@ public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView, Contract.ThrowIfNull(textView); Contract.ThrowIfNull(textBuffer); - return new SuggestedActionsSource(this, textView, textBuffer); + return new SuggestedActionsSource(this, textView, textBuffer, _suggestedActionCategoryRegistry); } } } diff --git a/src/EditorFeatures/Core/Implementation/TodoComment/TodoCommentIncrementalAnalyzer.cs b/src/EditorFeatures/Core/Implementation/TodoComment/TodoCommentIncrementalAnalyzer.cs index eb19bbe0da2f7..466004e770769 100644 --- a/src/EditorFeatures/Core/Implementation/TodoComment/TodoCommentIncrementalAnalyzer.cs +++ b/src/EditorFeatures/Core/Implementation/TodoComment/TodoCommentIncrementalAnalyzer.cs @@ -87,7 +87,7 @@ public async Task AnalyzeSyntaxAsync(Document document, InvocationReasons reason } } - private async Task> GetTodoCommentsAsync(Document document, ImmutableArray tokens, CancellationToken cancellationToken) + private async Task> GetTodoCommentsAsync(Document document, IList tokens, CancellationToken cancellationToken) { var service = document.GetLanguageService(); if (service == null) diff --git a/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbol.cs b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbol.cs new file mode 100644 index 0000000000000..94921c91aca09 --- /dev/null +++ b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbol.cs @@ -0,0 +1,61 @@ +// 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.CodeAnalysis.Editor.GoToDefinition; +using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.FindUsages; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.NavigableSymbols +{ + internal partial class NavigableSymbolService + { + private class NavigableSymbol : INavigableSymbol + { + private readonly ImmutableArray _definitions; + private readonly SnapshotSpan _span; + private readonly Document _document; + private readonly IEnumerable> _presenters; + private readonly IWaitIndicator _waitIndicator; + + public NavigableSymbol( + ImmutableArray definitions, + SnapshotSpan span, + Document document, + IEnumerable> streamingPresenters, + IWaitIndicator waitIndicator) + { + Contract.ThrowIfFalse(definitions.Length > 0); + + _definitions = definitions; + _span = span; + _document = document; + _presenters = streamingPresenters; + _waitIndicator = waitIndicator; + } + + public SnapshotSpan SymbolSpan => _span; + + public IEnumerable Relationships => + SpecializedCollections.SingletonEnumerable(PredefinedNavigableRelationships.Definition); + + public void Navigate(INavigableRelationship relationship) => + _waitIndicator.Wait( + title: EditorFeaturesResources.Go_to_Definition, + message: EditorFeaturesResources.Navigating_to_definition, + allowCancel: true, + showProgress: false, + action: context => GoToDefinitionHelpers.TryGoToDefinition( + _definitions, + _document.Project, + _definitions[0].NameDisplayParts.GetFullText(), + _presenters, + context.CancellationToken) + ); + } + } +} diff --git a/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbolSource.cs b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbolSource.cs new file mode 100644 index 0000000000000..156af97e01a07 --- /dev/null +++ b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.NavigableSymbolSource.cs @@ -0,0 +1,73 @@ +// 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 System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.GoToDefinition; +using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.Text.Shared.Extensions; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; + +namespace Microsoft.CodeAnalysis.Editor.NavigableSymbols +{ + internal partial class NavigableSymbolService + { + private partial class NavigableSymbolSource : INavigableSymbolSource + { + private readonly IEnumerable> _presenters; + private readonly IWaitIndicator _waitIndicator; + + private bool _disposed; + + public NavigableSymbolSource( + IEnumerable> streamingPresenters, + IWaitIndicator waitIndicator) + { + _presenters = streamingPresenters; + _waitIndicator = waitIndicator; + } + + public void Dispose() + { + _disposed = true; + } + + public async Task GetNavigableSymbolAsync(SnapshotSpan triggerSpan, CancellationToken cancellationToken) + { + if (_disposed) + { + return null; + } + + var snapshot = triggerSpan.Snapshot; + var position = triggerSpan.Start; + var document = snapshot.GetOpenDocumentInCurrentContextWithChanges(); + if (document == null) + { + return null; + } + + var service = document.GetLanguageService(); + + var context = new GoToSymbolContext(document, position, cancellationToken); + + await service.GetSymbolsAsync(context).ConfigureAwait(false); + + if (!context.TryGetItems(WellKnownSymbolTypes.Definition, out var definitions)) + { + return null; + } + + var snapshotSpan = new SnapshotSpan(snapshot, context.Span.ToSpan()); + return new NavigableSymbol(definitions.ToImmutableArray(), snapshotSpan, document, _presenters, _waitIndicator); + } + } + } +} diff --git a/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.cs b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.cs new file mode 100644 index 0000000000000..c1b6c945ea297 --- /dev/null +++ b/src/EditorFeatures/Core/NavigableSymbols/NavigableSymbolService.cs @@ -0,0 +1,39 @@ +// 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.ComponentModel.Composition; +using Microsoft.CodeAnalysis.Editor.Host; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; +using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Text; +using Microsoft.VisualStudio.Text.Editor; +using Microsoft.VisualStudio.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.NavigableSymbols +{ + [Export(typeof(INavigableSymbolSourceProvider))] + [Name(nameof(NavigableSymbolService))] + [ContentType(ContentTypeNames.RoslynContentType)] + internal partial class NavigableSymbolService : INavigableSymbolSourceProvider + { + private static readonly object s_key = new object(); + private readonly IEnumerable> _streamingPresenters; + private readonly IWaitIndicator _waitIndicator; + + [ImportingConstructor] + public NavigableSymbolService( + IWaitIndicator waitIndicator, + [ImportMany] IEnumerable> streamingPresenters) + { + _waitIndicator = waitIndicator; + _streamingPresenters = streamingPresenters; + } + + public INavigableSymbolSource TryCreateNavigableSymbolSource(ITextView textView, ITextBuffer buffer) + { + return textView.GetOrCreatePerSubjectBufferProperty(buffer, s_key, + (v, b) => new NavigableSymbolSource(_streamingPresenters, _waitIndicator)); + } + } +} diff --git a/src/EditorFeatures/Core/SymbolSearch/SymbolSearchUpdateEngineFactory.cs b/src/EditorFeatures/Core/SymbolSearch/SymbolSearchUpdateEngineFactory.cs index b7d0888c0281e..c76757b729e68 100644 --- a/src/EditorFeatures/Core/SymbolSearch/SymbolSearchUpdateEngineFactory.cs +++ b/src/EditorFeatures/Core/SymbolSearch/SymbolSearchUpdateEngineFactory.cs @@ -1,9 +1,11 @@ // 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.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Remote; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.SymbolSearch { @@ -61,31 +63,31 @@ private partial class RemoteUpdateEngine : ISymbolSearchUpdateEngine, ISymbolSea public async Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken) { - var results = await _session.TryInvokeAsync>( + var results = await _session.TryInvokeAsync>( nameof(IRemoteSymbolSearchUpdateEngine.FindPackagesWithTypeAsync), new object[] { source, name, arity }, cancellationToken).ConfigureAwait(false); - return results.NullToEmpty(); + return results.ToImmutableArrayOrEmpty(); } public async Task> FindPackagesWithAssemblyAsync( string source, string assemblyName, CancellationToken cancellationToken) { - var results = await _session.TryInvokeAsync>( + var results = await _session.TryInvokeAsync>( nameof(IRemoteSymbolSearchUpdateEngine.FindPackagesWithAssemblyAsync), new object[] { source, assemblyName }, cancellationToken).ConfigureAwait(false); - return results.NullToEmpty(); + return results.ToImmutableArrayOrEmpty(); } public async Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken) { - var results = await _session.TryInvokeAsync>( + var results = await _session.TryInvokeAsync>( nameof(IRemoteSymbolSearchUpdateEngine.FindReferenceAssembliesWithTypeAsync), new object[] { name, arity }, cancellationToken).ConfigureAwait(false); - return results.NullToEmpty(); + return results.ToImmutableArrayOrEmpty(); } public async Task UpdateContinuouslyAsync( diff --git a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs index c0ef2f0c25b23..cc0d339628f49 100644 --- a/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs +++ b/src/EditorFeatures/Test/CodeFixes/CodeFixServiceTests.cs @@ -46,7 +46,7 @@ public async Task TestGetFirstDiagnosticWithFixAsync() var reference = new MockAnalyzerReference(); var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference); var document = project.Documents.Single(); - var unused = await fixService.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None); + var unused = await fixService.GetMostSevereFixableDiagnostic(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None); var fixer1 = fixers.Single().Value as MockFixer; var fixer2 = reference.Fixer as MockFixer; @@ -127,7 +127,7 @@ private async Task GetFirstDiagnosticWithFixAsync(CodeFixProvider codefix) using (var workspace = tuple.Item1) { GetDocumentAndExtensionManager(tuple.Item2, workspace, out var document, out var extensionManager); - var unused = await tuple.Item3.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None); + var unused = await tuple.Item3.GetMostSevereFixableDiagnostic(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None); Assert.True(extensionManager.IsDisabled(codefix)); Assert.False(extensionManager.IsIgnored(codefix)); } diff --git a/src/EditorFeatures/Test/CommentSelection/CommentUncommentSelectionCommandHandlerTests.cs b/src/EditorFeatures/Test/CommentSelection/CommentUncommentSelectionCommandHandlerTests.cs index 2de31cdb6df3f..132ddd9e7e886 100644 --- a/src/EditorFeatures/Test/CommentSelection/CommentUncommentSelectionCommandHandlerTests.cs +++ b/src/EditorFeatures/Test/CommentSelection/CommentUncommentSelectionCommandHandlerTests.cs @@ -554,7 +554,7 @@ private static void CommentSelection(ITextView textView, IEnumerable null, service, textView.Selection.GetSnapshotSpansOnBuffer(textView.TextBuffer), textChanges, trackingSpans, operation, CancellationToken.None); - AssertEx.SetEqual(expectedChanges, textChanges); + Roslyn.Test.Utilities.AssertEx.SetEqual(expectedChanges, textChanges); // Actually apply the edit to let the tracking spans adjust. using (var edit = textView.TextBuffer.CreateEdit()) @@ -571,7 +571,7 @@ private static void CommentSelection(ITextView textView, IEnumerable if (expectedSelectedSpans != null) { - AssertEx.Equal(expectedSelectedSpans, textView.Selection.SelectedSpans.Select(snapshotSpan => snapshotSpan.Span)); + Roslyn.Test.Utilities.AssertEx.Equal(expectedSelectedSpans, textView.Selection.SelectedSpans.Select(snapshotSpan => snapshotSpan.Span)); } } diff --git a/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs b/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs index feb815c089fe3..8b33f63da2ec6 100644 --- a/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs +++ b/src/EditorFeatures/Test/Utilities/PatternMatcherTests.cs @@ -160,12 +160,12 @@ public void BreakIntoWordParts_TwoUppercaseCharacters() private void VerifyBreakIntoWordParts(string original, params string[] parts) { - AssertEx.Equal(parts, BreakIntoWordParts(original)); + Roslyn.Test.Utilities.AssertEx.Equal(parts, BreakIntoWordParts(original)); } private void VerifyBreakIntoCharacterParts(string original, params string[] parts) { - AssertEx.Equal(parts, BreakIntoCharacterParts(original)); + Roslyn.Test.Utilities.AssertEx.Equal(parts, BreakIntoCharacterParts(original)); } private const bool CaseSensitive = true; diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesCommandHandlerTests.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesCommandHandlerTests.vb new file mode 100644 index 0000000000000..9f0b987d6781d --- /dev/null +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesCommandHandlerTests.vb @@ -0,0 +1,86 @@ +' 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 System.Threading.Tasks +Imports Microsoft.CodeAnalysis.Editor.Commands +Imports Microsoft.CodeAnalysis.Editor.FindReferences +Imports Microsoft.CodeAnalysis.Editor.Host +Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces +Imports Microsoft.CodeAnalysis.FindUsages +Imports Microsoft.CodeAnalysis.Shared.TestHooks +Imports Microsoft.CodeAnalysis.Text.Shared.Extensions + +Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences + Public Class FindReferencesCommandHandlerTests + + + Public Async Function TestSelection() As Task + Dim source = " +class C +{ + void M() + { + int {|Definition:yyy|} = 0; + {|Reference:{|Selection:yyy|}|}++; + {|Reference:yyy|}++; + } +}" + Using workspace = TestWorkspace.CreateCSharp(source) + Dim testDocument = workspace.Documents.Single() + + Dim view = testDocument.GetTextView() + Dim textBuffer = view.TextBuffer + Dim snapshot = textBuffer.CurrentSnapshot + + view.Selection.Select( + testDocument.AnnotatedSpans("Selection").Single().ToSnapshotSpan(snapshot), isReversed:=False) + + Dim waiter = New Waiter() + + Dim context = New FindReferencesTests.TestContext() + Dim commandHandler = New FindReferencesCommandHandler( + workspace.GetService(Of IWaitIndicator), + {}, {New Lazy(Of IStreamingFindUsagesPresenter)(Function() New MockStreamingFindReferencesPresenter(context))}, + {New Lazy(Of IAsynchronousOperationListener, FeatureMetadata)(Function() waiter, New FeatureMetadata(FeatureAttribute.FindReferences))}) + + Dim document = workspace.CurrentSolution.GetDocument(testDocument.Id) + commandHandler.ExecuteCommand( + New FindReferencesCommandArgs(view, textBuffer), Sub() + End Sub) + + ' Wait for the find refs to be done. + Await waiter.CreateWaitTask() + + Assert.Equal(1, context.Definitions.Count) + Assert.Equal(testDocument.AnnotatedSpans("Definition").Single(), + context.Definitions(0).SourceSpans.Single().SourceSpan) + Assert.Equal(testDocument.AnnotatedSpans("Reference").Count, + context.References.Count) + + AssertEx.SetEqual(testDocument.AnnotatedSpans("Reference"), + context.References.Select(Function(r) r.SourceSpan.SourceSpan)) + End Using + End Function + + Private Class MockStreamingFindReferencesPresenter + Implements IStreamingFindUsagesPresenter + + Private ReadOnly _context As FindReferencesTests.TestContext + + Public Sub New(context As FindReferencesTests.TestContext) + _context = context + End Sub + + Public Sub ClearAll() Implements IStreamingFindUsagesPresenter.ClearAll + End Sub + + Public Function StartSearch(title As String, supportsReferences As Boolean) As FindUsagesContext Implements IStreamingFindUsagesPresenter.StartSearch + Return _context + End Function + End Class + + Private Class Waiter + Inherits AsynchronousOperationListener + + End Class + End Class +End Namespace diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb index dd69fcc741852..878737e6dea7b 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.vb @@ -125,7 +125,7 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences End Structure - Private Class TestContext + Friend Class TestContext Inherits FindUsagesContext Private ReadOnly gate As Object = New Object() diff --git a/src/EditorFeatures/Test2/NavigableSymbols/NavigableSymbolsTest.vb b/src/EditorFeatures/Test2/NavigableSymbols/NavigableSymbolsTest.vb new file mode 100644 index 0000000000000..38414782967c9 --- /dev/null +++ b/src/EditorFeatures/Test2/NavigableSymbols/NavigableSymbolsTest.vb @@ -0,0 +1,88 @@ +' 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 System +Imports System.Linq +Imports System.Collections.Immutable +Imports System.Threading +Imports System.Threading.Tasks +Imports Microsoft.CodeAnalysis.Text +Imports Microsoft.CodeAnalysis.Text.Shared.Extensions +Imports Microsoft.CodeAnalysis.Editor.Host +Imports Microsoft.CodeAnalysis.Editor.NavigableSymbols +Imports Microsoft.CodeAnalysis.Editor.UnitTests.BraceMatching +Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities +Imports Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers +Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces +Imports Microsoft.CodeAnalysis.Navigation +Imports Microsoft.VisualStudio.Composition +Imports Microsoft.VisualStudio.Text +Imports Roslyn.Test.Utilities +Imports Xunit + +Namespace Microsoft.CodeAnalysis.Editor.UnitTests.NavigableSymbols + + Public Class NavigableSymbolsTest + + Private Shared ReadOnly s_exportProvider As ExportProvider = MinimalTestExportProvider.CreateExportProvider( + TestExportProvider.EntireAssemblyCatalogWithCSharpAndVisualBasic.WithParts( + GetType(MockDocumentNavigationServiceProvider), + GetType(MockSymbolNavigationServiceProvider))) + + + Public Async Function TestCharp() As Task + Dim markup = " +class {|target:C|} +{ + {|highlighted:C|}$$ c +}" + Dim text As String = Nothing + Dim position As Integer? = Nothing + Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing + MarkupTestFile.GetPositionAndSpans(markup, text, position, spans) + + Using workspace = TestWorkspace.CreateCSharp(text, exportProvider:=s_exportProvider) + Await TestNavigated(workspace, position.Value, spans) + End Using + End Function + + + Public Async Function TestVB() As Task + Dim markup = " +Class {|target:C|} + Dim c as {|highlighted:C|}$$ +End Class" + Dim text As String = Nothing + Dim position As Integer? = Nothing + Dim spans As IDictionary(Of String, ImmutableArray(Of TextSpan)) = Nothing + MarkupTestFile.GetPositionAndSpans(markup, text, position, spans) + + Using workspace = TestWorkspace.CreateVisualBasic(text, exportProvider:=s_exportProvider) + Await TestNavigated(workspace, position.Value, spans) + End Using + End Function + + Private Async Function TestNavigated(workspace As TestWorkspace, position As Integer, spans As IDictionary(Of String, ImmutableArray(Of TextSpan))) As Task + Dim presenter = {New Lazy(Of IStreamingFindUsagesPresenter)(Function() New MockStreamingFindUsagesPresenter(Sub() Return))} + Dim service = New NavigableSymbolService(TestWaitIndicator.Default, presenter) + Dim view = workspace.Documents.First().GetTextView() + Dim buffer = workspace.Documents.First().GetTextBuffer() + Dim triggerSpan = New SnapshotSpan(buffer.CurrentSnapshot, New Span(position, 0)) + Dim source = service.TryCreateNavigableSymbolSource(view, buffer) + Dim symbol = Await source.GetNavigableSymbolAsync(triggerSpan, CancellationToken.None) + + Dim highlightedSpan = spans("highlighted").First() + Dim navigationTarget = spans("target").First() + + Assert.NotNull(symbol) + Assert.Equal(highlightedSpan.ToSpan(), symbol.SymbolSpan.Span) + + symbol.Navigate(symbol.Relationships.First()) + + Dim navigationService = DirectCast(workspace.Services.GetService(Of IDocumentNavigationService)(), MockDocumentNavigationServiceProvider.MockDocumentNavigationService) + Assert.Equal(True, navigationService.TryNavigateToLineAndOffsetReturnValue) + Assert.Equal(True, navigationService.TryNavigateToPositionReturnValue) + Assert.Equal(True, navigationService.TryNavigateToSpanReturnValue) + Assert.Equal(navigationTarget, navigationService.ProvidedTextSpan) + End Function + End Class +End Namespace diff --git a/src/EditorFeatures/TestUtilities/TextEditorFactoryExtensions.cs b/src/EditorFeatures/TestUtilities/TextEditorFactoryExtensions.cs index 0332c0c778e8f..228928231472a 100644 --- a/src/EditorFeatures/TestUtilities/TextEditorFactoryExtensions.cs +++ b/src/EditorFeatures/TestUtilities/TextEditorFactoryExtensions.cs @@ -15,7 +15,17 @@ public static DisposableTextView CreateDisposableTextView(this ITextEditorFactor public static DisposableTextView CreateDisposableTextView(this ITextEditorFactoryService textEditorFactory, ITextBuffer buffer) { - return new DisposableTextView(textEditorFactory.CreateTextView(buffer)); + // Every default role but outlining. Starting in 15.2, the editor + // OutliningManager imports JoinableTaskContext in a way that's + // difficult to satisfy in our unit tests. Since we don't directly + // depend on it, just disable it + var roles = textEditorFactory.CreateTextViewRoleSet(PredefinedTextViewRoles.Analyzable, + PredefinedTextViewRoles.Document, + PredefinedTextViewRoles.Editable, + PredefinedTextViewRoles.Interactive, + PredefinedTextViewRoles.Zoomable); + + return new DisposableTextView(textEditorFactory.CreateTextView(buffer, roles)); } } diff --git a/src/EditorFeatures/TestUtilities/Traits.cs b/src/EditorFeatures/TestUtilities/Traits.cs index 8e03c0de49996..9b74f127df849 100644 --- a/src/EditorFeatures/TestUtilities/Traits.cs +++ b/src/EditorFeatures/TestUtilities/Traits.cs @@ -85,6 +85,7 @@ public static class Features public const string CodeActionsOrderModifiers = "CodeActions.OrderModifiers"; public const string CodeActionsPopulateSwitch = "CodeActions.PopulateSwitch"; public const string CodeActionsQualifyMemberAccess = "CodeActions.QualifyMemberAccess"; + public const string CodeActionsReplaceDocCommentTextWithTag = "CodeActions.ReplaceDocCommentTextWithTag"; public const string CodeActionsReplaceMethodWithProperty = "CodeActions.ReplaceMethodWithProperty"; public const string CodeActionsReplacePropertyWithMethods = "CodeActions.ReplacePropertyWithMethods"; public const string CodeActionsRemoveByVal = "CodeActions.RemoveByVal"; @@ -152,6 +153,7 @@ public static class Features public const string LineSeparators = nameof(LineSeparators); public const string MetadataAsSource = nameof(MetadataAsSource); public const string NamingStyle = nameof(NamingStyle); + public const string NavigableSymbols = nameof(NavigableSymbols); public const string NavigateTo = nameof(NavigateTo); public const string NavigationBar = nameof(NavigationBar); public const string ObjectBrowser = nameof(ObjectBrowser); diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestHostDocument.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestHostDocument.cs index 015d6a3f12e9e..9fcf41e1ce3b2 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestHostDocument.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestHostDocument.cs @@ -135,8 +135,8 @@ public bool IsGenerated } public TestHostDocument( - string text = "", string displayName = "", - SourceCodeKind sourceCodeKind = SourceCodeKind.Regular, + string text = "", string displayName = "", + SourceCodeKind sourceCodeKind = SourceCodeKind.Regular, DocumentId id = null, string filePath = null, IReadOnlyList folders = null) { @@ -194,7 +194,7 @@ public override Task LoadTextAndVersionAsync(Workspace workspace return Task.FromResult(TextAndVersion.Create(text, VersionStamp.Create(), _hostDocument.FilePath)); } } - + public IWpfTextView GetTextView() { if (_textView == null) @@ -203,7 +203,18 @@ public IWpfTextView GetTextView() WpfTestCase.RequireWpfFact($"Creates an IWpfTextView through {nameof(TestHostDocument)}.{nameof(GetTextView)}"); - _textView = _exportProvider.GetExportedValue().CreateTextView(this.TextBuffer); + var factory = _exportProvider.GetExportedValue(); + + // Every default role but outlining. Starting in 15.2, the editor + // OutliningManager imports JoinableTaskContext in a way that's + // difficult to satisfy in our unit tests. Since we don't directly + // depend on it, just disable it + var roles = factory.CreateTextViewRoleSet(PredefinedTextViewRoles.Analyzable, + PredefinedTextViewRoles.Document, + PredefinedTextViewRoles.Editable, + PredefinedTextViewRoles.Interactive, + PredefinedTextViewRoles.Zoomable); + _textView = factory.CreateTextView(this.TextBuffer, roles); if (this.CursorPosition.HasValue) { _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot, CursorPosition.Value)); diff --git a/src/EditorFeatures/TestUtilities2/ServicesTestUtilities2.vbproj b/src/EditorFeatures/TestUtilities2/ServicesTestUtilities2.vbproj index 9152f130c61f5..c6958dd254754 100644 --- a/src/EditorFeatures/TestUtilities2/ServicesTestUtilities2.vbproj +++ b/src/EditorFeatures/TestUtilities2/ServicesTestUtilities2.vbproj @@ -63,6 +63,7 @@ + diff --git a/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/GoToTestHelpers.vb b/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/GoToTestHelpers.vb index dfda8e22ce62a..7aa821193daa1 100644 --- a/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/GoToTestHelpers.vb +++ b/src/EditorFeatures/TestUtilities2/Utilities/GoToHelpers/GoToTestHelpers.vb @@ -1,5 +1,7 @@ ' 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.Editor.CSharp.GoToDefinition +Imports Microsoft.CodeAnalysis.Editor.VisualBasic.GoToDefinition Imports Microsoft.CodeAnalysis.CSharp.GeneratedCodeRecognition Imports Microsoft.CodeAnalysis.Editor.Host Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces @@ -15,6 +17,8 @@ Namespace Microsoft.CodeAnalysis.Editor.UnitTests.Utilities.GoToHelpers Public ReadOnly Catalog As ComposableCatalog = TestExportProvider.MinimumCatalogWithCSharpAndVisualBasic.WithParts( GetType(MockDocumentNavigationServiceFactory), GetType(DefaultSymbolNavigationServiceFactory), + GetType(CSharpGoToDefinitionSymbolService), + GetType(VisualBasicGoToDefinitionSymbolService), GetType(CSharpGeneratedCodeRecognitionService), GetType(VisualBasicGeneratedCodeRecognitionService)) diff --git a/src/EditorFeatures/VisualBasic/BasicEditorFeatures.vbproj b/src/EditorFeatures/VisualBasic/BasicEditorFeatures.vbproj index ce92412ff56ab..da9f63835062c 100644 --- a/src/EditorFeatures/VisualBasic/BasicEditorFeatures.vbproj +++ b/src/EditorFeatures/VisualBasic/BasicEditorFeatures.vbproj @@ -22,7 +22,7 @@ - + True True VBEditorResources.resx diff --git a/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionService.vb b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionService.vb index a3cd253945dee..aa215beeefdd4 100644 --- a/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionService.vb +++ b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionService.vb @@ -15,9 +15,5 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.GoToDefinition Public Sub New( streamingPresenters As IEnumerable(Of Lazy(Of IStreamingFindUsagesPresenter))) MyBase.New(streamingPresenters) End Sub - - Protected Overrides Function FindRelatedExplicitlyDeclaredSymbol(symbol As ISymbol, compilation As Compilation) As ISymbol - Return symbol.FindRelatedExplicitlyDeclaredSymbol(compilation) - End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionSymbolService.vb b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionSymbolService.vb new file mode 100644 index 0000000000000..228b4a7d70945 --- /dev/null +++ b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToDefinitionSymbolService.vb @@ -0,0 +1,18 @@ +' 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 System.Composition +Imports Microsoft.CodeAnalysis.Editor.GoToDefinition +Imports Microsoft.CodeAnalysis.Editor.Host +Imports Microsoft.CodeAnalysis.Host.Mef +Imports Microsoft.CodeAnalysis.VisualBasic.Utilities + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.GoToDefinition + + Friend Class VisualBasicGoToDefinitionSymbolService + Inherits AbstractGoToDefinitionSymbolService + + Protected Overrides Function FindRelatedExplicitlyDeclaredSymbol(symbol As ISymbol, compilation As Compilation) As ISymbol + Return symbol.FindRelatedExplicitlyDeclaredSymbol(compilation) + End Function + End Class +End Namespace \ No newline at end of file diff --git a/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToSymbolService.vb b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToSymbolService.vb new file mode 100644 index 0000000000000..63f61a14af8f9 --- /dev/null +++ b/src/EditorFeatures/VisualBasic/GoToDefinition/VisualBasicGoToSymbolService.vb @@ -0,0 +1,11 @@ +Imports System.Composition +Imports Microsoft.CodeAnalysis.Editor.GoToDefinition +Imports Microsoft.CodeAnalysis.Host.Mef + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.GoToDefinition + + Friend Class VisualBasicGoToSymbolService + Inherits AbstractGoToSymbolService + + End Class +End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Classification/SemanticClassifierTests.vb b/src/EditorFeatures/VisualBasicTest/Classification/SemanticClassifierTests.vb index 9cecc4b998c31..aeddc8d9debdc 100644 --- a/src/EditorFeatures/VisualBasicTest/Classification/SemanticClassifierTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Classification/SemanticClassifierTests.vb @@ -545,5 +545,16 @@ end sub Await TestInClassAsync(text) End Function + + + + Public Async Function TestAttribute() As Task + Await TestAsync("Imports System + + +Class Program +End Class", + [Class]("AttributeUsage")) + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb b/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb index 4475eb204bb8d..2089fa5071c80 100644 --- a/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb +++ b/src/EditorFeatures/VisualBasicTest/CodeActions/MoveType/MoveTypeTests.MoveToNewFile.vb @@ -26,11 +26,11 @@ End Class " Await TestMissingInRegularAndScriptAsync(code) - End Function + End Function - - Public Async Function MultipleTypesInFileWithNoContainerNamespace() As Task - Dim code = + + Public Async Function MultipleTypesInFileWithNoContainerNamespace() As Task + Dim code = " [||]Class Class1 End Class @@ -224,5 +224,93 @@ End Class " Await TestMoveTypeToNewFileAsync(code, codeAfterMove, expectedDocumentName, destinationDocumentText) End Function + + + + Public Async Function TestLeadingBlankLines1() As Task + Dim code = +"' Banner Text +imports System + +[||]class Class1 + sub Foo() + Console.WriteLine() + end sub +end class + +class Class2 + sub Foo() + Console.WriteLine() + end sub +end class +" + Dim codeAfterMove = "' Banner Text +imports System + +class Class2 + sub Foo() + Console.WriteLine() + end sub +end class +" + + Dim expectedDocumentName = "Class1.vb" + Dim destinationDocumentText = "' Banner Text +imports System + +class Class1 + sub Foo() + Console.WriteLine() + end sub +end class +" + + Await TestMoveTypeToNewFileAsync( + code, codeAfterMove, expectedDocumentName, destinationDocumentText) + End Function + + + + Public Async Function TestLeadingBlankLines2() As Task + Dim code = +"' Banner Text +imports System + +class Class1 + sub Foo() + Console.WriteLine() + end sub +end class + +[||]class Class2 + sub Foo() + Console.WriteLine() + end sub +end class +" + Dim codeAfterMove = "' Banner Text +imports System + +class Class1 + sub Foo() + Console.WriteLine() + end sub +end class +" + + Dim expectedDocumentName = "Class2.vb" + Dim destinationDocumentText = "' Banner Text +imports System + +class Class2 + sub Foo() + Console.WriteLine() + end sub +end class +" + + Await TestMoveTypeToNewFileAsync( + code, codeAfterMove, expectedDocumentName, destinationDocumentText) + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb index 9ff4ceb54e975..b0d626ebda015 100644 --- a/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb +++ b/src/EditorFeatures/VisualBasicTest/Diagnostics/AddImport/AddImportTests_NuGet.vb @@ -239,7 +239,7 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa installerServiceMock.Verify() End Function - Private Function CreateSearchResult(packageName As String, typeName As String, nameParts As ImmutableArray(Of String)) As Task(Of ImmutableArray(Of PackageWithTypeResult)) + Private Function CreateSearchResult(packageName As String, typeName As String, nameParts As ImmutableArray(Of String)) As Task(Of IList(Of PackageWithTypeResult)) Return CreateSearchResult(New PackageWithTypeResult( packageName:=packageName, typeName:=typeName, @@ -248,8 +248,8 @@ End Class", fixProviderData:=New ProviderData(installerServiceMock.Object, packa containingNamespaceNames:=nameParts)) End Function - Private Function CreateSearchResult(ParamArray results As PackageWithTypeResult()) As Task(Of ImmutableArray(Of PackageWithTypeResult)) - Return Task.FromResult(ImmutableArray.Create(results)) + Private Function CreateSearchResult(ParamArray results As PackageWithTypeResult()) As Task(Of IList(Of PackageWithTypeResult)) + Return Task.FromResult(Of IList(Of PackageWithTypeResult))(ImmutableArray.Create(results)) End Function Private Function CreateNameParts(ParamArray parts As String()) As ImmutableArray(Of String) diff --git a/src/EditorFeatures/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb b/src/EditorFeatures/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb new file mode 100644 index 0000000000000..79c08c2e15ddc --- /dev/null +++ b/src/EditorFeatures/VisualBasicTest/ReplaceDocCommentTextWithTag/ReplaceDocCommentTextWithTagTests.vb @@ -0,0 +1,319 @@ +' 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.CodeRefactorings +Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.CodeRefactorings +Imports Microsoft.CodeAnalysis.VisualBasic.ReplaceDocCommentTextWithTag + +Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.ReplaceDocCommentTextWithTag + Public Class ReplaceDocCommentTextWithTagTests + Inherits AbstractVisualBasicCodeActionTest + + Protected Overrides Function CreateCodeRefactoringProvider(Workspace As Workspace, parameters As TestParameters) As CodeRefactoringProvider + Return New VisualBasicReplaceDocCommentTextWithTagCodeRefactoringProvider() + End Function + + + Public Async Function TestStartOfKeyword() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable [||]interface. +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable . +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfKeywordCapitalized() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable [||]Interface. +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable . +class C(Of TKey) +end class") + End Function + + + Public Async Function TestEndOfKeyword() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable interface[||]. +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable . +class C(Of TKey) +end class") + End Function + + + Public Async Function TestEndOfKeyword_NewLineFollowing() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable interface[||] +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable +class C(Of TKey) +end class") + End Function + + + Public Async Function TestSelectedKeyword() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable [|interface|]. +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable . +class C(Of TKey) +end class") + End Function + + + Public Async Function TestInsideKeyword() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable int[||]erface. +class C(Of TKey) +end class", +" +''' TKey must implement the System.IDisposable . +class C(Of TKey) +end class") + End Function + + + Public Async Function TestNotInsideKeywordIfNonEmptySpan() As Task + Await TestMissingAsync( +" +''' TKey must implement the System.IDisposable int[|erf|]ace +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_Start() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the [||]System.IDisposable interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_Mid1() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System[||].IDisposable interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_Mid2() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.[||]IDisposable interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_End() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the System.IDisposable[||] interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_CaseInsensitive() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the [||]system.idisposable interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestStartOfFullyQualifiedTypeName_Selected() As Task + Await TestInRegularAndScriptAsync( +" +''' TKey must implement the [|System.IDisposable|] interface. +class C(Of TKey) +end class", +" +''' TKey must implement the interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestTypeParameterReference() As Task + Await TestInRegularAndScriptAsync( +" +''' [||]TKey must implement the System.IDisposable interface. +class C(Of TKey) +end class", +" +''' must implement the System.IDisposable interface. +class C(Of TKey) +end class") + End Function + + + Public Async Function TestCanSeeInnerMethod() As Task + Await TestInRegularAndScriptAsync( +" +''' Use WriteLine[||] as a Console.WriteLine replacement +class C + sub WriteLine(Of TKey)(value as TKey) + end sub +end class", +" +''' Use as a Console.WriteLine replacement +class C + sub WriteLine(Of TKey)(value as TKey) + end sub +end class") + End Function + + + Public Async Function TestNotOnMispelledName() As Task + Await TestMissingAsync( +" +''' Use WriteLine1[||] as a Console.WriteLine replacement +class C + sub WriteLine(Of TKey)(value as TKey) + end sub +end class") + End Function + + + Public Async Function TestMethodTypeParameterSymbol() As Task + Await TestInRegularAndScriptAsync( +" +class C + ''' value has type TKey[||] so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) + end sub +end class", +" +class C + ''' value has type so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) + end sub +end class") + End Function + + + Public Async Function TestMethodTypeParameterSymbol_CaseInsensitive() As Task + Await TestInRegularAndScriptAsync( +" +class C + ''' value has type TKey[||] so we don't box primitives. + sub WriteLine(Of tkey)(value as TKey) + end sub +end class", +" +class C + ''' value has type so we don't box primitives. + sub WriteLine(Of tkey)(value as TKey) + end sub +end class") + End Function + + + Public Async Function TestMethodTypeParameterSymbol_EmptyBody() As Task + Await TestInRegularAndScriptAsync( +" +interface I + ''' value has type TKey[||] so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) +end interface", +" +interface I + ''' value has type so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) +end interface") + End Function + + + Public Async Function TestMethodParameterSymbol() As Task + Await TestInRegularAndScriptAsync( +" +class C + ''' value[||] has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) + end sub +end class", +" +class C + ''' has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) + end sub +end class") + End Function + + + Public Async Function TestMethodParameterSymbol_CaseInsensitive() As Task + Await TestInRegularAndScriptAsync( +" +class C + ''' value[||] has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(Value as TKey) + end sub +end class", +" +class C + ''' has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(Value as TKey) + end sub +end class") + End Function + + + Public Async Function TestMethodParameterSymbol_EmptyBody() As Task + Await TestInRegularAndScriptAsync( +" +interface I + ''' value[||] has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) +end interface", +" +interface I + ''' has type TKey so we don't box primitives. + sub WriteLine(Of TKey)(value as TKey) +end interface") + End Function + End Class +End Namespace diff --git a/src/Features/CSharp/Portable/ReplaceDocCommentTextWithTag/CSharpReplaceDocCommentTextWithTagCodeRefactoringProvider.cs b/src/Features/CSharp/Portable/ReplaceDocCommentTextWithTag/CSharpReplaceDocCommentTextWithTagCodeRefactoringProvider.cs new file mode 100644 index 0000000000000..486375fac176c --- /dev/null +++ b/src/Features/CSharp/Portable/ReplaceDocCommentTextWithTag/CSharpReplaceDocCommentTextWithTagCodeRefactoringProvider.cs @@ -0,0 +1,25 @@ +// 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.Composition; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.ReplaceDocCommentTextWithTag; + +namespace Microsoft.CodeAnalysis.CSharp.ReplaceDocCommentTextWithTag +{ + [ExportCodeRefactoringProvider(LanguageNames.CSharp), Shared] + internal class CSharpReplaceDocCommentTextWithTagCodeRefactoringProvider : + AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider + { + protected override bool IsXmlTextToken(SyntaxToken token) + => token.Kind() == SyntaxKind.XmlTextLiteralToken || + token.Kind() == SyntaxKind.XmlTextLiteralNewLineToken; + + protected override bool IsAnyKeyword(string text) + => SyntaxFacts.GetKeywordKind(text) != SyntaxKind.None || + SyntaxFacts.GetContextualKeywordKind(text) != SyntaxKind.None; + + protected override SyntaxNode ParseExpression(string text) + => SyntaxFactory.ParseExpression(text); + } +} diff --git a/src/Features/CSharp/Portable/TodoComments/CSharpTodoCommentIncrementalAnalyzerProvider.cs b/src/Features/CSharp/Portable/TodoComments/CSharpTodoCommentIncrementalAnalyzerProvider.cs index 2ae1686fea383..a2fca9fda9b74 100644 --- a/src/Features/CSharp/Portable/TodoComments/CSharpTodoCommentIncrementalAnalyzerProvider.cs +++ b/src/Features/CSharp/Portable/TodoComments/CSharpTodoCommentIncrementalAnalyzerProvider.cs @@ -28,7 +28,7 @@ public CSharpTodoCommentService(Workspace workspace) : base(workspace) { } - protected override void AppendTodoComments(ImmutableArray commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, List todoList) + protected override void AppendTodoComments(IList commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, List todoList) { if (PreprocessorHasComment(trivia)) { diff --git a/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs b/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs index f591a7a63ef7b..7b8b5ce36878e 100644 --- a/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs +++ b/src/Features/Core/Portable/AddImport/AbstractAddImportFeatureService.cs @@ -61,7 +61,7 @@ protected AbstractAddImportFeatureService() if (RemoteSupportedLanguages.IsSupported(document.Project.Language)) { var callbackTarget = new RemoteSymbolSearchService(symbolSearchService, cancellationToken); - var result = await document.Project.Solution.TryRunCodeAnalysisRemoteAsync>( + var result = await document.Project.Solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.AddImportEnabled, callbackTarget, nameof(IRemoteAddImportFeatureService.GetFixesAsync), @@ -78,9 +78,9 @@ protected AbstractAddImportFeatureService() var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); - if (!result.IsDefault) + if (result != null) { - return result; + return result.ToImmutableArray(); } } diff --git a/src/Features/Core/Portable/AddImport/Remote/AbstractAddImportFeatureService_Remote.cs b/src/Features/Core/Portable/AddImport/Remote/AbstractAddImportFeatureService_Remote.cs index 061faee76876d..8fa8bf9509476 100644 --- a/src/Features/Core/Portable/AddImport/Remote/AbstractAddImportFeatureService_Remote.cs +++ b/src/Features/Core/Portable/AddImport/Remote/AbstractAddImportFeatureService_Remote.cs @@ -1,6 +1,7 @@ // 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 System.Threading; using System.Threading.Tasks; @@ -39,21 +40,21 @@ public Task UpdateContinuouslyAsync(string sourceName, string localSettingsDirec throw new NotImplementedException(); } - public Task> FindPackagesWithTypeAsync( + public Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken) { return _symbolSearchService.FindPackagesWithTypeAsync( source, name, arity, cancellationToken); } - public Task> FindPackagesWithAssemblyAsync( + public Task> FindPackagesWithAssemblyAsync( string source, string name, CancellationToken cancellationToken) { return _symbolSearchService.FindPackagesWithAssemblyAsync( source, name, cancellationToken); } - public Task> FindReferenceAssembliesWithTypeAsync( + public Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken) { return _symbolSearchService.FindReferenceAssembliesWithTypeAsync( diff --git a/src/Features/Core/Portable/AddImport/Remote/IRemoteAddImportFeatureService.cs b/src/Features/Core/Portable/AddImport/Remote/IRemoteAddImportFeatureService.cs index 550c375c35fcc..5fff125b7ef9a 100644 --- a/src/Features/Core/Portable/AddImport/Remote/IRemoteAddImportFeatureService.cs +++ b/src/Features/Core/Portable/AddImport/Remote/IRemoteAddImportFeatureService.cs @@ -1,5 +1,6 @@ // 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.Threading; using System.Threading.Tasks; @@ -10,8 +11,8 @@ namespace Microsoft.CodeAnalysis.AddImport { internal interface IRemoteAddImportFeatureService { - Task> GetFixesAsync( + Task> GetFixesAsync( DocumentId documentId, TextSpan span, string diagnosticId, bool placeSystemNamespaceFirst, - bool searchReferenceAssemblies, ImmutableArray packageSources, CancellationToken cancellationToken); + bool searchReferenceAssemblies, IList packageSources, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs index 70fcebdd37e76..7ab3d06324af3 100644 --- a/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs +++ b/src/Features/Core/Portable/AddImport/SymbolReferenceFinder_PackageAssemblySearch.cs @@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.SymbolSearch; +using Microsoft.CodeAnalysis.Utilities; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.AddImport @@ -90,7 +91,7 @@ private partial class SymbolReferenceFinder cancellationToken.ThrowIfCancellationRequested(); var results = await _symbolSearchService.FindReferenceAssembliesWithTypeAsync( name, arity, cancellationToken).ConfigureAwait(false); - if (results.IsDefault) + if (results == null) { return; } @@ -121,7 +122,7 @@ private partial class SymbolReferenceFinder cancellationToken.ThrowIfCancellationRequested(); var results = await _symbolSearchService.FindPackagesWithTypeAsync( source.Name, name, arity, cancellationToken).ConfigureAwait(false); - if (results.IsDefault) + if (results == null) { return; } @@ -163,7 +164,7 @@ private partial class SymbolReferenceFinder var desiredName = GetDesiredName(isAttributeSearch, result.TypeName); allReferences.Add(new AssemblyReference( - _owner, new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight), result)); + _owner, new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames.ToReadOnlyList(), weight), result)); } private void HandleNugetReference( @@ -177,7 +178,7 @@ private partial class SymbolReferenceFinder { var desiredName = GetDesiredName(isAttributeSearch, result.TypeName); allReferences.Add(new PackageReference(_owner, - new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight), + new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames.ToReadOnlyList(), weight), source, result.PackageName, result.Version)); } diff --git a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs index f19e2f513252b..e79fc52e01e57 100644 --- a/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs +++ b/src/Features/Core/Portable/CodeRefactorings/MoveType/AbstractMoveTypeService.MoveTypeEditor.cs @@ -271,24 +271,21 @@ private static bool FilterToTopLevelMembers(SyntaxNode node, SyntaxNode typeNode { var currentTypeNode = (TTypeDeclarationSyntax)currentNode; - // Trim leading whitespace from the type so we don't have excessive - // leading blank lines. - return RemoveLeadingWhitespace(currentTypeNode); + // Trim leading blank lines from the type so we don't have an + // excessive number of them. + return RemoveLeadingBlankLines(currentTypeNode); }); } - private TTypeDeclarationSyntax RemoveLeadingWhitespace( + private TTypeDeclarationSyntax RemoveLeadingBlankLines( TTypeDeclarationSyntax currentTypeNode) { var syntaxFacts = State.SemanticDocument.Document.GetLanguageService(); - var leadingTrivia = currentTypeNode.GetLeadingTrivia(); - var afterWhitespace = leadingTrivia.SkipWhile( - t => syntaxFacts.IsWhitespaceTrivia(t) || syntaxFacts.IsEndOfLineTrivia(t)); - - var withoutLeadingWhitespace = currentTypeNode.WithLeadingTrivia(afterWhitespace); - return withoutLeadingWhitespace.ReplaceToken( - withoutLeadingWhitespace.GetFirstToken(), - withoutLeadingWhitespace.GetFirstToken().WithAdditionalAnnotations(Formatter.Annotation)); + var withoutBlankLines = syntaxFacts.GetNodeWithoutLeadingBlankLines(currentTypeNode); + + // Add an elastic marker so the formatter can add any blank lines it thinks are + // important to have (i.e. after a block of usings/imports). + return withoutBlankLines.WithPrependedLeadingTrivia(syntaxFacts.ElasticMarker); } } } diff --git a/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs b/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs index 5c915a4c9a39c..3f09f0a062bc9 100644 --- a/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs +++ b/src/Features/Core/Portable/DesignerAttributes/IRemoteDesignerAttributeService.cs @@ -1,6 +1,6 @@ // 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.Immutable; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -8,6 +8,6 @@ namespace Microsoft.CodeAnalysis.DesignerAttributes { internal interface IRemoteDesignerAttributeService { - Task> ScanDesignerAttributesAsync(ProjectId projectId, CancellationToken cancellationToken); + Task> ScanDesignerAttributesAsync(ProjectId projectId, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs index 5d78c9d79f7ca..d7d3b5506f387 100644 --- a/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs +++ b/src/Features/Core/Portable/DocumentHighlighting/AbstractDocumentHighlightsService.cs @@ -39,7 +39,7 @@ internal abstract partial class AbstractDocumentHighlightsService : IDocumentHig private async Task<(bool succeeded, ImmutableArray highlights)> GetDocumentHighlightsInRemoteProcessAsync( Document document, int position, IImmutableSet documentsToSearch, CancellationToken cancellationToken) { - var result = await document.Project.Solution.TryRunCodeAnalysisRemoteAsync>( + var result = await document.Project.Solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.DocumentHighlightingEnabled, nameof(IRemoteDocumentHighlights.GetDocumentHighlightsAsync), new object[] @@ -50,7 +50,7 @@ internal abstract partial class AbstractDocumentHighlightsService : IDocumentHig }, cancellationToken).ConfigureAwait(false); - if (result.IsDefault) + if (result == null) { return (succeeded: false, ImmutableArray.Empty); } diff --git a/src/Features/Core/Portable/DocumentHighlighting/IRemoteDocumentHighlights.cs b/src/Features/Core/Portable/DocumentHighlighting/IRemoteDocumentHighlights.cs index 43cd320c46565..df95e87c8fe14 100644 --- a/src/Features/Core/Portable/DocumentHighlighting/IRemoteDocumentHighlights.cs +++ b/src/Features/Core/Portable/DocumentHighlighting/IRemoteDocumentHighlights.cs @@ -1,5 +1,6 @@ // 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.Threading; @@ -9,17 +10,17 @@ namespace Microsoft.CodeAnalysis.DocumentHighlighting { internal interface IRemoteDocumentHighlights { - Task> GetDocumentHighlightsAsync( + Task> GetDocumentHighlightsAsync( DocumentId documentId, int position, DocumentId[] documentIdsToSearch, CancellationToken cancellationToken); } internal struct SerializableDocumentHighlights { public DocumentId DocumentId; - public ImmutableArray HighlightSpans; + public IList HighlightSpans; public DocumentHighlights Rehydrate(Solution solution) - => new DocumentHighlights(solution.GetDocument(DocumentId), HighlightSpans); + => new DocumentHighlights(solution.GetDocument(DocumentId), HighlightSpans.ToImmutableArray()); public static SerializableDocumentHighlights Dehydrate(DocumentHighlights highlights) => new SerializableDocumentHighlights diff --git a/src/Features/Core/Portable/FeaturesResources.Designer.cs b/src/Features/Core/Portable/FeaturesResources.Designer.cs index 84d9b1dd30be9..0e0ac0b45e2d7 100644 --- a/src/Features/Core/Portable/FeaturesResources.Designer.cs +++ b/src/Features/Core/Portable/FeaturesResources.Designer.cs @@ -3354,6 +3354,15 @@ internal class FeaturesResources { } } + /// + /// Looks up a localized string similar to Use {0}. + /// + internal static string Use_0 { + get { + return ResourceManager.GetString("Use_0", resourceCulture); + } + } + /// /// Looks up a localized string similar to Use auto property. /// diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index 78f762609b8cb..c2c7d0a5f392a 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -1301,4 +1301,7 @@ This version used in: {2} Warning: Method overrides symbol from metadata + + Use {0} + \ No newline at end of file diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs index cbc58c586469f..86c89802aaae2 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractAddParameterCheckCodeRefactoringProvider.cs @@ -105,10 +105,10 @@ internal abstract partial class AbstractAddParameterCheckCodeRefactoringProvider foreach (var coalesceNode in syntax.DescendantNodes().OfType()) { var operation = GetOperation(semanticModel, coalesceNode, cancellationToken); - if (operation is INullCoalescingExpression coalesceExpression) + if (operation is ICoalesceExpression coalesceExpression) { - if (IsParameterReference(coalesceExpression.PrimaryOperand, parameter) && - syntaxFacts.IsThrowExpression(coalesceExpression.SecondaryOperand.Syntax)) + if (IsParameterReference(coalesceExpression.Expression, parameter) && + syntaxFacts.IsThrowExpression(coalesceExpression.WhenNull.Syntax)) { return true; } diff --git a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs index a66107af87256..8c74a89e48d9e 100644 --- a/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs +++ b/src/Features/Core/Portable/InitializeParameter/AbstractInitializeMemberFromParameterCodeRefactoringProviderMemberCreation.cs @@ -391,8 +391,8 @@ private IOperation TryFindFieldOrPropertyAssignmentStatement(IParameterSymbol pa return true; } - if (UnwrapImplicitConversion(assignmentExpression.Value) is INullCoalescingExpression coalesceExpression && - IsParameterReference(coalesceExpression.PrimaryOperand, parameter)) + if (UnwrapImplicitConversion(assignmentExpression.Value) is ICoalesceExpression coalesceExpression && + IsParameterReference(coalesceExpression.Expression, parameter)) { // We already have a member initialized with this parameter like: // this.field = parameter ?? ... diff --git a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs index 55e53c71ee74a..f7bf8a75e7677 100644 --- a/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs +++ b/src/Features/Core/Portable/NavigateTo/AbstractNavigateToSearchService.Remote.cs @@ -1,12 +1,14 @@ // 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 System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Experiments; using Microsoft.CodeAnalysis.Remote; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.NavigateTo { @@ -17,11 +19,11 @@ internal abstract partial class AbstractNavigateToSearchService { var solution = document.Project.Solution; - var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( + var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchDocumentAsync), new object[] { document.Id, searchPattern }, cancellationToken).ConfigureAwait(false); - return serializableResults.NullToEmpty().SelectAsArray(r => r.Rehydrate(solution)); + return serializableResults.SelectAsArray(r => r.Rehydrate(solution)); } private async Task> SearchProjectInRemoteProcessAsync( @@ -29,11 +31,11 @@ internal abstract partial class AbstractNavigateToSearchService { var solution = project.Solution; - var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( + var serializableResults = await client.TryRunCodeAnalysisRemoteAsync>( solution, nameof(IRemoteNavigateToSearchService.SearchProjectAsync), new object[] { project.Id, searchPattern }, cancellationToken).ConfigureAwait(false); - return serializableResults.NullToEmpty().SelectAsArray(r => r.Rehydrate(solution)); + return serializableResults.SelectAsArray(r => r.Rehydrate(solution)); } private static async Task TryGetRemoteHostClientAsync(Project project, CancellationToken cancellationToken) diff --git a/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs b/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs index 936a91a04fce4..16f5a09bd0715 100644 --- a/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs +++ b/src/Features/Core/Portable/NavigateTo/IRemoteNavigateToSearchService.cs @@ -1,5 +1,6 @@ // 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.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ namespace Microsoft.CodeAnalysis.NavigateTo { internal interface IRemoteNavigateToSearchService { - Task> SearchDocumentAsync(DocumentId documentId, string searchPattern, CancellationToken cancellationToken); - Task> SearchProjectAsync(ProjectId projectId, string searchPattern, CancellationToken cancellationToken); + Task> SearchDocumentAsync(DocumentId documentId, string searchPattern, CancellationToken cancellationToken); + Task> SearchProjectAsync(ProjectId projectId, string searchPattern, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/ReplaceDocCommentTextWithTag/AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider.cs b/src/Features/Core/Portable/ReplaceDocCommentTextWithTag/AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider.cs new file mode 100644 index 0000000000000..10dd83805044f --- /dev/null +++ b/src/Features/Core/Portable/ReplaceDocCommentTextWithTag/AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider.cs @@ -0,0 +1,238 @@ +// 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.Composition; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.CodeAnalysis.ReplaceDocCommentTextWithTag +{ + internal abstract class AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider : CodeRefactoringProvider + { + protected abstract bool IsAnyKeyword(string text); + protected abstract bool IsXmlTextToken(SyntaxToken token); + protected abstract SyntaxNode ParseExpression(string text); + + public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) + { + var document = context.Document; + var span = context.Span; + var cancellationToken = context.CancellationToken; + + var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var token = root.FindToken(span.Start, findInsideTrivia: true); + + if (!IsXmlTextToken(token)) + { + return; + } + + if (!token.FullSpan.Contains(span)) + { + return; + } + + var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + + var singleWordSpan = ExpandSpan(sourceText, span, fullyQualifiedName: false); + var singleWordText = sourceText.ToString(singleWordSpan); + if (singleWordText == "") + { + return; + } + + // First see if they're on a keyword. + if (IsAnyKeyword(singleWordText)) + { + RegisterRefactoring(context, singleWordSpan, $@""); + return; + } + + // Not a keyword, see if it semantically means anything in the current context. + var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + var symbol = GetEnclosingSymbol(semanticModel, span.Start, cancellationToken); + if (symbol == null) + { + return; + } + + // See if we can expand the term out to a fully qualified name. Do this + // first in case the user has something like X.memberName. We don't want + // to try to bind "memberName" first as it might bind to something like + // a parameter, which is not what the user intends + var fullyQualifiedSpan = ExpandSpan(sourceText, span, fullyQualifiedName: true); + if (fullyQualifiedSpan != singleWordSpan) + { + var fullyQualifiedText = sourceText.ToString(fullyQualifiedSpan); + if (TryRegisterSeeCrefTagIfSymbol( + context, semanticModel, token, fullyQualifiedSpan, cancellationToken)) + { + return; + } + } + + // Check if the single word could be binding to a type parameter or parameter + // for the current symbol. + var syntaxFacts = document.GetLanguageService(); + var parameter = symbol.GetParameters().FirstOrDefault(p => syntaxFacts.StringComparer.Equals(p.Name, singleWordText)); + if (parameter != null) + { + RegisterRefactoring(context, singleWordSpan, $@""); + return; + } + + var typeParameter = symbol.GetTypeParameters().FirstOrDefault(t => syntaxFacts.StringComparer.Equals(t.Name, singleWordText)); + if (typeParameter != null) + { + RegisterRefactoring(context, singleWordSpan, $@""); + return; + } + + // Doc comments on a named type can see the members inside of it. So check + // inside the named type for a member that matches. + if (symbol is INamedTypeSymbol namedType) + { + var childMember = namedType.GetMembers().FirstOrDefault(m => syntaxFacts.StringComparer.Equals(m.Name, singleWordText)); + if (childMember != null) + { + RegisterRefactoring(context, singleWordSpan, $@""); + return; + } + } + + // Finally, try to speculatively bind the name and see if it binds to anything + // in the surrounding context. + TryRegisterSeeCrefTagIfSymbol( + context, semanticModel, token, singleWordSpan, cancellationToken); + } + + private bool TryRegisterSeeCrefTagIfSymbol( + CodeRefactoringContext context, SemanticModel semanticModel, SyntaxToken token, TextSpan replacementSpan, CancellationToken cancellationToken) + { + var sourceText = semanticModel.SyntaxTree.GetText(cancellationToken); + var text = sourceText.ToString(replacementSpan); + + var parsed = ParseExpression(text); + var foundSymbol = semanticModel.GetSpeculativeSymbolInfo(token.SpanStart, parsed, SpeculativeBindingOption.BindAsExpression).GetAnySymbol(); + if (foundSymbol == null) + { + return false; + } + + RegisterRefactoring(context, replacementSpan, $@""); + return true; + } + + private ISymbol GetEnclosingSymbol(SemanticModel semanticModel, int position, CancellationToken cancellationToken) + { + var root = semanticModel.SyntaxTree.GetRoot(cancellationToken); + var token = root.FindToken(position); + + for (var node = token.Parent; node != null; node = node.Parent) + { + if (semanticModel.GetDeclaredSymbol(node) is ISymbol declaration) + { + return declaration; + } + } + + return null; + } + + private void RegisterRefactoring( + CodeRefactoringContext context, TextSpan expandedSpan, string replacement) + { + context.RegisterRefactoring(new MyCodeAction( + string.Format(FeaturesResources.Use_0, replacement), + c => ReplaceTextAsync(context.Document, expandedSpan, replacement, c))); + } + + private async Task ReplaceTextAsync( + Document document, TextSpan span, string replacement, CancellationToken cancellationToken) + { + var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); + var newText = text.Replace(span, replacement); + + return document.WithText(newText); + } + + private TextSpan ExpandSpan(SourceText sourceText, TextSpan span, bool fullyQualifiedName) + { + if (span.Length != 0) + { + return span; + } + + var startInclusive = span.Start; + var endExclusive = span.Start; + while (startInclusive > 0 && + ShouldExpandSpanBackwardOneCharacter(sourceText, startInclusive, fullyQualifiedName)) + { + startInclusive--; + } + + while (endExclusive < sourceText.Length && + ShouldExpandSpanForwardOneCharacter(sourceText, endExclusive, fullyQualifiedName)) + { + endExclusive++; + } + + return TextSpan.FromBounds(startInclusive, endExclusive); + } + + private bool ShouldExpandSpanForwardOneCharacter( + SourceText sourceText, int endExclusive, bool fullyQualifiedName) + { + var currentChar = sourceText[endExclusive]; + + if (char.IsLetterOrDigit(currentChar)) + { + return true; + } + + // Only consume a dot in front of the current word if it is part of a dotted + // word chain, and isn't just the end of a sentence. + if (fullyQualifiedName && currentChar == '.' && + endExclusive + 1 < sourceText.Length && char.IsLetterOrDigit(sourceText[endExclusive + 1])) + { + return true; + } + + return false; + } + + private bool ShouldExpandSpanBackwardOneCharacter( + SourceText sourceText, int startInclusive, bool fullyQualifiedName) + { + Debug.Assert(startInclusive > 0); + + var previousCharacter = sourceText[startInclusive - 1]; + if (char.IsLetterOrDigit(previousCharacter)) + { + return true; + } + + if (fullyQualifiedName && previousCharacter == '.') + { + return true; + } + + return false; + } + + private class MyCodeAction : CodeAction.DocumentChangeAction + { + public MyCodeAction(string title, Func> createChangedDocument) + : base(title, createChangedDocument) + { + } + } + } +} diff --git a/src/Features/Core/Portable/Shared/TestHooks/FeatureMetadata.cs b/src/Features/Core/Portable/Shared/TestHooks/FeatureMetadata.cs index 618ceab3af11b..59b7c17ccefdf 100644 --- a/src/Features/Core/Portable/Shared/TestHooks/FeatureMetadata.cs +++ b/src/Features/Core/Portable/Shared/TestHooks/FeatureMetadata.cs @@ -19,8 +19,11 @@ internal class FeatureMetadata public string FeatureName { get; } public FeatureMetadata(IDictionary data) + : this((string)data.GetValueOrDefault("FeatureName")) { - this.FeatureName = (string)data.GetValueOrDefault("FeatureName"); } + + public FeatureMetadata(string featureName) + => FeatureName = featureName; } } diff --git a/src/Features/Core/Portable/TodoComments/AbstractTodoCommentService.cs b/src/Features/Core/Portable/TodoComments/AbstractTodoCommentService.cs index c39525a3e5dec..d4eeb07e6259e 100644 --- a/src/Features/Core/Portable/TodoComments/AbstractTodoCommentService.cs +++ b/src/Features/Core/Portable/TodoComments/AbstractTodoCommentService.cs @@ -36,9 +36,9 @@ protected AbstractTodoCommentService(Workspace workspace) protected abstract string GetNormalizedText(string message); protected abstract int GetCommentStartingIndex(string message); - protected abstract void AppendTodoComments(ImmutableArray commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, List todoList); + protected abstract void AppendTodoComments(IList commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, List todoList); - public async Task> GetTodoCommentsAsync(Document document, ImmutableArray commentDescriptors, CancellationToken cancellationToken) + public async Task> GetTodoCommentsAsync(Document document, IList commentDescriptors, CancellationToken cancellationToken) { // make sure given input is right one Contract.ThrowIfFalse(_workspace == document.Project.Solution.Workspace); @@ -59,7 +59,7 @@ public async Task> GetTodoCommentsAsync(Document document, Im } private async Task> GetTodoCommentsInRemoteHostAsync( - RemoteHostClient client, Document document, ImmutableArray commentDescriptors, CancellationToken cancellationToken) + RemoteHostClient client, Document document, IList commentDescriptors, CancellationToken cancellationToken) { var keepAliveSession = await TryGetKeepAliveSessionAsync(client, cancellationToken).ConfigureAwait(false); @@ -85,7 +85,7 @@ private async Task TryGetKeepAliveSessionAsync(RemoteHostClien } private async Task> GetTodoCommentsInCurrentProcessAsync( - Document document, ImmutableArray commentDescriptors, CancellationToken cancellationToken) + Document document, IList commentDescriptors, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -115,7 +115,7 @@ private bool ContainsComments(SyntaxTrivia trivia) return PreprocessorHasComment(trivia) || IsSingleLineComment(trivia) || IsMultilineComment(trivia); } - protected void AppendTodoCommentInfoFromSingleLine(ImmutableArray commentDescriptors, SyntacticDocument document, string message, int start, List todoList) + protected void AppendTodoCommentInfoFromSingleLine(IList commentDescriptors, SyntacticDocument document, string message, int start, List todoList) { var index = GetCommentStartingIndex(message); if (index >= message.Length) @@ -147,7 +147,7 @@ protected void AppendTodoCommentInfoFromSingleLine(ImmutableArray commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, int postfixLength, List todoList) + protected void ProcessMultilineComment(IList commentDescriptors, SyntacticDocument document, SyntaxTrivia trivia, int postfixLength, List todoList) { // this is okay since we know it is already alive var text = document.Text; diff --git a/src/Features/Core/Portable/TodoComments/IRemoteTodoCommentService.cs b/src/Features/Core/Portable/TodoComments/IRemoteTodoCommentService.cs index 5fd991c6d5718..c518327f06a39 100644 --- a/src/Features/Core/Portable/TodoComments/IRemoteTodoCommentService.cs +++ b/src/Features/Core/Portable/TodoComments/IRemoteTodoCommentService.cs @@ -13,6 +13,6 @@ namespace Microsoft.CodeAnalysis.TodoComments /// internal interface IRemoteTodoCommentService { - Task> GetTodoCommentsAsync(PinnedSolutionInfo solutionInfo, DocumentId documentId, ImmutableArray commentDescriptors, CancellationToken cancellationToken); + Task> GetTodoCommentsAsync(PinnedSolutionInfo solutionInfo, DocumentId documentId, IList commentDescriptors, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/TodoComments/ITodoCommentService.cs b/src/Features/Core/Portable/TodoComments/ITodoCommentService.cs index b1407ad36478c..e6a3689445361 100644 --- a/src/Features/Core/Portable/TodoComments/ITodoCommentService.cs +++ b/src/Features/Core/Portable/TodoComments/ITodoCommentService.cs @@ -42,6 +42,6 @@ public TodoComment(TodoCommentDescriptor descriptor, string message, int positio internal interface ITodoCommentService : ILanguageService { - Task> GetTodoCommentsAsync(Document document, ImmutableArray commentDescriptors, CancellationToken cancellationToken); + Task> GetTodoCommentsAsync(Document document, IList commentDescriptors, CancellationToken cancellationToken); } } diff --git a/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs b/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs index 701173ec6f89a..6e85dd64feadf 100644 --- a/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/UseThrowExpression/AbstractUseThrowExpressionDiagnosticAnalyzer.cs @@ -18,17 +18,17 @@ namespace Microsoft.CodeAnalysis.UseThrowExpression /// if (a == null) { /// throw SomeException(); /// } - /// + /// /// x = a; /// - /// + /// /// and offers to change it to - /// + /// /// /// x = a ?? throw SomeException(); /// - /// - /// Note: this analyzer can be updated to run on VB once VB supports 'throw' + /// + /// Note: this analyzer can be updated to run on VB once VB supports 'throw' /// expressions as well. /// internal abstract class AbstractUseThrowExpressionDiagnosticAnalyzer : @@ -62,7 +62,7 @@ protected override void InitializeWorker(AnalysisContext context) s_registerOperationActionInfo.Invoke(startContext, new object[] { new Action(operationContext => AnalyzeOperation(operationContext, expressionTypeOpt)), - ImmutableArray.Create(OperationKind.ThrowStatement) + ImmutableArray.Create(OperationKind.ThrowExpression) }); }); } @@ -77,31 +77,37 @@ private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol var cancellationToken = context.CancellationToken; - var throwOperation = (IThrowStatement)context.Operation; - var throwStatement = throwOperation.Syntax; + var throwExpressionOperation = (IThrowExpression)context.Operation; + var throwStatementOperation = throwExpressionOperation.Parent; + if (throwStatementOperation.Kind != OperationKind.ExpressionStatement) + { + return; + } + + var throwStatementSyntax = throwExpressionOperation.Syntax; var options = context.Options; var optionSet = options.GetDocumentOptionSetAsync(syntaxTree, cancellationToken).GetAwaiter().GetResult(); if (optionSet == null) { return; } - - var option = optionSet.GetOption(CodeStyleOptions.PreferThrowExpression, throwStatement.Language); + + var option = optionSet.GetOption(CodeStyleOptions.PreferThrowExpression, throwStatementSyntax.Language); if (!option.Value) { return; } var compilation = context.Compilation; - var semanticModel = compilation.GetSemanticModel(throwStatement.SyntaxTree); + var semanticModel = compilation.GetSemanticModel(throwStatementSyntax.SyntaxTree); var semanticFacts = GetSemanticFactsService(); - if (semanticFacts.IsInExpressionTree(semanticModel, throwStatement, expressionTypeOpt, cancellationToken)) + if (semanticFacts.IsInExpressionTree(semanticModel, throwStatementSyntax, expressionTypeOpt, cancellationToken)) { return; } var ifOperation = GetContainingIfOperation( - semanticModel, throwOperation, cancellationToken); + semanticModel, (IExpressionStatement)throwStatementOperation, cancellationToken); // This throw statement isn't parented by an if-statement. Nothing to // do here. @@ -159,18 +165,18 @@ private void AnalyzeOperation(OperationAnalysisContext context, INamedTypeSymbol var allLocations = ImmutableArray.Create( ifOperation.Syntax.GetLocation(), - throwOperation.ThrownObject.Syntax.GetLocation(), + throwExpressionOperation.Expression.Syntax.GetLocation(), assignmentExpression.Value.Syntax.GetLocation()); var descriptor = GetDescriptorWithSeverity(option.Notification.Value); context.ReportDiagnostic( - Diagnostic.Create(descriptor, throwStatement.GetLocation(), additionalLocations: allLocations)); + Diagnostic.Create(descriptor, throwStatementSyntax.GetLocation(), additionalLocations: allLocations)); // Fade out the rest of the if that surrounds the 'throw' exception. - var tokenBeforeThrow = throwStatement.GetFirstToken().GetPreviousToken(); - var tokenAfterThrow = throwStatement.GetLastToken().GetNextToken(); + var tokenBeforeThrow = throwStatementSyntax.GetFirstToken().GetPreviousToken(); + var tokenAfterThrow = throwStatementSyntax.GetLastToken().GetNextToken(); context.ReportDiagnostic( Diagnostic.Create(UnnecessaryWithSuggestionDescriptor, Location.Create(syntaxTree, TextSpan.FromBounds( @@ -293,7 +299,7 @@ private bool IsNull(IOperation operation) } private IIfStatement GetContainingIfOperation( - SemanticModel semanticModel, IThrowStatement throwOperation, + SemanticModel semanticModel, IExpressionStatement throwOperation, CancellationToken cancellationToken) { var throwStatement = throwOperation.Syntax; diff --git a/src/Features/VisualBasic/Portable/ReplaceDocCommentTextWithTag/VisualBasicReplaceDocCommentTextWithTagCodeRefactoringProvider.vb b/src/Features/VisualBasic/Portable/ReplaceDocCommentTextWithTag/VisualBasicReplaceDocCommentTextWithTagCodeRefactoringProvider.vb new file mode 100644 index 0000000000000..d4a8285b5524e --- /dev/null +++ b/src/Features/VisualBasic/Portable/ReplaceDocCommentTextWithTag/VisualBasicReplaceDocCommentTextWithTagCodeRefactoringProvider.vb @@ -0,0 +1,26 @@ +' 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 System.Composition +Imports Microsoft.CodeAnalysis.CodeRefactorings +Imports Microsoft.CodeAnalysis.ReplaceDocCommentTextWithTag + +Namespace Microsoft.CodeAnalysis.VisualBasic.ReplaceDocCommentTextWithTag + + Friend Class VisualBasicReplaceDocCommentTextWithTagCodeRefactoringProvider + Inherits AbstractReplaceDocCommentTextWithTagCodeRefactoringProvider + + Protected Overrides Function IsXmlTextToken(token As SyntaxToken) As Boolean + Return token.Kind() = SyntaxKind.XmlTextLiteralToken OrElse + token.Kind() = SyntaxKind.DocumentationCommentLineBreakToken + End Function + + Protected Overrides Function IsAnyKeyword(text As String) As Boolean + Return SyntaxFacts.GetKeywordKind(text) <> SyntaxKind.None OrElse + SyntaxFacts.GetContextualKeywordKind(text) <> SyntaxKind.None + End Function + + Protected Overrides Function ParseExpression(text As String) As SyntaxNode + Return SyntaxFactory.ParseExpression(text) + End Function + End Class +End Namespace diff --git a/src/Features/VisualBasic/Portable/TodoComments/BasicTodoCommentIncrementalAnalyzerProvider.vb b/src/Features/VisualBasic/Portable/TodoComments/BasicTodoCommentIncrementalAnalyzerProvider.vb index 012c20743e19e..cca5bb7ea250e 100644 --- a/src/Features/VisualBasic/Portable/TodoComments/BasicTodoCommentIncrementalAnalyzerProvider.vb +++ b/src/Features/VisualBasic/Portable/TodoComments/BasicTodoCommentIncrementalAnalyzerProvider.vb @@ -25,7 +25,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.TodoComments MyBase.New(workspace) End Sub - Protected Overrides Sub AppendTodoComments(commentDescriptors As ImmutableArray(Of TodoCommentDescriptor), document As SyntacticDocument, trivia As SyntaxTrivia, todoList As List(Of TodoComment)) + Protected Overrides Sub AppendTodoComments(commentDescriptors As IList(Of TodoCommentDescriptor), document As SyntacticDocument, trivia As SyntaxTrivia, todoList As List(Of TodoComment)) If PreprocessorHasComment(trivia) Then Dim commentTrivia = trivia.GetStructure().DescendantTrivia().First(Function(t) t.RawKind = SyntaxKind.CommentTrivia) diff --git a/src/Setup/Templates/Templates.csproj b/src/Setup/Templates/Templates.csproj index f88a473213435..2f992acc4e33b 100644 --- a/src/Setup/Templates/Templates.csproj +++ b/src/Setup/Templates/Templates.csproj @@ -17,9 +17,7 @@ false false false - $(BaseIntermediateOutputPath)\$(VersionType)\ - Roslyn Templates\$(VersionType) - $(VsixOutDirSuffix)\Roslyn SDK.vsix + Roslyn SDK.vsix true $(VisualStudioVersion) v4.6 diff --git a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs index 7c77a07459b4d..3b789b7340cfa 100644 --- a/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs +++ b/src/Test/Utilities/Portable/Compilation/OperationTreeVerifier.cs @@ -510,14 +510,6 @@ public override void VisitEmptyStatement(IEmptyStatement operation) LogCommonPropertiesAndNewLine(operation); } - public override void VisitThrowStatement(IThrowStatement operation) - { - LogString(nameof(IThrowStatement)); - LogCommonPropertiesAndNewLine(operation); - - Visit(operation.ThrownObject, "ThrownObject"); - } - public override void VisitReturnStatement(IReturnStatement operation) { LogString(nameof(IReturnStatement)); @@ -531,7 +523,7 @@ public override void VisitLockStatement(ILockStatement operation) LogString(nameof(ILockStatement)); LogCommonPropertiesAndNewLine(operation); - Visit(operation.LockedObject, "LockedObject"); + Visit(operation.Expression, "Expression"); Visit(operation.Body, "Body"); } @@ -865,13 +857,13 @@ public override void VisitConditionalChoiceExpression(IConditionalChoiceExpressi Visit(operation.IfFalseValue, "IfFalse"); } - public override void VisitNullCoalescingExpression(INullCoalescingExpression operation) + public override void VisitCoalesceExpression(ICoalesceExpression operation) { - LogString(nameof(INullCoalescingExpression)); + LogString(nameof(ICoalesceExpression)); LogCommonPropertiesAndNewLine(operation); - Visit(operation.PrimaryOperand, "Left"); - Visit(operation.SecondaryOperand, "Right"); + Visit(operation.Expression, "Expression"); + Visit(operation.WhenNull, "WhenNull"); } public override void VisitIsTypeExpression(IIsTypeExpression operation) @@ -906,15 +898,15 @@ public override void VisitTypeOfExpression(ITypeOfExpression operation) LogTypeOperationExpressionCommon(operation); } - public override void VisitLambdaExpression(ILambdaExpression operation) + public override void VisitAnonymousFunctionExpression(IAnonymousFunctionExpression operation) { - LogString(nameof(ILambdaExpression)); + LogString(nameof(IAnonymousFunctionExpression)); - LogSymbol(operation.Signature, header: " (Signature"); + LogSymbol(operation.Symbol, header: " (Symbol"); LogString(")"); LogCommonPropertiesAndNewLine(operation); - base.VisitLambdaExpression(operation); + base.VisitAnonymousFunctionExpression(operation); } public override void VisitLiteralExpression(ILiteralExpression operation) diff --git a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs index d1a7c49010aa7..9d5477bb4747b 100644 --- a/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs +++ b/src/Test/Utilities/Portable/Compilation/TestOperationWalker.cs @@ -154,11 +154,6 @@ public override void VisitEmptyStatement(IEmptyStatement operation) base.VisitEmptyStatement(operation); } - public override void VisitThrowStatement(IThrowStatement operation) - { - base.VisitThrowStatement(operation); - } - public override void VisitReturnStatement(IReturnStatement operation) { base.VisitReturnStatement(operation); @@ -372,9 +367,9 @@ public override void VisitConditionalChoiceExpression(IConditionalChoiceExpressi base.VisitConditionalChoiceExpression(operation); } - public override void VisitNullCoalescingExpression(INullCoalescingExpression operation) + public override void VisitCoalesceExpression(ICoalesceExpression operation) { - base.VisitNullCoalescingExpression(operation); + base.VisitCoalesceExpression(operation); } public override void VisitIsTypeExpression(IIsTypeExpression operation) @@ -398,11 +393,11 @@ public override void VisitTypeOfExpression(ITypeOfExpression operation) base.VisitTypeOfExpression(operation); } - public override void VisitLambdaExpression(ILambdaExpression operation) + public override void VisitAnonymousFunctionExpression(IAnonymousFunctionExpression operation) { - var signature = operation.Signature; + var signature = operation.Symbol; - base.VisitLambdaExpression(operation); + base.VisitAnonymousFunctionExpression(operation); } public override void VisitLocalFunctionStatement(ILocalFunctionStatement operation) diff --git a/src/Test/Utilities/Portable/Diagnostics/OperationTestAnalyzer.cs b/src/Test/Utilities/Portable/Diagnostics/OperationTestAnalyzer.cs index 2f989b7e684f3..20ee428500a12 100644 --- a/src/Test/Utilities/Portable/Diagnostics/OperationTestAnalyzer.cs +++ b/src/Test/Utilities/Portable/Diagnostics/OperationTestAnalyzer.cs @@ -1331,7 +1331,7 @@ public sealed override void Initialize(AnalysisContext context) context.RegisterOperationAction( (operationContext) => { - var lambdaExpression = (ILambdaExpression)operationContext.Operation; + var lambdaExpression = (IAnonymousFunctionExpression)operationContext.Operation; operationContext.ReportDiagnostic(Diagnostic.Create(LambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation())); var block = lambdaExpression.Body; // TODO: Can this possibly be null? Remove check if not. @@ -1357,7 +1357,7 @@ public sealed override void Initialize(AnalysisContext context) operationContext.ReportDiagnostic(Diagnostic.Create(NoneOperationInLambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation())); } }, - OperationKind.LambdaExpression); + OperationKind.AnonymousFunctionExpression); } } diff --git a/src/Tools/GenerateSdkPackages/files.txt b/src/Tools/GenerateSdkPackages/files.txt index 7ca106411acdd..a0eec1232ea3b 100644 --- a/src/Tools/GenerateSdkPackages/files.txt +++ b/src/Tools/GenerateSdkPackages/files.txt @@ -20,6 +20,7 @@ Microsoft.VisualStudio.Utilities.dll Microsoft.VisualStudio.Platform.VSEditor.dll Microsoft.VisualStudio.Platform.VSEditor.Interop.dll Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime.dll +Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime.dll Microsoft.Internal.Performance.CodeMarkers.DesignTime.dll PackageAndDeploy\Microsoft.VisualStudio.Shell.Framework.dll PackageAndDeploy\Microsoft.VisualStudio.Shell.15.0.dll diff --git a/src/Tools/GenerateSdkPackages/make-all.ps1 b/src/Tools/GenerateSdkPackages/make-all.ps1 index ac1b8966dd826..17b576fc0d863 100644 --- a/src/Tools/GenerateSdkPackages/make-all.ps1 +++ b/src/Tools/GenerateSdkPackages/make-all.ps1 @@ -28,14 +28,17 @@ function Package-Normal() { # The debugger DLLs have a more complex structure and it's easier to special case # copying them over. function Copy-Debugger() { - $debuggerRefDir = Join-Path $dllPath "debugger\ref" - $debuggerImplDir = Join-Path $dllPath "debugger\lib\net45" + $debuggerDir = Join-Path $dllPath "debugger" + $debuggerRefDir = Join-Path $debuggerDir "ref" + $debuggerImplDir = Join-Path $debuggerDir "lib\net45" Create-Directory $debuggerRefDir Create-Directory $debuggerImplDir Copy-Item -re -fo (Join-Path $dropPath "..\..\Debugger\ReferenceDLL\*") $debuggerRefDir Copy-Item -re -fo (Join-Path $dropPath "..\..\Debugger\IDE\Microsoft.VisualStudio.Debugger.Engine.dll") $debuggerImplDir Copy-Item -re -fo (Join-Path $dropPath "Microsoft.VisualStudio.Debugger.Metadata.dll") $debuggerImplDir + + Get-ChildItem $debuggerDir -Recurse -File | ForEach-Object { & $fakeSign -f $_.FullName } } # Used to package debugger nugets diff --git a/src/VisualStudio/Core/Def/Implementation/DesignerAttribute/DesignerAttributeIncrementalAnalyzer.cs b/src/VisualStudio/Core/Def/Implementation/DesignerAttribute/DesignerAttributeIncrementalAnalyzer.cs index c974689d215a2..6ceaa77b5d7b7 100644 --- a/src/VisualStudio/Core/Def/Implementation/DesignerAttribute/DesignerAttributeIncrementalAnalyzer.cs +++ b/src/VisualStudio/Core/Def/Implementation/DesignerAttribute/DesignerAttributeIncrementalAnalyzer.cs @@ -130,7 +130,7 @@ public async Task AnalyzeProjectAsync(Project project, bool semanticsChanged, In return null; } - var serializedResults = await session.InvokeAsync>( + var serializedResults = await session.InvokeAsync>( nameof(IRemoteDesignerAttributeService.ScanDesignerAttributesAsync), new object[] { project.Id }, cancellationToken).ConfigureAwait(false); var data = serializedResults.ToImmutableDictionary(kvp => kvp.FilePath); diff --git a/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPane.xaml.cs b/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPane.xaml.cs index 29bb0940e67b3..cd1c6b2711778 100644 --- a/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPane.xaml.cs +++ b/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPane.xaml.cs @@ -7,11 +7,12 @@ using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Navigation; -using EnvDTE; using Microsoft.CodeAnalysis.Diagnostics.Log; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; using Roslyn.Utilities; using Microsoft.CodeAnalysis.Editor.Implementation.Preview; +using IVsUIShell = Microsoft.VisualStudio.Shell.Interop.IVsUIShell; +using OLECMDEXECOPT = Microsoft.VisualStudio.OLE.Interop.OLECMDEXECOPT; namespace Microsoft.VisualStudio.LanguageServices.Implementation.PreviewPane { @@ -24,7 +25,7 @@ internal partial class PreviewPane : UserControl, IDisposable private readonly string _id; private readonly bool _logIdVerbatimInTelemetry; - private readonly DTE _dte; + private readonly IVsUIShell _uiShell; private bool _isExpanded; private double _heightForThreeLineTitle; @@ -39,14 +40,14 @@ internal partial class PreviewPane : UserControl, IDisposable string helpLinkToolTipText, IReadOnlyList previewContent, bool logIdVerbatimInTelemetry, - DTE dte, + IVsUIShell uiShell, Guid optionPageGuid = default) { InitializeComponent(); _id = id; _logIdVerbatimInTelemetry = logIdVerbatimInTelemetry; - _dte = dte; + _uiShell = uiShell; // Initialize header portion. if ((severityIcon != null) && !string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(title)) @@ -358,7 +359,11 @@ private void OptionsButton_Click(object sender, RoutedEventArgs e) { if (_optionPageGuid != default) { - _dte.ExecuteCommand("Tools.Options", _optionPageGuid.ToString()); + ErrorHandler.ThrowOnFailure(_uiShell.PostExecCommand( + VSConstants.GUID_VSStandardCommandSet97, + (uint)VSConstants.VSStd97CmdID.ToolsOptions, + (uint)OLECMDEXECOPT.OLECMDEXECOPT_DODEFAULT, + _optionPageGuid.ToString())); } } } diff --git a/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPaneService.cs b/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPaneService.cs index 1470c7b9d0d66..4e9a1f0fcaae2 100644 --- a/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPaneService.cs +++ b/src/VisualStudio/Core/Def/Implementation/PreviewPane/PreviewPaneService.cs @@ -18,18 +18,20 @@ using Microsoft.VisualStudio.Imaging.Interop; using Microsoft.VisualStudio.LanguageServices.Implementation.Utilities; using Microsoft.VisualStudio.Shell; +using IVsUIShell = Microsoft.VisualStudio.Shell.Interop.IVsUIShell; +using SVsUIShell = Microsoft.VisualStudio.Shell.Interop.SVsUIShell; namespace Microsoft.VisualStudio.LanguageServices.Implementation.PreviewPane { [ExportWorkspaceServiceFactory(typeof(IPreviewPaneService), ServiceLayer.Host), Shared] internal class PreviewPaneService : ForegroundThreadAffinitizedObject, IPreviewPaneService, IWorkspaceServiceFactory { - private readonly EnvDTE.DTE _dte; + private readonly IVsUIShell _uiShell; [ImportingConstructor] public PreviewPaneService(SVsServiceProvider serviceProvider) { - _dte = serviceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; + _uiShell = serviceProvider.GetService(typeof(SVsUIShell)) as IVsUIShell; } IWorkspaceService IWorkspaceServiceFactory.CreateService(HostWorkspaceServices workspaceServices) @@ -107,7 +109,7 @@ private static Uri GetHelpLink(DiagnosticData diagnostic, string language, strin return new PreviewPane( severityIcon: null, id: null, title: null, description: null, helpLink: null, helpLinkToolTipText: null, - previewContent: previewContent, logIdVerbatimInTelemetry: false, dte: _dte); + previewContent: previewContent, logIdVerbatimInTelemetry: false, uiShell: _uiShell); } var helpLinkToolTipText = string.Empty; @@ -128,7 +130,7 @@ private static Uri GetHelpLink(DiagnosticData diagnostic, string language, strin helpLinkToolTipText: helpLinkToolTipText, previewContent: previewContent, logIdVerbatimInTelemetry: diagnostic.CustomTags.Contains(WellKnownDiagnosticTags.Telemetry), - dte: _dte, + uiShell: _uiShell, optionPageGuid: optionPageGuid); } diff --git a/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs b/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs index 550f75ae71cd5..677ac878c2541 100644 --- a/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs +++ b/src/VisualStudio/Core/Def/Implementation/Watson/WatsonReporter.cs @@ -9,6 +9,19 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation { internal class WatsonReporter { + /// + /// The default callback to pass to . + /// Returning "0" signals that we should send data to Watson; any other value will cancel the Watson report. + /// + private static Func s_defaultCallback = _ => 0; + + /// + /// Controls whether or not we actually report the failure. + /// There are situations where we know we're in a bad state and any further reports are unlikely to be + /// helpful, so we shouldn't send them. + /// + private static bool s_reportWatson = true; + /// /// Report Non-Fatal Watson /// @@ -25,18 +38,7 @@ public static void Report(Exception exception) /// Exception that triggered this non-fatal error public static void Report(string description, Exception exception) { - TelemetryService.DefaultSession.PostFault( - eventName: FunctionId.NonFatalWatson.GetEventName(), - description: description, - exceptionObject: exception, - gatherEventDetails: arg => - { - arg.AddProcessDump(System.Diagnostics.Process.GetCurrentProcess().Id); - - // 0 means send watson, otherwise, cancel watson - // we always send watson since dump itself can have valuable data - return 0; - }); + Report(description, exception, s_defaultCallback); } /// @@ -44,9 +46,16 @@ public static void Report(string description, Exception exception) /// /// any description you want to save with this watson report /// Exception that triggered this non-fatal error - /// callback to include extra data with the NFW + /// Callback to include extra data with the NFW. Note that we always collect + /// a dump of the current process, but this can be used to add further information or files to the + /// CAB. public static void Report(string description, Exception exception, Func callback) { + if (!s_reportWatson) + { + return; + } + TelemetryService.DefaultSession.PostFault( eventName: FunctionId.NonFatalWatson.GetEventName(), description: description, @@ -57,6 +66,14 @@ public static void Report(string description, Exception exception, Func + diff --git a/src/VisualStudio/Core/Def/SymbolSearch/VisualStudioSymbolSearchService.cs b/src/VisualStudio/Core/Def/SymbolSearch/VisualStudioSymbolSearchService.cs index 49ca30337690d..ccd06a3f2eee0 100644 --- a/src/VisualStudio/Core/Def/SymbolSearch/VisualStudioSymbolSearchService.cs +++ b/src/VisualStudio/Core/Def/SymbolSearch/VisualStudioSymbolSearchService.cs @@ -108,7 +108,7 @@ private async Task UpdateSourceInBackgroundAsync(string sourceName) await engine.UpdateContinuouslyAsync(sourceName, _localSettingsDirectory).ConfigureAwait(false); } - public async Task> FindPackagesWithTypeAsync( + public async Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken) { var engine = await GetEngine(cancellationToken).ConfigureAwait(false); @@ -118,7 +118,7 @@ private async Task UpdateSourceInBackgroundAsync(string sourceName) return FilterAndOrderPackages(allPackagesWithType); } - public async Task> FindPackagesWithAssemblyAsync( + public async Task> FindPackagesWithAssemblyAsync( string source, string assemblyName, CancellationToken cancellationToken) { var engine = await GetEngine(cancellationToken).ConfigureAwait(false); @@ -170,7 +170,7 @@ private async Task UpdateSourceInBackgroundAsync(string sourceName) return result.ToImmutableAndFree(); } - public async Task> FindReferenceAssembliesWithTypeAsync( + public async Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken) { var engine = await GetEngine(cancellationToken).ConfigureAwait(false); diff --git a/src/VisualStudio/Core/Next/ServicesVisualStudio.Next.csproj b/src/VisualStudio/Core/Next/ServicesVisualStudio.Next.csproj index f87500ca0fd9c..f55a4170b5d50 100644 --- a/src/VisualStudio/Core/Next/ServicesVisualStudio.Next.csproj +++ b/src/VisualStudio/Core/Next/ServicesVisualStudio.Next.csproj @@ -59,6 +59,8 @@ + + diff --git a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs index c56c793ddbf32..05e5d2b8431d8 100644 --- a/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs +++ b/src/Workspaces/CSharp/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.cs @@ -123,17 +123,11 @@ private static bool IsNamespaceName(NameSyntax name) CancellationToken cancellationToken, out ClassifiedSpan classifiedSpan) { - if (symbol != null) + // Classify a reference to an attribute constructor in an attribute location + // as if we were classifying the attribute type itself. + if (symbol.IsConstructor() && name.IsParentKind(SyntaxKind.Attribute)) { - // see through using aliases - if (symbol.Kind == SymbolKind.Alias) - { - symbol = (symbol as IAliasSymbol).Target; - } - else if (symbol.IsConstructor() && name.IsParentKind(SyntaxKind.Attribute)) - { - symbol = symbol.ContainingType; - } + symbol = symbol.ContainingType; } if (name.IsVar && @@ -153,18 +147,15 @@ private static bool IsNamespaceName(NameSyntax name) } } - if (symbol != null) + // Use .Equals since we can't rely on object identity for constructed types. + if (symbol is ITypeSymbol typeSymbol) { - // Use .Equals since we can't rely on object identity for constructed types. - if (symbol is ITypeSymbol typeSymbol) + var classification = GetClassificationForType(typeSymbol); + if (classification != null) { - var classification = GetClassificationForType(typeSymbol); - if (classification != null) - { - var token = name.GetNameToken(); - classifiedSpan = new ClassifiedSpan(token.Span, classification); - return true; - } + var token = name.GetNameToken(); + classifiedSpan = new ClassifiedSpan(token.Span, classification); + return true; } } diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs index f04663fd044a1..ca4153cff96e6 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs @@ -33,6 +33,9 @@ private CSharpSyntaxFactsService() public StringComparer StringComparer { get; } = StringComparer.Ordinal; + public SyntaxTrivia ElasticMarker + => SyntaxFactory.ElasticMarker; + public SyntaxTrivia ElasticCarriageReturnLineFeed => SyntaxFactory.ElasticCarriageReturnLineFeed; diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs index 5804518b3d3d2..2619fdcc5cef6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_AllDeclarations.cs @@ -1,6 +1,7 @@ // 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 System.Diagnostics; using System.Threading; @@ -99,12 +100,12 @@ internal static partial class DeclarationFinder return (false, ImmutableArray.Empty); } - var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( + var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.SymbolFinderEnabled, nameof(IRemoteSymbolFinder.FindAllDeclarationsWithNormalQueryAsync), new object[] { project.Id, query.Name, query.Kind, criteria }, cancellationToken).ConfigureAwait(false); - if (result.IsDefault) + if (result == null) { return (false, ImmutableArray.Empty); } @@ -116,9 +117,9 @@ internal static partial class DeclarationFinder } private static async Task> RehydrateAsync( - Solution solution, ImmutableArray array, CancellationToken cancellationToken) + Solution solution, IList array, CancellationToken cancellationToken) { - var result = ArrayBuilder.GetInstance(array.Length); + var result = ArrayBuilder.GetInstance(array.Count); foreach (var dehydrated in array) { diff --git a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs index 60b80e14e5369..1f915167d00eb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/Declarations/DeclarationFinder_SourceDeclarations.cs @@ -1,6 +1,7 @@ // 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 System.Threading; using System.Threading.Tasks; @@ -115,12 +116,12 @@ internal static partial class DeclarationFinder private static async Task<(bool, ImmutableArray)> TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync( Solution solution, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { - var result = await solution.TryRunCodeAnalysisRemoteAsync>( + var result = await solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.SymbolFinderEnabled, nameof(IRemoteSymbolFinder.FindSolutionSourceDeclarationsWithNormalQueryAsync), new object[] { name, ignoreCase, criteria }, cancellationToken).ConfigureAwait(false); - if (result.IsDefault) + if (result == null) { return (false, ImmutableArray.Empty); } @@ -139,12 +140,12 @@ internal static partial class DeclarationFinder return (false, ImmutableArray.Empty); } - var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( + var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.SymbolFinderEnabled, nameof(IRemoteSymbolFinder.FindProjectSourceDeclarationsWithNormalQueryAsync), new object[] { project.Id, name, ignoreCase, criteria }, cancellationToken).ConfigureAwait(false); - if (result.IsDefault) + if (result == null) { return (false, ImmutableArray.Empty); } @@ -163,12 +164,12 @@ internal static partial class DeclarationFinder return (false, ImmutableArray.Empty); } - var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( + var result = await project.Solution.TryRunCodeAnalysisRemoteAsync>( RemoteFeatureOptions.SymbolFinderEnabled, nameof(IRemoteSymbolFinder.FindProjectSourceDeclarationsWithPatternAsync), new object[] { project.Id, pattern, criteria }, cancellationToken).ConfigureAwait(false); - if (result.IsDefault) + if (result == null) { return (false, ImmutableArray.Empty); } diff --git a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs index ed8a2c8e000ea..464535c989abd 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/IRemoteSymbolFinder.cs @@ -1,6 +1,7 @@ // 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 System.Threading; using System.Threading.Tasks; @@ -13,16 +14,16 @@ internal interface IRemoteSymbolFinder Task FindReferencesAsync(SerializableSymbolAndProjectId symbolAndProjectIdArg, DocumentId[] documentArgs, CancellationToken cancellationToken); Task FindLiteralReferencesAsync(object value, TypeCode typeCode, CancellationToken cancellationToken); - Task> FindAllDeclarationsWithNormalQueryAsync( + Task> FindAllDeclarationsWithNormalQueryAsync( ProjectId projectId, string name, SearchKind searchKind, SymbolFilter criteria, CancellationToken cancellationToken); - Task> FindSolutionSourceDeclarationsWithNormalQueryAsync( + Task> FindSolutionSourceDeclarationsWithNormalQueryAsync( string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken); - Task> FindProjectSourceDeclarationsWithNormalQueryAsync( + Task> FindProjectSourceDeclarationsWithNormalQueryAsync( ProjectId projectId, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken); - Task> FindProjectSourceDeclarationsWithPatternAsync( + Task> FindProjectSourceDeclarationsWithPatternAsync( ProjectId projectId, string pattern, SymbolFilter criteria, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs index 9732f4d8b0b12..310c6c1307a34 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs @@ -14,6 +14,7 @@ internal interface ISyntaxFactsService : ILanguageService bool IsCaseSensitive { get; } StringComparer StringComparer { get; } + SyntaxTrivia ElasticMarker { get; } SyntaxTrivia ElasticCarriageReturnLineFeed { get; } bool SupportsIndexingInitializer(ParseOptions options); diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs index d4ceffdd7b8ae..e2e486fc54df7 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/ISymbolExtensions.cs @@ -418,7 +418,7 @@ public static ImmutableArray GetParameters(this ISymbol symbol { case IMethodSymbol m: return m.Parameters; case IPropertySymbol nt: return nt.Parameters; - default: return ImmutableArray.Create(); + default: return ImmutableArray.Empty; } } @@ -428,7 +428,7 @@ public static ImmutableArray GetTypeParameters(this ISymbo { case IMethodSymbol m: return m.TypeParameters; case INamedTypeSymbol nt: return nt.TypeParameters; - default: return ImmutableArray.Create(); + default: return ImmutableArray.Empty; } } diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs index aaaff9300de34..a4b3873efbc51 100644 --- a/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs +++ b/src/Workspaces/Core/Portable/Shared/Extensions/SemanticModelExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Utilities; +using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Shared.Extensions @@ -14,23 +15,26 @@ namespace Microsoft.CodeAnalysis.Shared.Extensions internal struct TokenSemanticInfo { public static readonly TokenSemanticInfo Empty = new TokenSemanticInfo( - null, null, ImmutableArray.Empty, null); + null, null, ImmutableArray.Empty, null, default(TextSpan)); public readonly ISymbol DeclaredSymbol; public readonly IAliasSymbol AliasSymbol; public readonly ImmutableArray ReferencedSymbols; public readonly ITypeSymbol Type; + public readonly TextSpan Span; public TokenSemanticInfo( ISymbol declaredSymbol, IAliasSymbol aliasSymbol, ImmutableArray referencedSymbols, - ITypeSymbol type) + ITypeSymbol type, + TextSpan span) { DeclaredSymbol = declaredSymbol; AliasSymbol = aliasSymbol; ReferencedSymbols = referencedSymbols; Type = type; + Span = span; } public ImmutableArray GetSymbols(bool includeType) @@ -207,7 +211,7 @@ private static ISymbol MapSymbol(ISymbol symbol, ITypeSymbol type) } } - return new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type); + return new TokenSemanticInfo(declaredSymbol, aliasSymbol, allSymbols, type, token.Span); } public static SemanticModel GetOriginalSemanticModel(this SemanticModel semanticModel) diff --git a/src/Workspaces/Core/Portable/SymbolSearch/IRemoteSymbolSearchUpdateEngine.cs b/src/Workspaces/Core/Portable/SymbolSearch/IRemoteSymbolSearchUpdateEngine.cs index a5bd4254b4b18..6f7a0a047d91f 100644 --- a/src/Workspaces/Core/Portable/SymbolSearch/IRemoteSymbolSearchUpdateEngine.cs +++ b/src/Workspaces/Core/Portable/SymbolSearch/IRemoteSymbolSearchUpdateEngine.cs @@ -1,5 +1,6 @@ // 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.Threading; using System.Threading.Tasks; @@ -10,8 +11,8 @@ internal interface IRemoteSymbolSearchUpdateEngine { Task UpdateContinuouslyAsync(string sourceName, string localSettingsDirectory); - Task> FindPackagesWithTypeAsync(string source, string name, int arity, CancellationToken cancellationToken); - Task> FindPackagesWithAssemblyAsync(string source, string name, CancellationToken cancellationToken); - Task> FindReferenceAssembliesWithTypeAsync(string name, int arity, CancellationToken cancellationToken); + Task> FindPackagesWithTypeAsync(string source, string name, int arity, CancellationToken cancellationToken); + Task> FindPackagesWithAssemblyAsync(string source, string name, CancellationToken cancellationToken); + Task> FindReferenceAssembliesWithTypeAsync(string name, int arity, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/SymbolSearch/ISymbolSearchService.cs b/src/Workspaces/Core/Portable/SymbolSearch/ISymbolSearchService.cs index 1be1614d5b67f..c38f1e982ee21 100644 --- a/src/Workspaces/Core/Portable/SymbolSearch/ISymbolSearchService.cs +++ b/src/Workspaces/Core/Portable/SymbolSearch/ISymbolSearchService.cs @@ -23,7 +23,7 @@ internal interface ISymbolSearchService : IWorkspaceService /// Implementations should return results in order from best to worst (from their /// perspective). /// - Task> FindPackagesWithTypeAsync( + Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken); /// @@ -34,7 +34,7 @@ internal interface ISymbolSearchService : IWorkspaceService /// Implementations should return results in order from best to worst (from their /// perspective). /// - Task> FindPackagesWithAssemblyAsync( + Task> FindPackagesWithAssemblyAsync( string source, string assemblyName, CancellationToken cancellationToken); /// @@ -46,7 +46,7 @@ internal interface ISymbolSearchService : IWorkspaceService /// Implementations should return results in order from best to worst (from their /// perspective). /// - Task> FindReferenceAssembliesWithTypeAsync( + Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken); } @@ -64,7 +64,7 @@ protected PackageResult(string packageName, int rank) internal class PackageWithTypeResult : PackageResult { - public readonly ImmutableArray ContainingNamespaceNames; + public readonly IList ContainingNamespaceNames; public readonly string TypeName; public readonly string Version; @@ -73,7 +73,7 @@ internal class PackageWithTypeResult : PackageResult string typeName, string version, int rank, - ImmutableArray containingNamespaceNames) + IList containingNamespaceNames) : base(packageName, rank) { TypeName = typeName; @@ -118,14 +118,14 @@ public int CompareTo(PackageWithAssemblyResult other) internal class ReferenceAssemblyWithTypeResult { - public readonly ImmutableArray ContainingNamespaceNames; + public readonly IList ContainingNamespaceNames; public readonly string AssemblyName; public readonly string TypeName; public ReferenceAssemblyWithTypeResult( string assemblyName, string typeName, - ImmutableArray containingNamespaceNames) + IList containingNamespaceNames) { AssemblyName = assemblyName; TypeName = typeName; @@ -136,22 +136,22 @@ internal class ReferenceAssemblyWithTypeResult [ExportWorkspaceService(typeof(ISymbolSearchService)), Shared] internal class DefaultSymbolSearchService : ISymbolSearchService { - public Task> FindPackagesWithTypeAsync( + public Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyList(); } - public Task> FindPackagesWithAssemblyAsync( + public Task> FindPackagesWithAssemblyAsync( string source, string assemblyName, CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyList(); } - public Task> FindReferenceAssembliesWithTypeAsync( + public Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyList(); } } } diff --git a/src/Workspaces/Core/Portable/Utilities/IReadOnlyListExtensions.cs b/src/Workspaces/Core/Portable/Utilities/IReadOnlyListExtensions.cs index 1a4698cc9b540..b15e7de4427d1 100644 --- a/src/Workspaces/Core/Portable/Utilities/IReadOnlyListExtensions.cs +++ b/src/Workspaces/Core/Portable/Utilities/IReadOnlyListExtensions.cs @@ -1,12 +1,38 @@ -using System.Collections.Generic; +using System.Collections; +using System.Collections.Generic; namespace Microsoft.CodeAnalysis.Utilities { internal static class IReadOnlyListExtensions { + public static IReadOnlyList ToReadOnlyList(this IList list) + { + if (list is IReadOnlyList readOnlyList) + { + return readOnlyList; + } + + return new ReadOnlyList(list); + } + public static T Last(this IReadOnlyList list) { return list[list.Count - 1]; } + + private class ReadOnlyList : IReadOnlyList + { + private readonly IList _list; + + public ReadOnlyList(IList list) + { + _list = list; + } + + public T this[int index] => _list[index]; + public int Count => _list.Count; + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator(); + } } } diff --git a/src/Workspaces/Core/Portable/Utilities/SpecializedTasks.cs b/src/Workspaces/Core/Portable/Utilities/SpecializedTasks.cs index 88d1a406467d5..619a83bc7b18f 100644 --- a/src/Workspaces/Core/Portable/Utilities/SpecializedTasks.cs +++ b/src/Workspaces/Core/Portable/Utilities/SpecializedTasks.cs @@ -28,6 +28,16 @@ public static Task DefaultOrResult(T value) return Task.FromResult(value); } + public static Task> EmptyReadOnlyList() + { + return Empty.EmptyReadOnlyList; + } + + public static Task> EmptyList() + { + return Empty.EmptyList; + } + public static Task> EmptyImmutableArray() { return Empty.EmptyImmutableArray; @@ -48,6 +58,8 @@ private static class Empty public static readonly Task Default = Task.FromResult(default); public static readonly Task> EmptyEnumerable = Task.FromResult>(SpecializedCollections.EmptyEnumerable()); public static readonly Task> EmptyImmutableArray = Task.FromResult(ImmutableArray.Empty); + public static readonly Task> EmptyList = Task.FromResult(SpecializedCollections.EmptyList()); + public static readonly Task> EmptyReadOnlyList = Task.FromResult(SpecializedCollections.EmptyReadOnlyList()); } private static class FromResultCache where T : class diff --git a/src/Workspaces/Core/Portable/Utilities/TaskExtensions.cs b/src/Workspaces/Core/Portable/Utilities/TaskExtensions.cs index 2f1c4287eb833..5d027fd410976 100644 --- a/src/Workspaces/Core/Portable/Utilities/TaskExtensions.cs +++ b/src/Workspaces/Core/Portable/Utilities/TaskExtensions.cs @@ -90,6 +90,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationAction, nameof(continuationAction)); + Func continuationFunction = antecedent => { continuationAction(antecedent); @@ -116,6 +118,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWith( (Task antecedent) => continuationFunction((Task)antecedent), cancellationToken, continuationOptions, scheduler); } @@ -127,6 +131,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationAction, nameof(continuationAction)); + return task.SafeContinueWith( (Task antecedent) => continuationAction((Task)antecedent), cancellationToken, continuationOptions, scheduler); } @@ -156,6 +162,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance // We do not want this, so we pass the LazyCancellation flag to the TPL which implements // the behavior we want. + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + Func outerFunction = t => { try @@ -223,6 +231,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions taskContinuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWith(t => Task.Delay(millisecondsDelay, cancellationToken).SafeContinueWith( _ => continuationFunction(t), cancellationToken, TaskContinuationOptions.None, scheduler), @@ -237,6 +247,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions taskContinuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWith(t => Task.Delay(millisecondsDelay, cancellationToken).SafeContinueWith( _ => continuationFunction(t), cancellationToken, TaskContinuationOptions.None, scheduler), @@ -251,6 +263,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions taskContinuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationAction, nameof(continuationAction)); + return task.SafeContinueWith(t => Task.Delay(millisecondsDelay, cancellationToken).SafeContinueWith( _ => continuationAction(), cancellationToken, TaskContinuationOptions.None, scheduler), @@ -264,6 +278,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWithFromAsync( (Task antecedent) => continuationFunction((Task)antecedent), cancellationToken, continuationOptions, scheduler); } @@ -350,6 +366,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions taskContinuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWith(t => Task.Delay(millisecondsDelay, cancellationToken).SafeContinueWithFromAsync( _ => continuationFunction(t), cancellationToken, TaskContinuationOptions.None, scheduler), @@ -364,6 +382,8 @@ public static T WaitAndGetResult_CanCallOnBackground(this Task task, Cance TaskContinuationOptions taskContinuationOptions, TaskScheduler scheduler) { + Contract.ThrowIfNull(continuationFunction, nameof(continuationFunction)); + return task.SafeContinueWith(t => Task.Delay(millisecondsDelay, cancellationToken).SafeContinueWithFromAsync( _ => continuationFunction(t), cancellationToken, TaskContinuationOptions.None, scheduler), diff --git a/src/Workspaces/Core/Portable/Versions/PersistedVersionStampLogger.cs b/src/Workspaces/Core/Portable/Versions/PersistedVersionStampLogger.cs index c0c233d67899c..c81219b957555 100644 --- a/src/Workspaces/Core/Portable/Versions/PersistedVersionStampLogger.cs +++ b/src/Workspaces/Core/Portable/Versions/PersistedVersionStampLogger.cs @@ -11,12 +11,6 @@ internal static class PersistedVersionStampLogger private const string SyntaxTree = nameof(SyntaxTree); private const string Project = nameof(Project); private const string DependentProject = nameof(DependentProject); - private const string Semantic = nameof(Semantic); - private const string DependentSemantic = nameof(DependentSemantic); - - private const string ProjectCount = nameof(ProjectCount); - private const string InitialSemanticVersionCount = nameof(InitialSemanticVersionCount); - private const string InitialDependentSemanticVersionCount = nameof(InitialDependentSemanticVersionCount); private static readonly LogAggregator s_logAggregator = new LogAggregator(); @@ -60,55 +54,14 @@ public static void LogPersistedDependentProjectVersionUsage(bool succeeded) s_logAggregator.IncreaseCount(DependentProject); } - public static void LogPersistedSemanticVersionUsage(bool succeeded) - { - if (!succeeded) - { - return; - } - - s_logAggregator.IncreaseCount(Semantic); - } - - public static void LogPersistedDependentSemanticVersionUsage(bool succeeded) - { - if (!succeeded) - { - return; - } - - s_logAggregator.IncreaseCount(DependentSemantic); - } - - public static void LogProject() - { - s_logAggregator.IncreaseCount(ProjectCount); - } - - public static void LogInitialSemanticVersion() - { - s_logAggregator.IncreaseCount(InitialSemanticVersionCount); - } - - public static void LogInitialDependentSemanticVersion() - { - s_logAggregator.IncreaseCount(InitialDependentSemanticVersionCount); - } - public static void LogSummary() { Logger.Log(FunctionId.PersistedSemanticVersion_Info, KeyValueLogMessage.Create(m => { - m[ProjectCount] = s_logAggregator.GetCount(ProjectCount); - m[InitialSemanticVersionCount] = s_logAggregator.GetCount(InitialSemanticVersionCount); - m[InitialDependentSemanticVersionCount] = s_logAggregator.GetCount(InitialDependentSemanticVersionCount); - m[Text] = s_logAggregator.GetCount(Text); m[SyntaxTree] = s_logAggregator.GetCount(SyntaxTree); m[Project] = s_logAggregator.GetCount(Project); m[DependentProject] = s_logAggregator.GetCount(DependentProject); - m[Semantic] = s_logAggregator.GetCount(Semantic); - m[DependentSemantic] = s_logAggregator.GetCount(DependentSemantic); })); } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_AddImport.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_AddImport.cs index c6b34cfa47927..3c5bad5880633 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_AddImport.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_AddImport.cs @@ -1,5 +1,6 @@ // 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.Threading; using System.Threading.Tasks; @@ -13,9 +14,9 @@ namespace Microsoft.CodeAnalysis.Remote { internal partial class CodeAnalysisService : IRemoteAddImportFeatureService { - public async Task> GetFixesAsync( + public async Task> GetFixesAsync( DocumentId documentId, TextSpan span, string diagnosticId, bool placeSystemNamespaceFirst, - bool searchReferenceAssemblies, ImmutableArray packageSources, CancellationToken cancellationToken) + bool searchReferenceAssemblies, IList packageSources, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) { @@ -29,7 +30,7 @@ internal partial class CodeAnalysisService : IRemoteAddImportFeatureService var result = await service.GetFixesAsync( document, span, diagnosticId, placeSystemNamespaceFirst, symbolSearchService, searchReferenceAssemblies, - packageSources, cancellationToken).ConfigureAwait(false); + packageSources.ToImmutableArray(), cancellationToken).ConfigureAwait(false); return result; } @@ -54,28 +55,28 @@ public SymbolSearchService(CodeAnalysisService codeAnalysisService) this.codeAnalysisService = codeAnalysisService; } - public async Task> FindPackagesWithTypeAsync( + public async Task> FindPackagesWithTypeAsync( string source, string name, int arity, CancellationToken cancellationToken) { - var result = await codeAnalysisService.Rpc.InvokeAsync>( + var result = await codeAnalysisService.Rpc.InvokeAsync>( nameof(FindPackagesWithTypeAsync), source, name, arity).ConfigureAwait(false); return result; } - public async Task> FindPackagesWithAssemblyAsync( + public async Task> FindPackagesWithAssemblyAsync( string source, string assemblyName, CancellationToken cancellationToken) { - var result = await codeAnalysisService.Rpc.InvokeAsync>( + var result = await codeAnalysisService.Rpc.InvokeAsync>( nameof(FindPackagesWithAssemblyAsync), source, assemblyName).ConfigureAwait(false); return result; } - public async Task> FindReferenceAssembliesWithTypeAsync( + public async Task> FindReferenceAssembliesWithTypeAsync( string name, int arity, CancellationToken cancellationToken) { - var result = await codeAnalysisService.Rpc.InvokeAsync>( + var result = await codeAnalysisService.Rpc.InvokeAsync>( nameof(FindReferenceAssembliesWithTypeAsync), name, arity).ConfigureAwait(false); return result; diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DesignerAttributes.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DesignerAttributes.cs index bd4af79307a30..3aefc8e2ea1c3 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DesignerAttributes.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DesignerAttributes.cs @@ -1,10 +1,12 @@ // 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.Immutable; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.DesignerAttributes; using Microsoft.CodeAnalysis.Internal.Log; +using Roslyn.Utilities; using RoslynLogger = Microsoft.CodeAnalysis.Internal.Log.Logger; namespace Microsoft.CodeAnalysis.Remote @@ -17,16 +19,22 @@ internal partial class CodeAnalysisService : IRemoteDesignerAttributeService /// /// This will be called by ServiceHub/JsonRpc framework /// - public async Task> ScanDesignerAttributesAsync(ProjectId projectId, CancellationToken cancellationToken) + public async Task> ScanDesignerAttributesAsync(ProjectId projectId, CancellationToken cancellationToken) { using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_GetDesignerAttributesAsync, projectId.DebugName, cancellationToken)) { var solution = await GetSolutionAsync(cancellationToken).ConfigureAwait(false); var project = solution.GetProject(projectId); + var data = await AbstractDesignerAttributeService.TryAnalyzeProjectInCurrentProcessAsync( project, cancellationToken).ConfigureAwait(false); - return data.Values.ToImmutableArray(); + if (data.Count == 0) + { + return SpecializedCollections.EmptyList(); + } + + return data.Values.ToList(); } } } diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DocumentHighlights.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DocumentHighlights.cs index e62228197bbcd..db3147ec915fd 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DocumentHighlights.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_DocumentHighlights.cs @@ -1,5 +1,6 @@ // 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.Threading; @@ -13,7 +14,7 @@ namespace Microsoft.CodeAnalysis.Remote // root level service for all Roslyn services internal partial class CodeAnalysisService : IRemoteDocumentHighlights { - public async Task> GetDocumentHighlightsAsync( + public async Task> GetDocumentHighlightsAsync( DocumentId documentId, int position, DocumentId[] documentIdsToSearch, CancellationToken cancellationToken) { // NOTE: In projection scenarios, we might get a set of documents to search diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs index 96bd6613c5081..7ceff52363cec 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_NavigateTo.cs @@ -1,5 +1,6 @@ // 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.Threading; using System.Threading.Tasks; @@ -9,7 +10,7 @@ namespace Microsoft.CodeAnalysis.Remote { internal partial class CodeAnalysisService : IRemoteNavigateToSearchService { - public async Task> SearchDocumentAsync( + public async Task> SearchDocumentAsync( DocumentId documentId, string searchPattern, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) @@ -24,7 +25,7 @@ internal partial class CodeAnalysisService : IRemoteNavigateToSearchService } } - public async Task> SearchProjectAsync( + public async Task> SearchProjectAsync( ProjectId projectId, string searchPattern, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs index a2248cff9c61e..740060c72ea09 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_SymbolFinder.cs @@ -1,6 +1,7 @@ // 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 System.Linq; using System.Threading; @@ -59,7 +60,7 @@ public async Task FindLiteralReferencesAsync(object value, TypeCode typeCode, Ca } } - public async Task> FindAllDeclarationsWithNormalQueryAsync( + public async Task> FindAllDeclarationsWithNormalQueryAsync( ProjectId projectId, string name, SearchKind searchKind, SymbolFilter criteria, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) @@ -77,7 +78,7 @@ public async Task FindLiteralReferencesAsync(object value, TypeCode typeCode, Ca } } - public async Task> FindSolutionSourceDeclarationsWithNormalQueryAsync( + public async Task> FindSolutionSourceDeclarationsWithNormalQueryAsync( string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) @@ -90,7 +91,7 @@ public async Task FindLiteralReferencesAsync(object value, TypeCode typeCode, Ca } } - public async Task> FindProjectSourceDeclarationsWithNormalQueryAsync( + public async Task> FindProjectSourceDeclarationsWithNormalQueryAsync( ProjectId projectId, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) @@ -105,7 +106,7 @@ public async Task FindLiteralReferencesAsync(object value, TypeCode typeCode, Ca } } - public async Task> FindProjectSourceDeclarationsWithPatternAsync( + public async Task> FindProjectSourceDeclarationsWithPatternAsync( ProjectId projectId, string pattern, SymbolFilter criteria, CancellationToken cancellationToken) { using (UserOperationBooster.Boost()) diff --git a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_TodoComments.cs b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_TodoComments.cs index a9cde5d462b2d..4dec373eb2039 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_TodoComments.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/CodeAnalysisService_TodoComments.cs @@ -23,7 +23,7 @@ internal partial class CodeAnalysisService : IRemoteTodoCommentService /// /// This will be called by ServiceHub/JsonRpc framework /// - public async Task> GetTodoCommentsAsync(PinnedSolutionInfo solutionInfo, DocumentId documentId, ImmutableArray tokens, CancellationToken cancellationToken) + public async Task> GetTodoCommentsAsync(PinnedSolutionInfo solutionInfo, DocumentId documentId, IList tokens, CancellationToken cancellationToken) { using (RoslynLogger.LogBlock(FunctionId.CodeAnalysisService_GetTodoCommentsAsync, documentId.ProjectId.DebugName, cancellationToken)) { diff --git a/src/Workspaces/Remote/ServiceHub/Services/RemoteSymbolSearchUpdateEngine.cs b/src/Workspaces/Remote/ServiceHub/Services/RemoteSymbolSearchUpdateEngine.cs index d424a5c47e2b8..d46a9e47c43d0 100644 --- a/src/Workspaces/Remote/ServiceHub/Services/RemoteSymbolSearchUpdateEngine.cs +++ b/src/Workspaces/Remote/ServiceHub/Services/RemoteSymbolSearchUpdateEngine.cs @@ -1,6 +1,7 @@ // 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 System.IO; using System.Threading; @@ -28,7 +29,7 @@ public Task UpdateContinuouslyAsync(string sourceName, string localSettingsDirec return _updateEngine.UpdateContinuouslyAsync(sourceName, localSettingsDirectory); } - public async Task> FindPackagesWithTypeAsync(string source, string name, int arity, CancellationToken cancellationToken) + public async Task> FindPackagesWithTypeAsync(string source, string name, int arity, CancellationToken cancellationToken) { var results = await _updateEngine.FindPackagesWithTypeAsync( source, name, arity, cancellationToken).ConfigureAwait(false); @@ -36,7 +37,7 @@ public async Task> FindPackagesWithTypeAsy return results; } - public async Task> FindPackagesWithAssemblyAsync(string source, string assemblyName, CancellationToken cancellationToken) + public async Task> FindPackagesWithAssemblyAsync(string source, string assemblyName, CancellationToken cancellationToken) { var results = await _updateEngine.FindPackagesWithAssemblyAsync( source, assemblyName, cancellationToken).ConfigureAwait(false); @@ -44,7 +45,7 @@ public async Task> FindPackagesWithAss return results; } - public async Task> FindReferenceAssembliesWithTypeAsync(string name, int arity, CancellationToken cancellationToken) + public async Task> FindReferenceAssembliesWithTypeAsync(string name, int arity, CancellationToken cancellationToken) { var results = await _updateEngine.FindReferenceAssembliesWithTypeAsync( name, arity, cancellationToken).ConfigureAwait(false); diff --git a/src/Workspaces/VisualBasic/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.vb b/src/Workspaces/VisualBasic/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.vb index c2a9b6a29dbc0..1102cfb65b96e 100644 --- a/src/Workspaces/VisualBasic/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.vb +++ b/src/Workspaces/VisualBasic/Portable/Classification/SyntaxClassification/NameSyntaxClassifier.vb @@ -64,6 +64,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Classification.Classifiers End Select End If + ' Classify a reference to an attribute constructor in an attribute location + ' as if we were classifying the attribute type itself. + If symbol.IsConstructor() AndAlso node.IsParentKind(SyntaxKind.Attribute) Then + symbol = symbol.ContainingType + End If + If symbol IsNot Nothing Then If symbol.Kind = SymbolKind.Method Then Dim method = DirectCast(symbol, IMethodSymbol) diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb index 33e2eb31ab0a0..0b9fe01a99455 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb @@ -46,6 +46,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Get End Property + Public ReadOnly Property ElasticMarker As SyntaxTrivia Implements ISyntaxFactsService.ElasticMarker + Get + Return SyntaxFactory.ElasticMarker + End Get + End Property + Public ReadOnly Property ElasticCarriageReturnLineFeed As SyntaxTrivia Implements ISyntaxFactsService.ElasticCarriageReturnLineFeed Get Return SyntaxFactory.ElasticCarriageReturnLineFeed