Merge pull request #20525 from michaelnebel/csharp/reducelocationtuples

C#: Reduce location tuples.
This commit is contained in:
Michael Nebel
2025-10-02 12:32:35 +02:00
committed by GitHub
36 changed files with 223 additions and 48 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

@@ -2,11 +2,11 @@ using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
public class GeneratedLocation : SourceLocation
public class EmptyLocation : SourceLocation
{
private readonly File generatedFile;
private GeneratedLocation(Context cx)
private EmptyLocation(Context cx)
: base(cx, null)
{
generatedFile = GeneratedFile.Create(cx);
@@ -26,15 +26,16 @@ namespace Semmle.Extraction.CSharp.Entities
public override int GetHashCode() => 98732567;
public override bool Equals(object? obj) => obj is not null && obj.GetType() == typeof(GeneratedLocation);
public override bool Equals(object? obj) => obj is not null && obj.GetType() == typeof(EmptyLocation);
public static GeneratedLocation Create(Context cx) => GeneratedLocationFactory.Instance.CreateEntity(cx, typeof(GeneratedLocation), null);
public static EmptyLocation Create(Context cx)
=> EmptyLocationFactory.Instance.CreateEntity(cx, typeof(EmptyLocation), null);
private class GeneratedLocationFactory : CachedEntityFactory<string?, GeneratedLocation>
private class EmptyLocationFactory : CachedEntityFactory<string?, EmptyLocation>
{
public static GeneratedLocationFactory Instance { get; } = new GeneratedLocationFactory();
public static EmptyLocationFactory Instance { get; } = new EmptyLocationFactory();
public override GeneratedLocation Create(Context cx, string? init) => new GeneratedLocation(cx);
public override EmptyLocation Create(Context cx, string? init) => new EmptyLocation(cx);
}
}
}

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)
{

View File

@@ -238,6 +238,9 @@ namespace Semmle.Extraction.CSharp
compilationEntity = Entities.Compilation.Create(cx);
// Ensure that the empty location is always created.
Entities.EmptyLocation.Create(cx);
ExtractionContext.CompilationInfos.ForEach(ci => trapWriter.Writer.compilation_info(compilationEntity, ci.key, ci.value));
ReportProgressTaskDone(currentTaskId, assemblyPath, trapWriter.TrapFile, stopwatch.Elapsed, AnalysisAction.Extracted);

View File

@@ -550,6 +550,10 @@ namespace Semmle.Extraction.CSharp
!SymbolEqualityComparer.Default.Equals(symbol, symbol.OriginalDefinition) ||
scope.InScope(symbol);
public bool ExtractLocation(ISymbol symbol) =>
SymbolEqualityComparer.Default.Equals(symbol, symbol.OriginalDefinition) &&
scope.InScope(symbol);
/// <summary>
/// Runs the given action <paramref name="a"/>, guarding for trap duplication
/// based on key <paramref name="key"/>.
@@ -582,14 +586,14 @@ namespace Semmle.Extraction.CSharp
public Entities.Location CreateLocation()
{
return SourceTree is null
? Entities.GeneratedLocation.Create(this)
? Entities.EmptyLocation.Create(this)
: CreateLocation(Microsoft.CodeAnalysis.Location.Create(SourceTree, Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(0, 0)));
}
public Entities.Location CreateLocation(Microsoft.CodeAnalysis.Location? location)
{
return (location is null || location.Kind == LocationKind.None)
? Entities.GeneratedLocation.Create(this)
? Entities.EmptyLocation.Create(this)
: location.IsInSource
? Entities.NonGeneratedSourceLocation.Create(this, location)
: Entities.Assembly.Create(this, location);

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The extraction of the location for bound generic entities (methods, accessors, indexers, properties, and events) has been optimized. Previously, location information was extracted multiple times for each bound generic. Now, only the location of the unbound generic declaration is extracted during the extraction phase, and the QL library explicitly reuses this location for all bound instances of the same generic.

View File

@@ -265,7 +265,7 @@ class Method extends Callable, Virtualizable, Attributable, @method {
result = Virtualizable.super.getAnUltimateImplementor()
}
override Location getALocation() { method_location(this, result) }
override Location getALocation() { method_location(this.getUnboundDeclaration(), result) }
/** Holds if this method is an extension method. */
predicate isExtensionMethod() { this.getParameter(0).hasExtensionMethodModifier() }

View File

@@ -68,7 +68,7 @@ class Event extends DeclarationWithAccessors, @event {
result = DeclarationWithAccessors.super.getAnUltimateImplementor()
}
override Location getALocation() { event_location(this, result) }
override Location getALocation() { event_location(this.getUnboundDeclaration(), result) }
override string getAPrimaryQlClass() { result = "Event" }
}
@@ -99,7 +99,7 @@ class EventAccessor extends Accessor, @event_accessor {
override Event getDeclaration() { event_accessors(this, _, _, result, _) }
override Location getALocation() { event_accessor_location(this, result) }
override Location getALocation() { event_accessor_location(this.getUnboundDeclaration(), result) }
}
/**

View File

@@ -196,7 +196,7 @@ class Property extends DeclarationWithGetSetAccessors, @property {
override PropertyAccess getAnAccess() { result.getTarget() = this }
override Location getALocation() { property_location(this, result) }
override Location getALocation() { property_location(this.getUnboundDeclaration(), result) }
override Expr getAnAssignedValue() {
result = DeclarationWithGetSetAccessors.super.getAnAssignedValue()
@@ -328,7 +328,7 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer
result = DeclarationWithGetSetAccessors.super.getAnUltimateImplementor()
}
override Location getALocation() { indexer_location(this, result) }
override Location getALocation() { indexer_location(this.getUnboundDeclaration(), result) }
override string toStringWithTypes() {
result = this.getName() + "[" + this.parameterTypesToString() + "]"
@@ -408,7 +408,7 @@ class Accessor extends Callable, Modifiable, Attributable, Overridable, @callabl
override Accessor getUnboundDeclaration() { accessors(this, _, _, _, result) }
override Location getALocation() { accessor_location(this, result) }
override Location getALocation() { accessor_location(this.getUnboundDeclaration(), result) }
override string toString() { result = this.getName() }
}

View File

@@ -0,0 +1,35 @@
using System;
public abstract class A<T>
{
public abstract T Prop { get; }
public abstract T this[int index] { get; set; }
public abstract event EventHandler Event;
public void Apply(T t) { }
public abstract object ToObject(T t);
}
public class A2 : A<string>
{
public override string Prop => "";
public override string this[int i]
{
get { return ""; }
set { }
}
public override event EventHandler Event
{
add { }
remove { }
}
public override object ToObject(string t) => t;
public void M()
{
A2 other = new();
other.Apply("");
}
}

View File

@@ -0,0 +1,20 @@
using System;
public class B : A<int>
{
public override int Prop => 0;
public override int this[int i]
{
get { return 0; }
set { }
}
public override event EventHandler Event
{
add { }
remove { }
}
public override object ToObject(int t) => t;
}

View File

@@ -0,0 +1,12 @@
using System;
class C
{
public void M()
{
B b = new B();
b.Apply(0);
A2 a2 = new A2();
a2.Apply("");
}
}

View File

@@ -0,0 +1,52 @@
member_locations
| A.cs:3:23:3:26 | A<Int32> | A.cs:5:23:5:26 | Prop | A.cs:5:23:5:26 | A.cs:5:23:5:26 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:6:23:6:26 | Item | A.cs:6:23:6:26 | A.cs:6:23:6:26 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
| A.cs:3:23:3:26 | A<String> | A.cs:5:23:5:26 | Prop | A.cs:5:23:5:26 | A.cs:5:23:5:26 |
| A.cs:3:23:3:26 | A<String> | A.cs:6:23:6:26 | Item | A.cs:6:23:6:26 | A.cs:6:23:6:26 |
| A.cs:3:23:3:26 | A<String> | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A<String> | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A<String> | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
| A.cs:3:23:3:26 | A`1 | A.cs:5:23:5:26 | Prop | A.cs:5:23:5:26 | A.cs:5:23:5:26 |
| A.cs:3:23:3:26 | A`1 | A.cs:6:23:6:26 | Item | A.cs:6:23:6:26 | A.cs:6:23:6:26 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A`1 | A.cs:8:17:8:21 | Apply | A.cs:8:17:8:21 | A.cs:8:17:8:21 |
| A.cs:3:23:3:26 | A`1 | A.cs:9:28:9:35 | ToObject | A.cs:9:28:9:35 | A.cs:9:28:9:35 |
| A.cs:12:14:12:15 | A2 | A.cs:14:28:14:31 | Prop | A.cs:14:28:14:31 | A.cs:14:28:14:31 |
| A.cs:12:14:12:15 | A2 | A.cs:16:28:16:31 | Item | A.cs:16:28:16:31 | A.cs:16:28:16:31 |
| A.cs:12:14:12:15 | A2 | A.cs:22:40:22:44 | Event | A.cs:22:40:22:44 | A.cs:22:40:22:44 |
| A.cs:12:14:12:15 | A2 | A.cs:28:28:28:35 | ToObject | A.cs:28:28:28:35 | A.cs:28:28:28:35 |
| A.cs:12:14:12:15 | A2 | A.cs:30:17:30:17 | M | A.cs:30:17:30:17 | A.cs:30:17:30:17 |
| B.cs:3:14:3:14 | B | B.cs:5:25:5:28 | Prop | B.cs:5:25:5:28 | B.cs:5:25:5:28 |
| B.cs:3:14:3:14 | B | B.cs:7:25:7:28 | Item | B.cs:7:25:7:28 | B.cs:7:25:7:28 |
| B.cs:3:14:3:14 | B | B.cs:13:40:13:44 | Event | B.cs:13:40:13:44 | B.cs:13:40:13:44 |
| B.cs:3:14:3:14 | B | B.cs:19:28:19:35 | ToObject | B.cs:19:28:19:35 | B.cs:19:28:19:35 |
| C.cs:3:7:3:7 | C | C.cs:5:17:5:17 | M | C.cs:5:17:5:17 | C.cs:5:17:5:17 |
accessor_location
| A.cs:3:23:3:26 | A<Int32> | A.cs:5:30:5:32 | get_Prop | A.cs:5:30:5:32 | A.cs:5:30:5:32 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:6:41:6:43 | get_Item | A.cs:6:41:6:43 | A.cs:6:41:6:43 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A<Int32> | A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A<String> | A.cs:5:30:5:32 | get_Prop | A.cs:5:30:5:32 | A.cs:5:30:5:32 |
| A.cs:3:23:3:26 | A<String> | A.cs:6:41:6:43 | get_Item | A.cs:6:41:6:43 | A.cs:6:41:6:43 |
| A.cs:3:23:3:26 | A<String> | A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
| A.cs:3:23:3:26 | A<String> | A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A<String> | A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A`1 | A.cs:5:30:5:32 | get_Prop | A.cs:5:30:5:32 | A.cs:5:30:5:32 |
| A.cs:3:23:3:26 | A`1 | A.cs:6:41:6:43 | get_Item | A.cs:6:41:6:43 | A.cs:6:41:6:43 |
| A.cs:3:23:3:26 | A`1 | A.cs:6:46:6:48 | set_Item | A.cs:6:46:6:48 | A.cs:6:46:6:48 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | add_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:3:23:3:26 | A`1 | A.cs:7:40:7:44 | remove_Event | A.cs:7:40:7:44 | A.cs:7:40:7:44 |
| A.cs:12:14:12:15 | A2 | A.cs:14:36:14:37 | get_Prop | A.cs:14:36:14:37 | A.cs:14:36:14:37 |
| A.cs:12:14:12:15 | A2 | A.cs:18:9:18:11 | get_Item | A.cs:18:9:18:11 | A.cs:18:9:18:11 |
| A.cs:12:14:12:15 | A2 | A.cs:19:9:19:11 | set_Item | A.cs:19:9:19:11 | A.cs:19:9:19:11 |
| A.cs:12:14:12:15 | A2 | A.cs:24:9:24:11 | add_Event | A.cs:24:9:24:11 | A.cs:24:9:24:11 |
| A.cs:12:14:12:15 | A2 | A.cs:25:9:25:14 | remove_Event | A.cs:25:9:25:14 | A.cs:25:9:25:14 |
| B.cs:3:14:3:14 | B | B.cs:5:33:5:33 | get_Prop | B.cs:5:33:5:33 | B.cs:5:33:5:33 |
| B.cs:3:14:3:14 | B | B.cs:9:9:9:11 | get_Item | B.cs:9:9:9:11 | B.cs:9:9:9:11 |
| B.cs:3:14:3:14 | B | B.cs:10:9:10:11 | set_Item | B.cs:10:9:10:11 | B.cs:10:9:10:11 |
| B.cs:3:14:3:14 | B | B.cs:15:9:15:11 | add_Event | B.cs:15:9:15:11 | B.cs:15:9:15:11 |
| B.cs:3:14:3:14 | B | B.cs:16:9:16:14 | remove_Event | B.cs:16:9:16:14 | B.cs:16:9:16:14 |

View File

@@ -0,0 +1,14 @@
import csharp
query predicate member_locations(Type t, Member m, SourceLocation l) {
t = m.getDeclaringType() and
l = m.getLocation() and
not l instanceof EmptyLocation and
not m instanceof Constructor
}
query predicate accessor_location(Type t, Accessor a, SourceLocation l) {
t = a.getDeclaringType() and
l = a.getLocation() and
not l instanceof EmptyLocation
}