Skip to content

Commit 84d613f

Browse files
Fix INTL0101 code fix NotImplementedException for non-class declaration types
The AttributesOnSeparateLines code fix only handled ClassDeclarationSyntax, MethodDeclarationSyntax, PropertyDeclarationSyntax, and FieldDeclarationSyntax. Any other declaration type flagged by the analyzer (structs, records, interfaces, enums, constructors, enum members, indexers, etc.) would throw NotImplementedException when a user tried to apply the code fix. Replace both switch expressions with MemberDeclarationSyntax base class pattern matching, which covers all C# declaration types via the shared AttributeLists / WithAttributeLists() abstract members. Use graceful fallbacks instead of throwing. Add code fix tests for: struct, record, interface, enum type, constructor, enum member, and indexer declarations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4569a5b commit 84d613f

2 files changed

Lines changed: 310 additions & 10 deletions

File tree

IntelliTect.Analyzer/IntelliTect.Analyzer.CodeFixes/AttributesOnSeparateLines.cs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,23 +95,17 @@ private static IEnumerable<AttributeListSyntax> GetAttributeListSyntaxes(SyntaxN
9595
{
9696
return node switch
9797
{
98-
ClassDeclarationSyntax c => c.AttributeLists,
99-
MethodDeclarationSyntax m => m.AttributeLists,
100-
PropertyDeclarationSyntax p => p.AttributeLists,
101-
FieldDeclarationSyntax f => f.AttributeLists,
102-
_ => throw new NotImplementedException(),
98+
MemberDeclarationSyntax m => m.AttributeLists,
99+
_ => Enumerable.Empty<AttributeListSyntax>(),
103100
};
104101
}
105102

106103
private static SyntaxNode BuildNodeWithAttributeLists(SyntaxNode node, SyntaxList<AttributeListSyntax> attributeLists)
107104
{
108105
return node switch
109106
{
110-
ClassDeclarationSyntax c => c.WithAttributeLists(attributeLists),
111-
MethodDeclarationSyntax m => m.WithAttributeLists(attributeLists),
112-
PropertyDeclarationSyntax p => p.WithAttributeLists(attributeLists),
113-
FieldDeclarationSyntax f => f.WithAttributeLists(attributeLists),
114-
_ => throw new NotImplementedException(),
107+
MemberDeclarationSyntax m => m.WithAttributeLists(attributeLists),
108+
_ => node,
115109
};
116110
}
117111
}

IntelliTect.Analyzer/IntelliTect.Analyzer.Test/AttributesOnSeparateLinesTests.cs

Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,312 @@ static void Main()
390390
await VerifyCSharpFix(test, fixTest);
391391
}
392392

393+
[TestMethod]
394+
public async Task StructAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
395+
{
396+
string test = @"using System;
397+
398+
namespace ConsoleApp
399+
{
400+
class AAttribute : Attribute
401+
{
402+
}
403+
404+
class BAttribute : Attribute
405+
{
406+
}
407+
408+
[A][B]
409+
struct MyStruct
410+
{
411+
}
412+
}";
413+
414+
string fixTest = @"using System;
415+
416+
namespace ConsoleApp
417+
{
418+
class AAttribute : Attribute
419+
{
420+
}
421+
422+
class BAttribute : Attribute
423+
{
424+
}
425+
426+
[A]
427+
[B]
428+
struct MyStruct
429+
{
430+
}
431+
}";
432+
await VerifyCSharpFix(test, fixTest);
433+
}
434+
435+
[TestMethod]
436+
public async Task RecordAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
437+
{
438+
string test = @"using System;
439+
440+
namespace ConsoleApp
441+
{
442+
class AAttribute : Attribute
443+
{
444+
}
445+
446+
class BAttribute : Attribute
447+
{
448+
}
449+
450+
[A][B]
451+
record MyRecord
452+
{
453+
}
454+
}";
455+
456+
string fixTest = @"using System;
457+
458+
namespace ConsoleApp
459+
{
460+
class AAttribute : Attribute
461+
{
462+
}
463+
464+
class BAttribute : Attribute
465+
{
466+
}
467+
468+
[A]
469+
[B]
470+
record MyRecord
471+
{
472+
}
473+
}";
474+
await VerifyCSharpFix(test, fixTest);
475+
}
476+
477+
[TestMethod]
478+
public async Task InterfaceAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
479+
{
480+
string test = @"using System;
481+
482+
namespace ConsoleApp
483+
{
484+
class AAttribute : Attribute
485+
{
486+
}
487+
488+
class BAttribute : Attribute
489+
{
490+
}
491+
492+
[A][B]
493+
interface IMyInterface
494+
{
495+
}
496+
}";
497+
498+
string fixTest = @"using System;
499+
500+
namespace ConsoleApp
501+
{
502+
class AAttribute : Attribute
503+
{
504+
}
505+
506+
class BAttribute : Attribute
507+
{
508+
}
509+
510+
[A]
511+
[B]
512+
interface IMyInterface
513+
{
514+
}
515+
}";
516+
await VerifyCSharpFix(test, fixTest);
517+
}
518+
519+
[TestMethod]
520+
public async Task EnumAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
521+
{
522+
string test = @"using System;
523+
524+
namespace ConsoleApp
525+
{
526+
class AAttribute : Attribute
527+
{
528+
}
529+
530+
class BAttribute : Attribute
531+
{
532+
}
533+
534+
[A][B]
535+
enum MyEnum
536+
{
537+
Foo
538+
}
539+
}";
540+
541+
string fixTest = @"using System;
542+
543+
namespace ConsoleApp
544+
{
545+
class AAttribute : Attribute
546+
{
547+
}
548+
549+
class BAttribute : Attribute
550+
{
551+
}
552+
553+
[A]
554+
[B]
555+
enum MyEnum
556+
{
557+
Foo
558+
}
559+
}";
560+
await VerifyCSharpFix(test, fixTest);
561+
}
562+
563+
[TestMethod]
564+
public async Task ConstructorAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
565+
{
566+
string test = @"using System;
567+
568+
namespace ConsoleApp
569+
{
570+
class AAttribute : Attribute
571+
{
572+
}
573+
574+
class BAttribute : Attribute
575+
{
576+
}
577+
578+
class Program
579+
{
580+
[A][B]
581+
Program()
582+
{
583+
}
584+
}
585+
}";
586+
587+
string fixTest = @"using System;
588+
589+
namespace ConsoleApp
590+
{
591+
class AAttribute : Attribute
592+
{
593+
}
594+
595+
class BAttribute : Attribute
596+
{
597+
}
598+
599+
class Program
600+
{
601+
[A]
602+
[B]
603+
Program()
604+
{
605+
}
606+
}
607+
}";
608+
await VerifyCSharpFix(test, fixTest);
609+
}
610+
611+
[TestMethod]
612+
public async Task EnumMemberAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
613+
{
614+
string test = @"using System;
615+
616+
namespace ConsoleApp
617+
{
618+
class AAttribute : Attribute
619+
{
620+
}
621+
622+
class BAttribute : Attribute
623+
{
624+
}
625+
626+
enum MyEnum
627+
{
628+
[A][B]
629+
Bar
630+
}
631+
}";
632+
633+
string fixTest = @"using System;
634+
635+
namespace ConsoleApp
636+
{
637+
class AAttribute : Attribute
638+
{
639+
}
640+
641+
class BAttribute : Attribute
642+
{
643+
}
644+
645+
enum MyEnum
646+
{
647+
[A]
648+
[B]
649+
Bar
650+
}
651+
}";
652+
await VerifyCSharpFix(test, fixTest);
653+
}
654+
655+
[TestMethod]
656+
public async Task IndexerAttributeLineViolation_CodeFix_TwoAttributesOnSameLine_TwoAttributesOnSeparateLines()
657+
{
658+
string test = @"using System;
659+
660+
namespace ConsoleApp
661+
{
662+
class AAttribute : Attribute
663+
{
664+
}
665+
666+
class BAttribute : Attribute
667+
{
668+
}
669+
670+
class Program
671+
{
672+
[A][B]
673+
int this[int i] { get => 0; }
674+
}
675+
}";
676+
677+
string fixTest = @"using System;
678+
679+
namespace ConsoleApp
680+
{
681+
class AAttribute : Attribute
682+
{
683+
}
684+
685+
class BAttribute : Attribute
686+
{
687+
}
688+
689+
class Program
690+
{
691+
[A]
692+
[B]
693+
int this[int i] { get => 0; }
694+
}
695+
}";
696+
await VerifyCSharpFix(test, fixTest);
697+
}
698+
393699
[TestMethod]
394700
[Description("Analyzer should not report on generated code")]
395701
public void AttributesOnSameLine_InGeneratedCode_NoDiagnostic()

0 commit comments

Comments
 (0)