Merge pull request #10498 from Marcono1234/marcono1234/compilation-unit-simple-name-type

Java: Add `CompilationUnit.getATypeInScope()`
This commit is contained in:
Anders Schack-Mulligen
2022-09-28 13:18:29 +02:00
committed by GitHub
5 changed files with 52 additions and 9 deletions

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Added the predicate `CompilationUnit.getATypeInScope()`.

View File

@@ -31,5 +31,38 @@ class CompilationUnit extends Element, File {
*/
Module getModule() { cumodule(this, result) }
/**
* Gets a type which is available in the top-level scope of this compilation unit.
* This can be a type:
* - declared in this compilation unit as top-level type
* - imported with an `import` declaration
* - declared in the same package as this compilation unit
* - declared in the package `java.lang`
*
* This predicate not consider "shadowing", it can have types as result whose simple name is
* shadowed by another type in scope.
*/
ClassOrInterface getATypeInScope() {
// See "Shadowing", https://docs.oracle.com/javase/specs/jls/se17/html/jls-6.html#jls-6.4.1
// Currently shadowing is not considered
result.(TopLevelType).getCompilationUnit() = this
or
exists(Import importDecl | importDecl.getCompilationUnit() = this |
result =
[
importDecl.(ImportStaticTypeMember).getATypeImport(),
importDecl.(ImportType).getImportedType(),
importDecl.(ImportStaticOnDemand).getATypeImport(),
importDecl.(ImportOnDemandFromType).getAnImport(),
importDecl.(ImportOnDemandFromPackage).getAnImport(),
]
)
or
// From same package or java.lang, see https://docs.oracle.com/javase/specs/jls/se17/html/jls-7.html
result.(TopLevelType).getPackage() = this.getPackage()
or
result.(TopLevelType).getPackage().hasName("java.lang")
}
override string getAPrimaryQlClass() { result = "CompilationUnit" }
}

View File

@@ -11,22 +11,20 @@
import java
RefType getTaggedType(ThrowsTag tag) {
ClassOrInterface getTaggedType(ThrowsTag tag) {
result.hasName(tag.getExceptionName()) and
exists(ImportType i | i.getFile() = tag.getFile() | i.getImportedType() = result)
result = tag.getFile().(CompilationUnit).getATypeInScope()
}
predicate canThrow(Callable callable, RefType exception) {
exists(string uncheckedException |
uncheckedException = "RuntimeException" or uncheckedException = "Error"
|
exception.getAnAncestor().hasQualifiedName("java.lang", uncheckedException)
)
predicate canThrow(Callable callable, Class exception) {
exception instanceof UncheckedThrowableType
or
callable.getAnException().getType().getADescendant() = exception
}
from ThrowsTag throwsTag, RefType thrownType, Callable docMethod
// Uses ClassOrInterface as type for thrownType to also cover case where erroneously an interface
// type is declared as thrown exception
from ThrowsTag throwsTag, ClassOrInterface thrownType, Callable docMethod
where
getTaggedType(throwsTag) = thrownType and
docMethod.getDoc().getJavadoc().getAChild*() = throwsTag and

View File

@@ -1,2 +1,3 @@
| ImpossibleJavadocThrows.java:9:5:9:12 | @throws | Javadoc for bad1 claims to throw InterruptedException but this is impossible. |
| ImpossibleJavadocThrows.java:16:5:16:15 | @exception | Javadoc for bad2 claims to throw Exception but this is impossible. |
| ImpossibleJavadocThrows.java:23:5:23:12 | @throws | Javadoc for bad3 claims to throw Runnable but this is impossible. |

View File

@@ -18,6 +18,13 @@ class ImpossibleJavadocThrows {
public void bad2() {
}
/**
*
* @throws Runnable
*/
public void bad3() {
}
/**
*
* @throws InterruptedException