diff --git a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs index 4804ef1c971f0..945b0566ded84 100644 --- a/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs +++ b/src/Compilers/CSharp/Portable/Declarations/DeclarationTreeBuilder.cs @@ -693,6 +693,15 @@ private SingleTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyntax node, D { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasPrimaryConstructor; + + foreach (var attributeListSyntax in node.AttributeLists) + { + if (attributeListSyntax.Target?.Identifier.ToAttributeLocation() == AttributeLocation.Method) + { + declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasAttributes; + break; + } + } } var memberNames = GetNonTypeMemberNames( diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PrimaryConstructorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PrimaryConstructorTests.cs index e3905450d2eff..b2c007beae636 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PrimaryConstructorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PrimaryConstructorTests.cs @@ -3428,6 +3428,121 @@ class C(int someParam) Assert.Equal(@"A(""someParam"")", c.PrimaryConstructor.GetAttributes().Single().ToString()); } + [Theory] + [CombinatorialData] + [WorkItem("https://github.com/dotnet/roslyn/issues/68349")] + public void AttributesOnPrimaryConstructor_11([CombinatorialValues("class C();", "struct C();", "record C();", "record class C();", "record struct C();")] string declaration) + { + string source = @" +_ = new C(); + +[method: System.Obsolete(""Obsolete!!!"", error: true)] +" + declaration + @" +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (2,5): error CS0619: 'C.C()' is obsolete: 'Obsolete!!!' + // _ = new C(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "new C()").WithArguments("C.C()", "Obsolete!!!").WithLocation(2, 5) + ); + + var c = (SourceMemberContainerTypeSymbol)comp.GetTypeByMetadataName("C"); + Assert.True(c.AnyMemberHasAttributes); + } + + [Theory] + [CombinatorialData] + public void AttributesOnPrimaryConstructor_12([CombinatorialValues("class", "struct", "record", "record class", "record struct")] string declaration) + { + string source = @" +_ = new C1(); + +partial " + declaration + @" C1(); + +#line 100 +[method: System.Obsolete(""Obsolete!!!"", error: true)] +partial " + declaration + @" C1 +#line 200 + ; +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (100,2): warning CS0657: 'method' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'type'. All attributes in this block will be ignored. + // [method: System.Obsolete("Obsolete!!!", error: true)] + Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "method").WithArguments("method", "type").WithLocation(100, 2) + ); + + var c1 = (SourceMemberContainerTypeSymbol)comp.GetTypeByMetadataName("C1"); + Assert.False(c1.AnyMemberHasAttributes); + } + + [Theory] + [CombinatorialData] + public void AttributesOnPrimaryConstructor_13([CombinatorialValues("class", "struct", "record", "record class", "record struct")] string declaration) + { + string source = @" +_ = new C1(); + +[method: System.Obsolete(""Obsolete!!!"", error: true)] +partial " + declaration + @" C1(); + +partial " + declaration + @" C1; +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (2,5): error CS0619: 'C1.C1()' is obsolete: 'Obsolete!!!' + // _ = new C1(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "new C1()").WithArguments("C1.C1()", "Obsolete!!!").WithLocation(2, 5) + ); + + var c1 = (SourceMemberContainerTypeSymbol)comp.GetTypeByMetadataName("C1"); + Assert.True(c1.AnyMemberHasAttributes); + } + + [Theory] + [CombinatorialData] + [WorkItem("https://github.com/dotnet/roslyn/issues/68349")] + public void AttributesOnPrimaryConstructor_14([CombinatorialValues("class C();", "struct C();", "record C();", "record class C();", "record struct C();")] string declaration) + { + string source = @" +_ = new C(); + +[System.Obsolete(""Obsolete!!!"", error: true)] +" + declaration + @" +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (2,9): error CS0619: 'C' is obsolete: 'Obsolete!!!' + // _ = new C(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "C").WithArguments("C", "Obsolete!!!").WithLocation(2, 9) + ); + + var c = (SourceMemberContainerTypeSymbol)comp.GetTypeByMetadataName("C"); + Assert.False(c.AnyMemberHasAttributes); + } + + [Theory] + [CombinatorialData] + [WorkItem("https://github.com/dotnet/roslyn/issues/68349")] + public void AttributesOnPrimaryConstructor_15([CombinatorialValues("class C();", "struct C();", "record C();", "record class C();", "record struct C();")] string declaration) + { + string source = @" +_ = new C(); + +[type: System.Obsolete(""Obsolete!!!"", error: true)] +" + declaration + @" +"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (2,9): error CS0619: 'C' is obsolete: 'Obsolete!!!' + // _ = new C(); + Diagnostic(ErrorCode.ERR_DeprecatedSymbolStr, "C").WithArguments("C", "Obsolete!!!").WithLocation(2, 9) + ); + + var c = (SourceMemberContainerTypeSymbol)comp.GetTypeByMetadataName("C"); + Assert.False(c.AnyMemberHasAttributes); + } + [Fact] public void AnalyzerActions_01_Class() {