Skip to content

Commit 37c40c5

Browse files
authored
Merge pull request github#10959 from igfoo/igfoo/diags
Java/Kotlin: Add a diagnostics consistency query
2 parents 52cd200 + 4050801 commit 37c40c5

File tree

32 files changed

+167
-15
lines changed

32 files changed

+167
-15
lines changed

java/kotlin-extractor/src/main/java/com/semmle/extractor/java/OdasaOutput.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, Tr
277277
// Only re-write an existing trap file if we encountered a newer version of the same class.
278278
TrapClassVersion trapVersion = readVersionInfo(trap);
279279
if (!currVersion.isValid()) {
280-
log.warn("Not rewriting trap file for: " + shortName + " " + trapVersion + " " + currVersion + " " + trap);
280+
log.trace("Not rewriting trap file for: " + shortName + " " + trapVersion + " " + currVersion + " " + trap);
281281
} else if (currVersion.newerThan(trapVersion)) {
282282
log.trace("Rewriting trap file for: " + shortName + " " + trapVersion + " " + currVersion + " " + trap);
283283
deleteTrapFileAndDependencies(sym, signature);
@@ -291,7 +291,7 @@ private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, Tr
291291
// If the TRAP file already exists then we
292292
// don't need to write it.
293293
if (trap.exists()) {
294-
log.warn("Not rewriting trap file for " + trap.toString() + " as it exists");
294+
log.trace("Not rewriting trap file for " + trap.toString() + " as it exists");
295295
return null;
296296
}
297297
// If the TRAP file was written in the past, and
@@ -301,7 +301,7 @@ private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, Tr
301301
File trapFileDir = trap.getParentFile();
302302
File trapOld = new File(trapFileDir, trap.getName().replace(".trap.gz", ".trap-old.gz"));
303303
if (trapOld.exists()) {
304-
log.warn("Not rewriting trap file for " + trap.toString() + " as the trap-old exists");
304+
log.trace("Not rewriting trap file for " + trap.toString() + " as the trap-old exists");
305305
return null;
306306
}
307307
// Otherwise, if any newer TRAP file has already
@@ -316,7 +316,7 @@ private TrapFileManager getMembersWriterForDecl(File trap, File trapFileBase, Tr
316316
if (m.matches() && m.group(1).equals(trapFileBaseName)) {
317317
TrapClassVersion v = new TrapClassVersion(Integer.valueOf(m.group(2)), Integer.valueOf(m.group(3)), Long.valueOf(m.group(4)), m.group(5));
318318
if (v.newerThan(trapFileVersion)) {
319-
log.warn("Not rewriting trap file for " + trap.toString() + " as " + f.toString() + " exists");
319+
log.trace("Not rewriting trap file for " + trap.toString() + " as " + f.toString() + " exists");
320320
return null;
321321
}
322322
}

java/ql/consistency-queries/diags.ql

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import semmle.code.java.Diagnostics
2+
3+
/*
4+
* This query fails if any unexpected diagnostics are recorded in the
5+
* database. By putting
6+
* // Diagnostic Matches: PAT
7+
* in any source files, you can declare that diagnostics matching PAT
8+
* (in the string.matches(string) sense) are expected.
9+
*/
10+
11+
class DiagnosticException extends Top {
12+
string pattern;
13+
14+
DiagnosticException() {
15+
this.(KtComment).getText() = "// Diagnostic Matches: " + pattern
16+
or
17+
this.(Javadoc).toString() = "// Diagnostic Matches: " + pattern
18+
}
19+
20+
Diagnostic getException() { diagnosticMessage(result).matches(pattern) }
21+
}
22+
23+
string diagnosticMessage(Diagnostic d) {
24+
if d.getFullMessage() != "" then result = d.getFullMessage() else result = d.getMessage()
25+
}
26+
27+
// Check that there aren't any old DiagnosticExceptions left after
28+
// something is fixed.
29+
query predicate unusedDiagnosticException(DiagnosticException de) { not exists(de.getException()) }
30+
31+
query predicate unexpectedDiagnostic(Diagnostic d, string s) {
32+
s = diagnosticMessage(d) and
33+
not d = any(DiagnosticException de).getException()
34+
}
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
| CodeQL Kotlin extractor | 2 | | IrProperty without a getter | d.kt:0:0:0:0 | d.kt:0:0:0:0 |
2-
| CodeQL Kotlin extractor | 2 | | Not rewriting trap file for test-db/trap/java/classes/java/lang/Boolean.members/Boolean.members<VERSION>-<MODIFIED>-kotlin.trap.gz as it exists | file://:0:0:0:0 | file://:0:0:0:0 |
3-
| CodeQL Kotlin extractor | 2 | | Not rewriting trap file for test-db/trap/java/classes/kotlin/Boolean.members/Boolean.members<VERSION>-<MODIFIED>-null.trap.gz as it exists | file://:0:0:0:0 | file://:0:0:0:0 |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11

22
annotation class SomeAnnotation
33

4+
// Diagnostic Matches: Incomplete annotation: @kotlin.Metadata(%)
5+
// Diagnostic Matches: Unknown location for kotlin.Metadata

java/ql/test/kotlin/library-tests/annotations/jvmName/test.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,12 @@ class X {
1515

1616
annotation class Ann(
1717
val p: Int,
18-
@get:JvmName("w") val q: Int)
18+
@get:JvmName("w") val q: Int)
19+
20+
// Diagnostic Matches: Incomplete annotation: @kotlin.Metadata(%)
21+
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="changeY")
22+
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="getX_prop")
23+
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="method")
24+
// Diagnostic Matches: Incomplete annotation: @kotlin.jvm.JvmName(name="y")
25+
// Diagnostic Matches: Unknown location for kotlin.Metadata
26+
// Diagnostic Matches: Unknown location for kotlin.jvm.JvmName

java/ql/test/kotlin/library-tests/arrays-with-variances/takesArrayList.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,8 @@ public class TakesArrayList {
110110
fun inInArrayComparableAny(c: Comparable<Array<in Array<in Any>>>) { }
111111

112112
}
113+
114+
// Diagnostic Matches: Incomplete annotation: @kotlin.Metadata(%)
115+
// Diagnostic Matches: Unknown location for kotlin.Metadata
116+
// Diagnostic Matches: Completion failure for type: org.jetbrains.annotations.NotNull
117+
// Diagnostic Matches: Unknown location for org.jetbrains.annotations.NotNull

java/ql/test/kotlin/library-tests/comments/comments.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ comments
1515
| comments.kt:71:9:73:11 | /**\n * An anonymous function comment\n */ | /**\n * An anonymous function comment\n */ |
1616
| comments.kt:79:9:81:11 | /**\n * A local function comment\n */ | /**\n * A local function comment\n */ |
1717
| comments.kt:88:10:90:11 | /**\n * An anonymous object comment\n */ | /**\n * An anonymous object comment\n */ |
18+
| comments.kt:95:1:95:163 | // Diagnostic Matches: % Couldn't get owner of KDoc. The comment is extracted without an owner. ...while extracting a file (comments.kt) at %comments.kt:1:1:96:0% | // Diagnostic Matches: % Couldn't get owner of KDoc. The comment is extracted without an owner. ...while extracting a file (comments.kt) at %comments.kt:1:1:96:0% |
1819
commentOwners
1920
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
2021
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | comments.kt:12:1:31:1 | Group |
@@ -39,6 +40,7 @@ commentNoOwners
3940
| comments.kt:1:1:1:25 | /** Kdoc with no owner */ |
4041
| comments.kt:24:9:24:25 | // A line comment |
4142
| comments.kt:28:5:30:6 | /*\n A block comment\n */ |
43+
| comments.kt:95:1:95:163 | // Diagnostic Matches: % Couldn't get owner of KDoc. The comment is extracted without an owner. ...while extracting a file (comments.kt) at %comments.kt:1:1:96:0% |
4244
commentSections
4345
| comments.kt:1:1:1:25 | /** Kdoc with no owner */ | Kdoc with no owner |
4446
| comments.kt:4:1:11:3 | /**\n * A group of *members*.\n *\n * This class has no useful logic; it's just a documentation example.\n *\n * @property name the name of this group.\n * @constructor Creates an empty group.\n */ | A group of *members*.\n\nThis class has no useful logic; it's just a documentation example.\n\n |

java/ql/test/kotlin/library-tests/comments/comments.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@ class XX {
9090
*/
9191
X() {
9292
}
93-
}
93+
}
94+
95+
// Diagnostic Matches: % Couldn't get owner of KDoc. The comment is extracted without an owner. ...while extracting a file (comments.kt) at %comments.kt:1:1:96:0%

java/ql/test/kotlin/library-tests/controlflow/basic/Test.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,5 @@ fun fn_when(x: Boolean, y: Boolean) {
122122
else -> false
123123
} -> { } }
124124
}
125+
126+
// Diagnostic Matches: % Couldn't find a Java equivalent function to kotlin.Int.dec in java.lang.Integer ...while extracting a call (<no name>) at %Test.kt:40:4:40:6%

java/ql/test/kotlin/library-tests/controlflow/dominance/Test.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,5 @@ TODO
9898
}
9999

100100
}
101+
102+
// Diagnostic Matches: % Couldn't find a Java equivalent function to kotlin.Int.dec in java.lang.Integer ...while extracting a call (<no name>) at %Test.kt:40:4:40:6%

0 commit comments

Comments
 (0)