Skip to content

Commit 7c5b186

Browse files
committed
Ruby/QL: add discard predicates for locations
1 parent f714e5c commit 7c5b186

File tree

4 files changed

+118
-3
lines changed

4 files changed

+118
-3
lines changed

ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ import codeql.Locations as L
99
overlay[local]
1010
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }
1111

12+
/** Holds if `loc` is in the `file` and is part of the overlay base database. */
13+
overlay[local]
14+
private predicate discardableLocation(@file file, @location_default loc) {
15+
not isOverlay() and locations_default(loc, file, _, _, _, _)
16+
}
17+
18+
/** Holds if `loc` should be discarded, because it is part of the overlay base and is in a file that was also extracted as part of the overlay database. */
19+
overlay[discard_entity]
20+
private predicate discardLocation(@location_default loc) {
21+
exists(@file file, string path | files(file, path) |
22+
discardableLocation(file, loc) and overlayChangedFiles(path)
23+
)
24+
}
25+
1226
module QL {
1327
/** The base class for all AST nodes */
1428
class AstNode extends @ql_ast_node {

ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,20 @@ import codeql.Locations as L
99
overlay[local]
1010
private predicate isOverlay() { databaseMetadata("isOverlay", "true") }
1111

12+
/** Holds if `loc` is in the `file` and is part of the overlay base database. */
13+
overlay[local]
14+
private predicate discardableLocation(@file file, @location_default loc) {
15+
not isOverlay() and locations_default(loc, file, _, _, _, _)
16+
}
17+
18+
/** Holds if `loc` should be discarded, because it is part of the overlay base and is in a file that was also extracted as part of the overlay database. */
19+
overlay[discard_entity]
20+
private predicate discardLocation(@location_default loc) {
21+
exists(@file file, string path | files(file, path) |
22+
discardableLocation(file, loc) and overlayChangedFiles(path)
23+
)
24+
}
25+
1226
module Ruby {
1327
/** The base class for all AST nodes */
1428
class AstNode extends @ruby_ast_node {

shared/tree-sitter-extractor/src/generator/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ pub fn generate(
5151

5252
ql::write(
5353
&mut ql_writer,
54-
&[ql::TopLevel::Predicate(
55-
ql_gen::create_is_overlay_predicate(),
56-
)],
54+
&[
55+
ql::TopLevel::Predicate(ql_gen::create_is_overlay_predicate()),
56+
ql::TopLevel::Predicate(ql_gen::create_discardable_location_predicate()),
57+
ql::TopLevel::Predicate(ql_gen::create_discard_location_predicate()),
58+
],
5759
)?;
5860

5961
for language in languages {

shared/tree-sitter-extractor/src/generator/ql_gen.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,91 @@ pub fn create_discard_ast_node_predicate(ast_node_name: &str) -> ql::Predicate {
396396
}
397397
}
398398

399+
pub fn create_discardable_location_predicate() -> ql::Predicate<'static> {
400+
ql::Predicate {
401+
name: "discardableLocation",
402+
qldoc: Some(String::from(
403+
"Holds if `loc` is in the `file` and is part of the overlay base database.",
404+
)),
405+
overridden: false,
406+
is_private: true,
407+
is_final: false,
408+
overlay: Some(ql::OverlayAnnotation::Local),
409+
return_type: None,
410+
formal_parameters: vec![
411+
ql::FormalParameter {
412+
name: "file",
413+
param_type: ql::Type::At("file"),
414+
},
415+
ql::FormalParameter {
416+
name: "loc",
417+
param_type: ql::Type::At("location_default"),
418+
},
419+
],
420+
body: ql::Expression::And(vec![
421+
ql::Expression::Negation(Box::new(ql::Expression::Pred("isOverlay", vec![]))),
422+
ql::Expression::Pred(
423+
"locations_default",
424+
vec![
425+
ql::Expression::Var("loc"),
426+
ql::Expression::Var("file"),
427+
ql::Expression::Var("_"),
428+
ql::Expression::Var("_"),
429+
ql::Expression::Var("_"),
430+
ql::Expression::Var("_"),
431+
],
432+
),
433+
]),
434+
}
435+
}
436+
437+
/// Creates a discard predicate for `@location_default` entities. This is necessary because the
438+
/// tree-sitter extractors use `*` IDs for locations, which means that locations don't get shared
439+
/// between the base and overlay databases.
440+
pub fn create_discard_location_predicate() -> ql::Predicate<'static> {
441+
ql::Predicate {
442+
name: "discardLocation",
443+
qldoc: Some(String::from(
444+
"Holds if `loc` should be discarded, because it is part of the overlay base \
445+
and is in a file that was also extracted as part of the overlay database.",
446+
)),
447+
overridden: false,
448+
is_private: true,
449+
is_final: false,
450+
overlay: Some(ql::OverlayAnnotation::DiscardEntity),
451+
return_type: None,
452+
formal_parameters: vec![ql::FormalParameter {
453+
name: "loc",
454+
param_type: ql::Type::At("location_default"),
455+
}],
456+
body: ql::Expression::Aggregate {
457+
name: "exists",
458+
vars: vec![
459+
ql::FormalParameter {
460+
name: "file",
461+
param_type: ql::Type::At("file"),
462+
},
463+
ql::FormalParameter {
464+
name: "path",
465+
param_type: ql::Type::String,
466+
},
467+
],
468+
range: Some(Box::new(ql::Expression::Pred(
469+
"files",
470+
vec![ql::Expression::Var("file"), ql::Expression::Var("path")],
471+
))),
472+
expr: Box::new(ql::Expression::And(vec![
473+
ql::Expression::Pred(
474+
"discardableLocation",
475+
vec![ql::Expression::Var("file"), ql::Expression::Var("loc")],
476+
),
477+
ql::Expression::Pred("overlayChangedFiles", vec![ql::Expression::Var("path")]),
478+
])),
479+
second_expr: None,
480+
},
481+
}
482+
}
483+
399484
/// Returns an expression to get a field that's defined as a column in the parent's table.
400485
///
401486
/// # Arguments

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy