Skip to content

Commit

Permalink
Merge pull request #18166 from tamasvajk/fix/db-quality-query-2
Browse files Browse the repository at this point in the history
C#: Fix calls with no target in DB quality query
  • Loading branch information
tamasvajk authored Dec 2, 2024
2 parents f56e337 + b8fd20e commit 8375c49
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 6 deletions.
20 changes: 16 additions & 4 deletions csharp/ql/src/Telemetry/DatabaseQuality.qll
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,36 @@ module CallTargetStats implements StatsSig {
)
}

private predicate isInitializedWithCollectionInitializer(PropertyCall c) {
private predicate isInitializedWithObjectOrCollectionInitializer(PropertyCall c) {
exists(Property p, AssignExpr assign |
p = c.getProperty() and
assign = c.getParent() and
assign.getLValue() = c and
assign.getRValue() instanceof CollectionInitializer
assign.getRValue() instanceof ObjectOrCollectionInitializer
)
}

private predicate isEventFieldAccess(EventCall c) {
exists(Event e | c.getEvent() = e |
forall(Accessor a | e.getAnAccessor() = a | a.isCompilerGenerated())
)
}

private predicate isTypeParameterInstantiation(ObjectCreation e) {
e.getType() instanceof TypeParameter
}

additional predicate isNotOkCall(Call c) {
not exists(c.getTarget()) and
not c instanceof DelegateCall and
not c instanceof DynamicExpr and
not isNoSetterPropertyCallInConstructor(c) and
not isNoSetterPropertyInitialization(c) and
not isAnonymousObjectMemberDeclaration(c) and
not isInitializedWithCollectionInitializer(c) and
not c.getParent+() instanceof NameOfExpr
not isInitializedWithObjectOrCollectionInitializer(c) and
not c.getParent+() instanceof NameOfExpr and
not isEventFieldAccess(c) and
not isTypeParameterInstantiation(c)
}

int getNumberOfNotOk() { result = count(Call c | isNotOkCall(c)) }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
| Quality.cs:32:9:32:21 | access to indexer | Call without target $@. | Quality.cs:32:9:32:21 | access to indexer | access to indexer |
| Quality.cs:34:21:34:25 | object creation of type null | Call without target $@. | Quality.cs:34:21:34:25 | object creation of type null | object creation of type null |
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@
| Quality.cs:15:24:15:34 | access to property MyProperty3 | Call without target $@. | Quality.cs:15:24:15:34 | access to property MyProperty3 | access to property MyProperty3 |
| Quality.cs:15:24:15:46 | access to property MyProperty2 | Call without target $@. | Quality.cs:15:24:15:46 | access to property MyProperty2 | access to property MyProperty2 |
| Quality.cs:19:13:19:23 | access to property MyProperty4 | Call without target $@. | Quality.cs:19:13:19:23 | access to property MyProperty4 | access to property MyProperty4 |
| Quality.cs:24:16:24:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:24:16:24:26 | access to property MyProperty2 | access to property MyProperty2 |
| Quality.cs:20:13:20:23 | access to property MyProperty6 | Call without target $@. | Quality.cs:20:13:20:23 | access to property MyProperty6 | access to property MyProperty6 |
| Quality.cs:23:9:23:14 | access to event Event1 | Call without target $@. | Quality.cs:23:9:23:14 | access to event Event1 | access to event Event1 |
| Quality.cs:23:9:23:30 | delegate call | Call without target $@. | Quality.cs:23:9:23:30 | delegate call | delegate call |
| Quality.cs:26:19:26:26 | access to indexer | Call without target $@. | Quality.cs:26:19:26:26 | access to indexer | access to indexer |
| Quality.cs:29:21:29:27 | access to indexer | Call without target $@. | Quality.cs:29:21:29:27 | access to indexer | access to indexer |
| Quality.cs:32:9:32:21 | access to indexer | Call without target $@. | Quality.cs:32:9:32:21 | access to indexer | access to indexer |
| Quality.cs:34:21:34:25 | object creation of type null | Call without target $@. | Quality.cs:34:21:34:25 | object creation of type null | object creation of type null |
| Quality.cs:38:16:38:26 | access to property MyProperty2 | Call without target $@. | Quality.cs:38:16:38:26 | access to property MyProperty2 | access to property MyProperty2 |
| Quality.cs:50:20:50:26 | object creation of type T | Call without target $@. | Quality.cs:50:20:50:26 | object creation of type T | object creation of type T |
32 changes: 31 additions & 1 deletion csharp/ql/test/query-tests/Telemetry/DatabaseQuality/Quality.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,43 @@ public Test()

new Test()
{
MyProperty4 = { 1, 2, 3 }
MyProperty4 = { 1, 2, 3 },
MyProperty6 = { [1] = "" }
};

Event1.Invoke(this, 5);

var str = "abcd";
var sub = str[..3]; // TODO: this is not an indexer call, but rather a `str.Substring(0, 3)` call.

Span<int> sp = null;
var slice = sp[..3]; // TODO: this is not an indexer call, but rather a `sp.Slice(0, 3)` call.

Span<byte> guidBytes = stackalloc byte[16];
guidBytes[08] = 1; // TODO: this indexer call has no target, because the target is a `ref` returning getter.

new MyList([new(), new Test()]); // TODO: the `new()` call has no target, which is unexpected, as we know at compile time, that this is a `new Test()` call.
}

public int MyProperty1 { get; }
public int MyProperty2 { get; } = 42;
public Test MyProperty3 { get; set; }
public List<int> MyProperty4 { get; }
static int MyProperty5 { get; }
public Dictionary<int, string> MyProperty6 { get; }

public event EventHandler<int> Event1;

class Gen<T> where T : new()
{
public static T Factory()
{
return new T();
}
}

class MyList
{
public MyList(IEnumerable<Test> init) { }
}
}

0 comments on commit 8375c49

Please sign in to comment.