From b90338042b95d32ccb602e487ab423709fa4fee0 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Thu, 23 Jun 2022 11:44:53 -0700 Subject: [PATCH 1/2] Handle possible null symbols in getAttributeTarget --- .../Compilation/SyntaxTreeSemanticModel.cs | 12 ++-- .../Semantic/Semantics/LocalFunctionTests.cs | 61 +++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 1d56e63bbf85e..09f122b1b3b6b 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -1291,12 +1291,12 @@ Symbol getAttributeTarget(SyntaxNode targetSyntax) { BaseMethodDeclarationSyntax methodDeclaration => GetDeclaredMemberSymbol(methodDeclaration), LocalFunctionStatementSyntax localFunction => GetMemberModel(localFunction)?.GetDeclaredLocalFunction(localFunction), - ParameterSyntax parameterSyntax => ((Symbols.PublicModel.ParameterSymbol)GetDeclaredSymbol(parameterSyntax)).UnderlyingSymbol, - TypeParameterSyntax typeParameterSyntax => ((Symbols.PublicModel.TypeParameterSymbol)GetDeclaredSymbol(typeParameterSyntax)).UnderlyingSymbol, - IndexerDeclarationSyntax indexerSyntax => ((Symbols.PublicModel.PropertySymbol)GetDeclaredSymbol(indexerSyntax)).UnderlyingSymbol, - AccessorDeclarationSyntax accessorSyntax => ((Symbols.PublicModel.MethodSymbol)GetDeclaredSymbol(accessorSyntax)).UnderlyingSymbol, - AnonymousFunctionExpressionSyntax anonymousFunction => ((Symbols.PublicModel.Symbol)GetSymbolInfo(anonymousFunction).Symbol).UnderlyingSymbol, - DelegateDeclarationSyntax delegateSyntax => ((Symbols.PublicModel.NamedTypeSymbol)GetDeclaredSymbol(delegateSyntax)).UnderlyingSymbol, + ParameterSyntax parameterSyntax => ((Symbols.PublicModel.ParameterSymbol)GetDeclaredSymbol(parameterSyntax))?.UnderlyingSymbol, + TypeParameterSyntax typeParameterSyntax => ((Symbols.PublicModel.TypeParameterSymbol)GetDeclaredSymbol(typeParameterSyntax))?.UnderlyingSymbol, + IndexerDeclarationSyntax indexerSyntax => ((Symbols.PublicModel.PropertySymbol)GetDeclaredSymbol(indexerSyntax))?.UnderlyingSymbol, + AccessorDeclarationSyntax accessorSyntax => ((Symbols.PublicModel.MethodSymbol)GetDeclaredSymbol(accessorSyntax))?.UnderlyingSymbol, + AnonymousFunctionExpressionSyntax anonymousFunction => ((Symbols.PublicModel.Symbol)GetSymbolInfo(anonymousFunction).Symbol)?.UnderlyingSymbol, + DelegateDeclarationSyntax delegateSyntax => ((Symbols.PublicModel.NamedTypeSymbol)GetDeclaredSymbol(delegateSyntax))?.UnderlyingSymbol, _ => null }; } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index df87ce161d64c..d134238caf131 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -9748,6 +9748,40 @@ public MyAttribute(string name1) { } ); } + [Fact, WorkItem(1556927, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1556927")] + public void ParameterScope_ValueLocalNotInPropertyOrAccessorAttributeNameOf_UnknownAccessor() + { + var source = @" +class C +{ + int Property4 { [My(nameof(value))] unknown => throw null; } +} + +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name) { } +} +"; + var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }); + comp.VerifyDiagnostics( + // (4,9): error CS0548: 'C.Property4': property or indexer must have at least one accessor + // int Property4 { [My(nameof(value))] unknown => throw null; } + Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "Property4").WithArguments("C.Property4").WithLocation(4, 9), + // (4,41): error CS1014: A get or set accessor expected + // int Property4 { [My(nameof(value))] unknown => throw null; } + Diagnostic(ErrorCode.ERR_GetOrSetExpected, "unknown").WithLocation(4, 41) + ); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var node = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "value") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.Attribute))) + .Single(); + + Assert.Null(model.GetSymbolInfo(node).Symbol); + } + [Fact] public void ParameterScope_InParameterAttributeNameOf_Constructor() { @@ -10429,5 +10463,32 @@ public MyAttribute(string name1) { } "); comp.VerifyDiagnostics(); } + + [Fact, WorkItem(1556927, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1556927")] + public void LambdaOutsideMemberModel() + { + var text = @" +public class MyAttribute : System.Attribute +{ + public MyAttribute(string name1) { } +} + +int P +{ + badAccessorName + { + M([My(nameof(P))] env => env); +"; + var comp = CreateCompilation(text); + + var tree = comp.SyntaxTrees.First(); + var model = comp.GetSemanticModel(tree); + var node = tree.GetRoot().DescendantNodes().OfType() + .Where(i => i.Identifier.ValueText == "P") + .Where(i => i.Ancestors().Any(a => a.IsKind(SyntaxKind.Attribute))) + .Single(); + + Assert.Null(model.GetSymbolInfo(node).Symbol); + } } } From 94982f3a70fb1ea6386afa120cec763d090ba1a6 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Sun, 26 Jun 2022 09:43:34 -0700 Subject: [PATCH 2/2] Factor with GetDeclaredSymbolForNode --- .../Compilation/SyntaxTreeSemanticModel.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 09f122b1b3b6b..8776d29626174 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -1289,14 +1289,14 @@ Symbol getAttributeTarget(SyntaxNode targetSyntax) { return targetSyntax switch { - BaseMethodDeclarationSyntax methodDeclaration => GetDeclaredMemberSymbol(methodDeclaration), - LocalFunctionStatementSyntax localFunction => GetMemberModel(localFunction)?.GetDeclaredLocalFunction(localFunction), - ParameterSyntax parameterSyntax => ((Symbols.PublicModel.ParameterSymbol)GetDeclaredSymbol(parameterSyntax))?.UnderlyingSymbol, - TypeParameterSyntax typeParameterSyntax => ((Symbols.PublicModel.TypeParameterSymbol)GetDeclaredSymbol(typeParameterSyntax))?.UnderlyingSymbol, - IndexerDeclarationSyntax indexerSyntax => ((Symbols.PublicModel.PropertySymbol)GetDeclaredSymbol(indexerSyntax))?.UnderlyingSymbol, - AccessorDeclarationSyntax accessorSyntax => ((Symbols.PublicModel.MethodSymbol)GetDeclaredSymbol(accessorSyntax))?.UnderlyingSymbol, - AnonymousFunctionExpressionSyntax anonymousFunction => ((Symbols.PublicModel.Symbol)GetSymbolInfo(anonymousFunction).Symbol)?.UnderlyingSymbol, - DelegateDeclarationSyntax delegateSyntax => ((Symbols.PublicModel.NamedTypeSymbol)GetDeclaredSymbol(delegateSyntax))?.UnderlyingSymbol, + BaseMethodDeclarationSyntax or + LocalFunctionStatementSyntax or + ParameterSyntax or + TypeParameterSyntax or + IndexerDeclarationSyntax or + AccessorDeclarationSyntax or + DelegateDeclarationSyntax => GetDeclaredSymbolForNode(targetSyntax).GetSymbol(), + AnonymousFunctionExpressionSyntax anonymousFunction => GetSymbolInfo(anonymousFunction).Symbol.GetSymbol(), _ => null }; }