Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ql/extractor/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub fn run(options: Options) -> std::io::Result<()> {
languages,
options.dbscheme,
options.library,
false, // do not use facade AST
"run 'scripts/create-extractor-pack.sh' in ql/",
)
}
1,336 changes: 914 additions & 422 deletions ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions ruby/extractor/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub fn run(options: Options) -> std::io::Result<()> {
languages,
options.dbscheme,
options.library,
false, // do not use facade AST
"run 'make dbscheme' in ql/ruby/",
)
}
1,428 changes: 970 additions & 458 deletions ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll

Large diffs are not rendered by default.

100 changes: 87 additions & 13 deletions shared/tree-sitter-extractor/src/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub fn generate(
languages: Vec<language::Language>,
dbscheme_path: PathBuf,
ql_library_path: PathBuf,
use_facade_ast: bool,
regenerate_instructions: &str,
) -> std::io::Result<()> {
let dbscheme_file = File::create(dbscheme_path).map_err(|e| {
Expand Down Expand Up @@ -47,6 +48,7 @@ pub fn generate(
ql::write(
&mut ql_writer,
&[ql::TopLevel::Import(ql::Import {
is_private: false,
module: "codeql.Locations",
alias: Some("L"),
})],
Expand Down Expand Up @@ -122,17 +124,35 @@ pub fn generate(

let mut body = vec![];

for c in ql_gen::create_ast_node_class(
let facade_import_name = if use_facade_ast {
format!("FacadeAst::{}", &language.name)
} else {
language.name.clone() // If not using a facade AST, treat the module itself as the facade module.
};
if use_facade_ast {
body.push(ql::TopLevel::Import(ql::Import {
is_private: true,
module: &facade_import_name,
alias: Some("F"),
}));
} else {
body.push(ql::TopLevel::ModuleAlias(ql::ModuleAlias {
is_private: true,
name: "F",
target: &language.name,
}));
}

body.push(ql::TopLevel::Class(ql_gen::create_ast_node_class(
&ast_node_name,
&node_location_table_name,
&node_parent_table_name,
) {
body.push(ql::TopLevel::Class(c));
}
)));

for c in ql_gen::create_token_class(&token_name, &tokeninfo_name) {
body.push(ql::TopLevel::Class(c));
}
body.push(ql::TopLevel::Class(ql_gen::create_token_class(
&token_name,
&tokeninfo_name,
)));

if has_trivia_tokens {
body.push(ql::TopLevel::Class(ql_gen::create_trivia_token_class(
Expand Down Expand Up @@ -166,14 +186,68 @@ pub fn generate(

body.append(&mut ql_gen::convert_nodes(&nodes));
body.push(ql_gen::create_print_ast_module(&nodes));
let mut final_body = if use_facade_ast {
vec![
ql::TopLevel::Import(ql::Import {
is_private: true,
module: &facade_import_name,
alias: Some("F"),
}),
ql::TopLevel::Import(ql::Import {
is_private: false,
module: "F",
alias: None,
}),
]
} else {
vec![
ql::TopLevel::ModuleAlias(ql::ModuleAlias {
is_private: true,
name: "F",
target: &language.name,
}),
ql::TopLevel::Import(ql::Import {
is_private: false,
module: "F",
alias: None,
}),
]
};
let final_aliases = body
.iter()
.filter_map(|decl| match decl {
ql::TopLevel::Class(c) => Some(ql::TopLevel::Class(ql::Class {
qldoc: None,
name: c.name,
is_abstract: false,
is_final: true,
is_private: false,
supertypes: Set::new(),
characteristic_predicate: None,
predicates: vec![],
alias: Some(format!("F::{}", c.name)),
})),
_ => None,
})
.collect::<Vec<_>>();
final_body.extend(final_aliases);
let final_module_name = format!("{}Final", language.name);
ql::write(
&mut ql_writer,
&[ql::TopLevel::Module(ql::Module {
qldoc: None,
name: &language.name,
body,
overlay: Some(ql::OverlayAnnotation::Local),
})],
&[
ql::TopLevel::Module(ql::Module {
qldoc: None,
name: &language.name,
body,
overlay: Some(ql::OverlayAnnotation::Local),
}),
ql::TopLevel::Module(ql::Module {
qldoc: None,
name: &final_module_name,
body: final_body,
overlay: None,
}),
],
)?;
}
Ok(())
Expand Down
26 changes: 26 additions & 0 deletions shared/tree-sitter-extractor/src/generator/ql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::fmt;
pub enum TopLevel<'a> {
Class(Class<'a>),
Import(Import<'a>),
ModuleAlias(ModuleAlias<'a>),
Module(Module<'a>),
Predicate(Predicate<'a>),
}
Expand All @@ -14,20 +15,41 @@ impl fmt::Display for TopLevel<'_> {
match self {
TopLevel::Import(imp) => write!(f, "{imp}"),
TopLevel::Class(cls) => write!(f, "{cls}"),
TopLevel::ModuleAlias(alias) => write!(f, "{alias}"),
TopLevel::Module(m) => write!(f, "{m}"),
TopLevel::Predicate(pred) => write!(f, "{pred}"),
}
}
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ModuleAlias<'a> {
pub is_private: bool,
pub name: &'a str,
pub target: &'a str,
}

impl fmt::Display for ModuleAlias<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_private {
write!(f, "private ")?;
}
write!(f, "module {} = {};", self.name, self.target)
}
}

#[derive(Clone, Eq, PartialEq, Hash)]
pub struct Import<'a> {
pub is_private: bool,
pub module: &'a str,
pub alias: Option<&'a str>,
}

impl fmt::Display for Import<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_private {
write!(f, "private ")?;
}
write!(f, "import {}", &self.module)?;
if let Some(name) = &self.alias {
write!(f, " as {name}")?;
Expand Down Expand Up @@ -146,6 +168,9 @@ pub enum Type<'a> {

/// A user-defined type.
Normal(&'a str),

/// A normal type with an `F::` prefix.
Facade(&'a str),
}

impl fmt::Display for Type<'_> {
Expand All @@ -155,6 +180,7 @@ impl fmt::Display for Type<'_> {
Type::String => write!(f, "string"),
Type::Normal(name) => write!(f, "{name}"),
Type::At(name) => write!(f, "@{name}"),
Type::Facade(name) => write!(f, "F::{name}"),
}
}
}
Expand Down
Loading
Loading