@@ -30,7 +30,9 @@ private AstNode publicApi() {
30
30
*/
31
31
private AstNode queryPredicate ( ) {
32
32
// result = query relation that is "transitively" imported by a .ql file.
33
- PathProblemQuery:: importsQueryRelation ( result ) .asFile ( ) .getExtension ( ) = "ql"
33
+ // PathProblemQuery::importsQueryRelation(result).asFile().getExtension() = "ql"
34
+ // any query predicate. Query predicates are usually meant to be used.
35
+ result .( Predicate ) .hasAnnotation ( "query" )
34
36
or
35
37
// the from-where-select
36
38
result instanceof Select
@@ -200,8 +202,9 @@ private AstNode benign() {
200
202
result instanceof BlockComment or
201
203
not exists ( result .toString ( ) ) or // <- invalid code
202
204
// cached-stages pattern
203
- result .( Module ) .getAMember ( ) .( ClasslessPredicate ) .getName ( ) = "forceStage" or
204
- result .( ClasslessPredicate ) .getName ( ) = "forceStage" or
205
+ result .( Module ) .getAMember ( ) .( ClasslessPredicate ) .getName ( ) =
206
+ [ "forceStage" , "forceCachingInSameStageforceCachingInSameStage" ] or
207
+ result .( ClasslessPredicate ) .getName ( ) = [ "forceStage" , "forceCachingInSameStage" ] or
205
208
result .getLocation ( ) .getFile ( ) .getBaseName ( ) = "Caching.qll" or
206
209
// sometimes contains dead code - ignore
207
210
result .getLocation ( ) .getFile ( ) .getRelativePath ( ) .matches ( "%/tutorials/%" ) or
@@ -235,20 +238,64 @@ private AstNode queryable() {
235
238
or
236
239
result instanceof TopLevel // toplevel is always alive.
237
240
or
241
+ result = hackyShouldBeTreatedAsAlive ( )
242
+ or
243
+ // The below prevents the query from being too loud. The files below contain a lot of unqueryable code.
244
+ // I think some of it is from some languages not using all features of a shared library, but I'm not sure (haven't look much into it).
245
+ result
246
+ .getLocation ( )
247
+ .getFile ( )
248
+ .getBaseName ( )
249
+ .matches ( [ "DataFlowImpl" , "SsaImplCommon" , "FlowSummary" ] + "%" )
250
+ or
238
251
// recurisve cases
239
252
result = aliveStep ( queryable ( ) )
240
253
}
241
254
255
+ // The benign cases are mostly
256
+ private AstNode benignUnqueryable ( ) {
257
+ result = benign ( ) or
258
+ // cached-stages pattern
259
+ // sometimes contains dead code - ignore
260
+ result .( Module ) .getName ( ) = "Debugging" or
261
+ result .getLocation ( ) .getFile ( ) = benignUnqueryableFile ( )
262
+ }
263
+
264
+ pragma [ noinline]
265
+ private File benignUnqueryableFile ( ) {
266
+ result .getAbsolutePath ( ) .matches ( "%/explore/%" ) or
267
+ result .getRelativePath ( ) .matches ( "%/tutorials/%" ) or
268
+ result .getRelativePath ( ) .matches ( "%/experimental/%" ) or
269
+ result .getBaseName ( ) =
270
+ [
271
+ "Expr.qll" , "TypeScript.qll" , "YAML.qll" , "Tokens.qll" , "Instruction.qll" , "Persistence.qll" ,
272
+ "ES2015Modules.qll"
273
+ ] or // lots of classes that exist for completeness
274
+ result .getBaseName ( ) = [ "CachedStages.qll" , "Caching.qll" , "tutorial.qll" ] or
275
+ result .getBaseName ( ) = "PrettyPrintAst.qll" or // it's dead code, but seems intentional
276
+ result .getBaseName ( ) = [ "CryptoAlgorithmNames.qll" , "SensitiveDataHeuristics.qll" ] or // not all langs use all the things
277
+ // some more identical files
278
+ result .getBaseName ( ) = "ReachableBlock.qll" or
279
+ // QL-for-QL tests contain plenty of unqueryable code on purpose
280
+ result .getAbsolutePath ( ) .matches ( "%/ql/ql/test%" )
281
+ }
282
+
242
283
/**
243
284
* Gets an AstNode that does not affect any query result.
244
285
* Is interresting as an quick-eval target to investigate dead code.
245
286
* (It is intentional that this predicate is a result of this predicate).
246
287
*/
247
- AstNode unQueryable ( string msg ) {
288
+ AstNode unQueryable ( ) {
248
289
not result = queryable ( ) and
249
290
not result = deprecated ( ) and
250
- not result = benign ( ) and
251
- not result .getParent ( ) = any ( AstNode node | not node = queryable ( ) ) and
252
- msg = result .getLocation ( ) .getFile ( ) .getBaseName ( ) and
253
- result .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) .matches ( "%/javascript/%" )
291
+ not result = benignUnqueryable ( ) and
292
+ not result .getParent ( ) = any ( AstNode node | not node = queryable ( ) )
254
293
}
294
+
295
+ AstNode unqueryableLang ( string lang ) {
296
+ lang = "/" + [ "cpp" , "csharp" , "java" , "javascript" , "python" , "ruby" ] + "/" and
297
+ result = unQueryable ( ) and
298
+ result .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) .matches ( "%" + lang + "%" )
299
+ }
300
+
301
+ int countLang ( string lang ) { result = strictcount ( unqueryableLang ( lang ) ) }
0 commit comments