Skip to content

Commit 431aa2c

Browse files
committed
Java: Add CompilationUnit.getATypeAvailableBySimpleName()
This predicate is mainly helpful for Javadoc queries and for queries which check whether the name of an element shadows another type.
1 parent 18a8a33 commit 431aa2c

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* Added the predicate `CompilationUnit.getATypeAvailableBySimpleName()`.

java/ql/lib/semmle/code/java/CompilationUnit.qll

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,50 @@ class CompilationUnit extends Element, File {
3131
*/
3232
Module getModule() { cumodule(this, result) }
3333

34+
/**
35+
* Gets a type which is available by its simple name in this compilation unit.
36+
* Reasons for this can be:
37+
* - The type is declared in this compilation unit as top-level type
38+
* - The type is imported
39+
* - The type is declared in the same package as this compilation unit
40+
* - The type is declared in the package `java.lang`
41+
*/
42+
ClassOrInterface getATypeAvailableBySimpleName() {
43+
// See "Shadowing", https://docs.oracle.com/javase/specs/jls/se17/html/jls-6.html#jls-6.4.1
44+
// Note: Currently the logic below does not consider shadowing and might have multiple results
45+
// with the same type name
46+
result.(TopLevelType).getCompilationUnit() = this
47+
or
48+
exists(ImportStaticTypeMember importDecl |
49+
importDecl.getCompilationUnit() = this and
50+
result = importDecl.getATypeImport()
51+
)
52+
or
53+
exists(ImportType importDecl |
54+
importDecl.getCompilationUnit() = this and
55+
result = importDecl.getImportedType()
56+
)
57+
or
58+
exists(ImportStaticOnDemand importDecl |
59+
importDecl.getCompilationUnit() = this and
60+
result = importDecl.getATypeImport()
61+
)
62+
or
63+
exists(ImportOnDemandFromType importDecl |
64+
importDecl.getCompilationUnit() = this and
65+
result = importDecl.getAnImport()
66+
)
67+
or
68+
exists(ImportOnDemandFromPackage importDecl |
69+
importDecl.getCompilationUnit() = this and
70+
result = importDecl.getAnImport()
71+
)
72+
or
73+
// From same package or java.lang, see https://docs.oracle.com/javase/specs/jls/se17/html/jls-7.html
74+
result.(TopLevelType).getPackage() = this.getPackage()
75+
or
76+
result.(TopLevelType).getPackage().hasName("java.lang")
77+
}
78+
3479
override string getAPrimaryQlClass() { result = "CompilationUnit" }
3580
}

java/ql/src/Advisory/Documentation/ImpossibleJavadocThrows.ql

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,18 @@
1111

1212
import java
1313

14-
RefType getTaggedType(ThrowsTag tag) {
14+
Class getTaggedType(ThrowsTag tag) {
1515
result.hasName(tag.getExceptionName()) and
16-
exists(ImportType i | i.getFile() = tag.getFile() | i.getImportedType() = result)
16+
result = tag.getFile().(CompilationUnit).getATypeAvailableBySimpleName()
1717
}
1818

19-
predicate canThrow(Callable callable, RefType exception) {
20-
exists(string uncheckedException |
21-
uncheckedException = "RuntimeException" or uncheckedException = "Error"
22-
|
23-
exception.getAnAncestor().hasQualifiedName("java.lang", uncheckedException)
24-
)
19+
predicate canThrow(Callable callable, Class exception) {
20+
exception instanceof UncheckedThrowableType
2521
or
2622
callable.getAnException().getType().getADescendant() = exception
2723
}
2824

29-
from ThrowsTag throwsTag, RefType thrownType, Callable docMethod
25+
from ThrowsTag throwsTag, Class thrownType, Callable docMethod
3026
where
3127
getTaggedType(throwsTag) = thrownType and
3228
docMethod.getDoc().getJavadoc().getAChild*() = throwsTag and

0 commit comments

Comments
 (0)