@@ -25,6 +25,40 @@ public static bool ConstructedOrParentIsConstructed(INamedTypeSymbol symbol)
2525 symbol . ContainingType is not null && ConstructedOrParentIsConstructed ( symbol . ContainingType ) ;
2626 }
2727
28+
29+ /// <summary>
30+ /// A hashset containing the C# contextual keywords that could be confused with types (and typing).
31+ ///
32+ /// For the list of all contextual keywords, see
33+ /// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/#contextual-keywords
34+ /// </summary>
35+ private readonly HashSet < string > ContextualKeywordTypes = [
36+ "dynamic" ,
37+ "nint" ,
38+ "nuint" ,
39+ "var"
40+ ] ;
41+
42+ /// <summary>
43+ /// Returns true in case we suspect this is a broken type.
44+ /// </summary>
45+ /// <param name="symbol">Type symbol</param>
46+ private bool IsBrokenType ( ITypeSymbol symbol )
47+ {
48+ if ( ! Context . ExtractionContext . IsStandalone ||
49+ ! symbol . FromSource ( ) ||
50+ symbol . IsAnonymousType )
51+ {
52+ return false ;
53+ }
54+
55+ // (1) public class { ... } is a broken type as it doesn't have a name.
56+ // (2) public class var { ... } is an allowed type, but it overrides the `var` keyword for all uses.
57+ // The same goes for other contextual keywords that could be used as type names.
58+ // It is probably a better heuristic to treat these as broken types.
59+ return string . IsNullOrEmpty ( symbol . Name ) || ContextualKeywordTypes . Contains ( symbol . Name ) ;
60+ }
61+
2862 public Kinds . TypeKind GetTypeKind ( Context cx , bool constructUnderlyingTupleType )
2963 {
3064 switch ( Symbol . SpecialType )
@@ -48,6 +82,9 @@ public Kinds.TypeKind GetTypeKind(Context cx, bool constructUnderlyingTupleType)
4882 if ( Symbol . IsBoundNullable ( ) )
4983 return Kinds . TypeKind . NULLABLE ;
5084
85+ if ( IsBrokenType ( Symbol ) )
86+ return Kinds . TypeKind . UNKNOWN ;
87+
5188 switch ( Symbol . TypeKind )
5289 {
5390 case TypeKind . Class : return Kinds . TypeKind . CLASS ;
0 commit comments