C#: Only extract locations for unbound declarations (if a declaration can be unfound) and don't extract empty locations.

This commit is contained in:
Michael Nebel
2025-09-30 11:23:24 +02:00
parent e9901305b2
commit 443c183e41
24 changed files with 63 additions and 33 deletions

View File

@@ -63,8 +63,10 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.accessors(this, kind, Symbol.Name, parent, unboundAccessor);
foreach (var l in Locations)
trapFile.accessor_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.accessor_location, this, Locations);
}
Overrides(trapFile);

View File

@@ -59,11 +59,11 @@ namespace Semmle.Extraction.CSharp.Entities
{
var type = Type.Create(Context, Symbol.AttributeClass);
trapFile.attributes(this, kind, type.TypeRef, entity);
trapFile.attribute_location(this, Location);
WriteLocationToTrap(trapFile.attribute_location, this, Location);
if (attributeSyntax is not null)
{
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
WriteLocationToTrap(trapFile.attribute_location, this, Assembly.CreateOutputAssembly(Context));
TypeMention.Create(Context, attributeSyntax.Name, this, type);
}

View File

@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.CodeAnalysis;
@@ -52,6 +54,22 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
protected static void WriteLocationToTrap<T1>(Action<T1, Location> writeAction, T1 entity, Location l)
{
if (l is not EmptyLocation)
{
writeAction(entity, l);
}
}
protected static void WriteLocationsToTrap<T1>(Action<T1, Location> writeAction, T1 entity, IEnumerable<Location> locations)
{
foreach (var loc in locations)
{
WriteLocationToTrap(writeAction, entity, loc);
}
}
public override bool NeedsPopulation { get; }
public override int GetHashCode() => Symbol is null ? 0 : Symbol.GetHashCode();

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

View File

@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
trapFile.commentblock(this);
trapFile.commentblock_location(this, Context.CreateLocation(Symbol.Location));
WriteLocationToTrap(trapFile.commentblock_location, this, Context.CreateLocation(Symbol.Location));
Symbol.CommentLines.ForEach((l, child) => trapFile.commentblock_child(this, l, child));
}

View File

@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
location = Context.CreateLocation(Location);
trapFile.commentline(this, Type == CommentLineType.MultilineContinuation ? CommentLineType.Multiline : Type, Text, RawText);
trapFile.commentline_location(this, location);
WriteLocationToTrap(trapFile.commentline_location, this, location);
}
public override Microsoft.CodeAnalysis.Location? ReportingLocation => location?.Symbol;

View File

@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities
ContainingType!.PopulateGenerics();
trapFile.constructors(this, Symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
trapFile.constructor_location(this, Location);
WriteLocationToTrap(trapFile.constructor_location, this, Location);
if (MakeSynthetic)
{

View File

@@ -15,7 +15,7 @@ namespace Semmle.Extraction.CSharp.Entities
ContainingType!.PopulateGenerics();
trapFile.destructors(this, $"~{Symbol.ContainingType.Name}", ContainingType, OriginalDefinition(Context, this, Symbol));
trapFile.destructor_location(this, Location);
WriteLocationToTrap(trapFile.destructor_location, this, Location);
}
private static new Destructor OriginalDefinition(Context cx, Destructor original, IMethodSymbol symbol)

View File

@@ -51,8 +51,10 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier!.Name, this, explicitInterface);
}
foreach (var l in Locations)
trapFile.event_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.event_location, this, Locations);
}
foreach (var syntaxType in declSyntaxReferences
.OfType<VariableDeclaratorSyntax>()

View File

@@ -48,8 +48,10 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.event_accessors(this, kind, Symbol.Name, parent, unboundAccessor);
foreach (var l in Locations)
trapFile.event_accessor_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.event_accessor_location, this, Locations);
}
Overrides(trapFile);

View File

@@ -40,6 +40,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.expr_parent_top_level(this, info.Child, info.Parent);
else
trapFile.expr_parent(this, info.Child, info.Parent);
trapFile.expr_location(this, Location);
if (Type.HasValue && !Type.Value.HasObliviousNullability())

View File

@@ -49,8 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
foreach (var l in Locations)
trapFile.field_location(this, l);
WriteLocationsToTrap(trapFile.field_location, this, Locations);
if (!IsSourceDeclaration || !Symbol.FromSource())
return;

View File

@@ -19,8 +19,10 @@ namespace Semmle.Extraction.CSharp.Entities
var type = Type.Create(Context, Symbol.Type);
trapFile.indexers(this, Symbol.GetName(useMetadataName: true), ContainingType!, type.TypeRef, OriginalDefinition);
foreach (var l in Locations)
trapFile.indexer_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.indexer_location, this, Locations);
}
var getter = BodyDeclaringSymbol.GetMethod;
var setter = BodyDeclaringSymbol.SetMethod;

View File

@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.localvars(this, Kinds.VariableKind.None, Symbol.Name, @var, Type.Create(Context, parent.Type).TypeRef, parent);
}
trapFile.localvar_location(this, Location);
WriteLocationToTrap(trapFile.localvar_location, this, Location);
DefineConstantValue(trapFile);
}

View File

@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities
var ns = Namespace.Create(Context, @namespace);
trapFile.namespace_declarations(this, ns);
trapFile.namespace_declaration_location(this, Context.CreateLocation(node.Name.GetLocation()));
WriteLocationToTrap(trapFile.namespace_declaration_location, this, Context.CreateLocation(node.Name.GetLocation()));
var visitor = new Populators.TypeOrNamespaceVisitor(Context, trapFile, this);

View File

@@ -43,8 +43,10 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
foreach (var l in Locations)
trapFile.method_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.method_location, this, Locations);
}
PopulateGenerics(trapFile);
Overrides(trapFile);

View File

@@ -116,14 +116,16 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent!, Original);
foreach (var l in Symbol.Locations)
trapFile.param_location(this, Context.CreateLocation(l));
{
WriteLocationToTrap(trapFile.param_location, this, Context.CreateLocation(l));
}
if (!Symbol.Locations.Any() &&
Symbol.ContainingSymbol is IMethodSymbol ms &&
ms.Name == WellKnownMemberNames.TopLevelStatementsEntryPointMethodName &&
ms.ContainingType.Name == WellKnownMemberNames.TopLevelStatementsEntryPointTypeName)
{
trapFile.param_location(this, Context.CreateLocation());
WriteLocationToTrap(trapFile.param_location, this, Context.CreateLocation());
}
if (Symbol.HasExplicitDefaultValue && Context.Defines(Symbol))
@@ -247,7 +249,6 @@ namespace Semmle.Extraction.CSharp.Entities
var typeKey = VarargsType.Create(Context);
// !! Maybe originaldefinition is wrong
trapFile.@params(this, "", typeKey, Ordinal, Kind.None, Parent!, this);
trapFile.param_location(this, GeneratedLocation.Create(Context));
}
protected override int Ordinal => ((Method)Parent!).OriginalDefinition.Symbol.Parameters.Length;

View File

@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
PopulatePreprocessor(trapFile);
trapFile.preprocessor_directive_active(this, Symbol.IsActive);
trapFile.preprocessor_directive_location(this, Context.CreateLocation(ReportingLocation));
WriteLocationToTrap(trapFile.preprocessor_directive_location, this, Context.CreateLocation(ReportingLocation));
var compilation = Compilation.Create(Context);
trapFile.preprocessor_directive_compilation(this, compilation);

View File

@@ -69,8 +69,10 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier!.Name, this, explicitInterface);
}
foreach (var l in Locations)
trapFile.property_location(this, l);
if (Context.ExtractLocation(Symbol))
{
WriteLocationsToTrap(trapFile.property_location, this, Locations);
}
if (IsSourceDeclaration && Symbol.FromSource())
{

View File

@@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
trapFile.types(this, Kinds.TypeKind.DYNAMIC, "dynamic");
trapFile.type_location(this, Location);
WriteLocationToTrap(trapFile.type_location, this, Location);
trapFile.has_modifiers(this, Modifier.Create(Context, "public"));
trapFile.parent_namespace(this, Namespace.Create(Context, Context.Compilation.GlobalNamespace));

View File

@@ -83,8 +83,7 @@ namespace Semmle.Extraction.CSharp.Entities
// Class location
if (!Symbol.IsGenericType || Symbol.IsReallyUnbound())
{
foreach (var l in Locations)
trapFile.type_location(this, l);
WriteLocationsToTrap(trapFile.type_location, this, Locations);
}
if (Symbol.IsAnonymousType)

View File

@@ -55,7 +55,7 @@ namespace Semmle.Extraction.CSharp.Entities
// about what locations are available for a tuple type.
// Sometimes it's the source code, and sometimes it's empty.
foreach (var l in Symbol.Locations)
trapFile.type_location(this, Context.CreateLocation(l));
WriteLocationToTrap(trapFile.type_location, this, Context.CreateLocation(l));
}
private readonly Lazy<Field?[]> tupleElementsLazy;

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var l in Symbol.Locations)
{
trapFile.type_location(this, Context.CreateLocation(l));
WriteLocationToTrap(trapFile.type_location, this, Context.CreateLocation(l));
}
if (IsSourceDeclaration)

View File

@@ -26,8 +26,7 @@ namespace Semmle.Extraction.CSharp.Entities
returnType.TypeRef,
(UserOperator)OriginalDefinition);
foreach (var l in Locations)
trapFile.operator_location(this, l);
WriteLocationsToTrap(trapFile.operator_location, this, Locations);
if (IsSourceDeclaration)
{