Skip to content

Commit b48b5d4

Browse files
authored
Merge pull request #10498 from Marcono1234/marcono1234/compilation-unit-simple-name-type
Java: Add `CompilationUnit.getATypeInScope()`
2 parents a48b893 + c40b628 commit b48b5d4

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-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.getATypeInScope()`.

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

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

34+
/**
35+
* Gets a type which is available in the top-level scope of this compilation unit.
36+
* This can be a type:
37+
* - declared in this compilation unit as top-level type
38+
* - imported with an `import` declaration
39+
* - declared in the same package as this compilation unit
40+
* - declared in the package `java.lang`
41+
*
42+
* This predicate not consider "shadowing", it can have types as result whose simple name is
43+
* shadowed by another type in scope.
44+
*/
45+
ClassOrInterface getATypeInScope() {
46+
// See "Shadowing", https://docs.oracle.com/javase/specs/jls/se17/html/jls-6.html#jls-6.4.1
47+
// Currently shadowing is not considered
48+
result.(TopLevelType).getCompilationUnit() = this
49+
or
50+
exists(Import importDecl | importDecl.getCompilationUnit() = this |
51+
result =
52+
[
53+
importDecl.(ImportStaticTypeMember).getATypeImport(),
54+
importDecl.(ImportType).getImportedType(),
55+
importDecl.(ImportStaticOnDemand).getATypeImport(),
56+
importDecl.(ImportOnDemandFromType).getAnImport(),
57+
importDecl.(ImportOnDemandFromPackage).getAnImport(),
58+
]
59+
)
60+
or
61+
// From same package or java.lang, see https://docs.oracle.com/javase/specs/jls/se17/html/jls-7.html
62+
result.(TopLevelType).getPackage() = this.getPackage()
63+
or
64+
result.(TopLevelType).getPackage().hasName("java.lang")
65+
}
66+
3467
override string getAPrimaryQlClass() { result = "CompilationUnit" }
3568
}

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

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

1212
import java
1313

14-
RefType getTaggedType(ThrowsTag tag) {
14+
ClassOrInterface 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).getATypeInScope()
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+
// Uses ClassOrInterface as type for thrownType to also cover case where erroneously an interface
26+
// type is declared as thrown exception
27+
from ThrowsTag throwsTag, ClassOrInterface thrownType, Callable docMethod
3028
where
3129
getTaggedType(throwsTag) = thrownType and
3230
docMethod.getDoc().getJavadoc().getAChild*() = throwsTag and
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
| ImpossibleJavadocThrows.java:9:5:9:12 | @throws | Javadoc for bad1 claims to throw InterruptedException but this is impossible. |
22
| ImpossibleJavadocThrows.java:16:5:16:15 | @exception | Javadoc for bad2 claims to throw Exception but this is impossible. |
3+
| ImpossibleJavadocThrows.java:23:5:23:12 | @throws | Javadoc for bad3 claims to throw Runnable but this is impossible. |

java/ql/test/query-tests/Javadoc/ImpossibleJavadocThrows.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ public void bad1() {
1818
public void bad2() {
1919
}
2020

21+
/**
22+
*
23+
* @throws Runnable
24+
*/
25+
public void bad3() {
26+
}
27+
2128
/**
2229
*
2330
* @throws InterruptedException

0 commit comments

Comments
 (0)