mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
Merge pull request #12234 from michaelnebel/csharp/filescopedtypes
C# 11: Support for `file` scoped types.
This commit is contained in:
@@ -85,6 +85,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (nt.IsRecord)
|
||||
HasModifier(cx, trapFile, key, Modifiers.Record);
|
||||
|
||||
if (nt.IsFileLocal)
|
||||
HasModifier(cx, trapFile, key, Modifiers.File);
|
||||
|
||||
if (nt.TypeKind == TypeKind.Struct)
|
||||
{
|
||||
if (nt.IsReadOnly)
|
||||
@@ -97,7 +100,11 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
|
||||
{
|
||||
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
|
||||
// A file scoped type has declared accessibility `internal` which we shouldn't extract.
|
||||
// The file modifier is extracted as a source level modifier.
|
||||
if (symbol.Kind != SymbolKind.NamedType || !((INamedTypeSymbol)symbol).IsFileLocal)
|
||||
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
|
||||
|
||||
if (symbol.Kind == SymbolKind.ErrorType)
|
||||
trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public));
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ internal static class Modifiers
|
||||
public const string Async = "async";
|
||||
public const string Const = "const";
|
||||
public const string Extern = "extern";
|
||||
public const string File = "file";
|
||||
public const string Internal = "internal";
|
||||
public const string New = "new";
|
||||
public const string Override = "override";
|
||||
|
||||
@@ -282,54 +282,60 @@ namespace Semmle.Extraction.CSharp
|
||||
public static IEnumerable<IFieldSymbol?> GetTupleElementsMaybeNull(this INamedTypeSymbol type) =>
|
||||
type.TupleElements;
|
||||
|
||||
private static void BuildQualifierAndName(INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
|
||||
{
|
||||
if (named.ContainingType is not null)
|
||||
{
|
||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
trapFile.Write('.');
|
||||
}
|
||||
else if (named.ContainingNamespace is not null)
|
||||
{
|
||||
if (cx.ShouldAddAssemblyTrapPrefix && named.ContainingAssembly is not null)
|
||||
BuildAssembly(named.ContainingAssembly, trapFile);
|
||||
named.ContainingNamespace.BuildNamespace(cx, trapFile);
|
||||
}
|
||||
|
||||
var name = named.IsFileLocal ? named.MetadataName : named.Name;
|
||||
trapFile.Write(name);
|
||||
}
|
||||
|
||||
private static void BuildTupleId(INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined)
|
||||
{
|
||||
trapFile.Write('(');
|
||||
trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
|
||||
(i, f) =>
|
||||
{
|
||||
if (f is null)
|
||||
{
|
||||
trapFile.Write($"null({i})");
|
||||
}
|
||||
else
|
||||
{
|
||||
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
|
||||
trapFile.Write(":");
|
||||
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
}
|
||||
}
|
||||
);
|
||||
trapFile.Write(")");
|
||||
}
|
||||
|
||||
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
|
||||
{
|
||||
if (!constructUnderlyingTupleType && named.IsTupleType)
|
||||
{
|
||||
trapFile.Write('(');
|
||||
trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
|
||||
(i, f) =>
|
||||
{
|
||||
if (f is null)
|
||||
{
|
||||
trapFile.Write($"null({i})");
|
||||
}
|
||||
else
|
||||
{
|
||||
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
|
||||
trapFile.Write(":");
|
||||
f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
}
|
||||
}
|
||||
);
|
||||
trapFile.Write(")");
|
||||
BuildTupleId(named, cx, trapFile, symbolBeingDefined);
|
||||
return;
|
||||
}
|
||||
|
||||
void AddContaining()
|
||||
{
|
||||
if (named.ContainingType is not null)
|
||||
{
|
||||
named.ContainingType.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
|
||||
trapFile.Write('.');
|
||||
}
|
||||
else if (named.ContainingNamespace is not null)
|
||||
{
|
||||
if (cx.ShouldAddAssemblyTrapPrefix && named.ContainingAssembly is not null)
|
||||
BuildAssembly(named.ContainingAssembly, trapFile);
|
||||
named.ContainingNamespace.BuildNamespace(cx, trapFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (named.TypeParameters.IsEmpty)
|
||||
{
|
||||
AddContaining();
|
||||
trapFile.Write(named.Name);
|
||||
BuildQualifierAndName(named, cx, trapFile, symbolBeingDefined);
|
||||
}
|
||||
else if (named.IsReallyUnbound())
|
||||
{
|
||||
AddContaining();
|
||||
trapFile.Write(named.Name);
|
||||
BuildQualifierAndName(named, cx, trapFile, symbolBeingDefined);
|
||||
trapFile.Write("`");
|
||||
trapFile.Write(named.TypeParameters.Length);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user