diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/bleeding-codeql-analysis.yml similarity index 96% rename from .github/workflows/codeql-analysis.yml rename to .github/workflows/bleeding-codeql-analysis.yml index 664bfde89bf..115b145fc42 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/bleeding-codeql-analysis.yml @@ -1,4 +1,4 @@ -name: "CodeQL" +name: "CodeQL with bleeding edge queries and extractor" on: workflow_dispatch: @@ -62,7 +62,7 @@ jobs: - name: Release build run: cargo build --release - name: Generate dbscheme - run: target/release/ql-generator + run: target/release/ql-generator --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll - uses: actions/upload-artifact@v2 with: name: ql.dbscheme diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4759f095fe..674821b85b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: run: cargo build --release - name: Generate dbscheme if: ${{ matrix.os == 'ubuntu-latest' }} - run: target/release/ql-generator + run: target/release/ql-generator --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll - uses: actions/upload-artifact@v2 if: ${{ matrix.os == 'ubuntu-latest' }} with: diff --git a/.github/workflows/dataset_measure.yml b/.github/workflows/dataset_measure.yml index 594daf701ab..bbf25377cd7 100644 --- a/.github/workflows/dataset_measure.yml +++ b/.github/workflows/dataset_measure.yml @@ -73,7 +73,7 @@ jobs: path: stats - run: | python -m pip install --user lxml - find stats -name 'stats.xml' | sort | xargs python scripts/merge_stats.py --output ql/src/ql.dbscheme.stats --normalise tokeninfo + find stats -name 'stats.xml' | sort | xargs python scripts/merge_stats.py --output ql/src/ql.dbscheme.stats --normalise ql_tokeninfo - uses: actions/upload-artifact@v2 with: name: ql.dbscheme.stats diff --git a/.github/workflows/published-codeql-analysis.yml b/.github/workflows/published-codeql-analysis.yml new file mode 100644 index 00000000000..706be102d56 --- /dev/null +++ b/.github/workflows/published-codeql-analysis.yml @@ -0,0 +1,53 @@ +name: "CodeQL with published queries and extractor" + +on: + workflow_dispatch: + push: + branches: [ main ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ main ] + +jobs: + + analyze: + name: Analyze + + runs-on: ubuntu-latest + + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Download pack + run: | + # adjust this line to make the workflow work in other repositories + # the ql-qlpack.zip file can be downloaded at: + # - https://github.com/github/codeql-ql/releases + # - https://github.com/github/codeql-ql/actions/workflows/bleeding-codeql-analysis.yml + gh release download latest --pattern ql-qlpack.zip + unzip ql-qlpack.zip -d "${PACK}" + env: + PACK: ${{ runner.temp }}/ql-qlpack + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Hack codeql-action options + run: | + JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]') + echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV} + env: + PACK: ${{ runner.temp }}/ql-qlpack + + - name: Initialize CodeQL + uses: github/codeql-action/init@esbena/ql + with: + languages: ql + db-location: ${{ runner.temp }}/db + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@esbena/ql diff --git a/Cargo.lock b/Cargo.lock index 2b35c05221a..16626b5d836 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,6 +329,7 @@ dependencies = [ name = "ql-generator" version = "0.1.0" dependencies = [ + "clap", "node-types", "tracing", "tracing-subscriber", diff --git a/create-extractor-pack.ps1 b/create-extractor-pack.ps1 index 775499cd7f7..9e6cb4ae295 100644 --- a/create-extractor-pack.ps1 +++ b/create-extractor-pack.ps1 @@ -1,6 +1,6 @@ cargo build --release -cargo run --release -p ql-generator +cargo run --release -p ql-generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/ codeql query format -i ql\src\codeql_ql\ast\internal\TreeSitter.qll if (Test-Path -Path extractor-pack) { diff --git a/create-extractor-pack.sh b/create-extractor-pack.sh index 09ce99751fd..5e45c41f819 100755 --- a/create-extractor-pack.sh +++ b/create-extractor-pack.sh @@ -12,7 +12,7 @@ fi cargo build --release -cargo run --release -p ql-generator +cargo run --release -p ql-generator -- --dbscheme ql/src/ql.dbscheme --library ql/src/codeql_ql/ast/internal/TreeSitter.qll codeql query format -i ql/src/codeql_ql/ast/internal/TreeSitter.qll rm -rf extractor-pack diff --git a/extractor/src/extractor.rs b/extractor/src/extractor.rs index 84d86b202c4..7c83f51e0dc 100644 --- a/extractor/src/extractor.rs +++ b/extractor/src/extractor.rs @@ -3,11 +3,13 @@ use std::borrow::Cow; use std::collections::BTreeMap as Map; use std::collections::BTreeSet as Set; use std::fmt; +use std::io::Write; use std::path::Path; + use tracing::{error, info, span, Level}; use tree_sitter::{Language, Node, Parser, Range, Tree}; -struct TrapWriter { +pub struct TrapWriter { /// The accumulated trap entries trap_output: Vec, /// A counter for generating fresh labels @@ -16,7 +18,7 @@ struct TrapWriter { global_keys: std::collections::HashMap, } -fn new_trap_writer() -> TrapWriter { +pub fn new_trap_writer() -> TrapWriter { TrapWriter { counter: 0, trap_output: Vec::new(), @@ -66,15 +68,6 @@ impl TrapWriter { vec![ Arg::Label(file_label), Arg::String(normalize_path(absolute_path)), - Arg::String(match absolute_path.file_name() { - None => "".to_owned(), - Some(file_name) => format!("{}", file_name.to_string_lossy()), - }), - Arg::String(match absolute_path.extension() { - None => "".to_owned(), - Some(ext) => format!("{}", ext.to_string_lossy()), - }), - Arg::Int(1), // 1 = from source ], ); self.populate_parent_folders(file_label, absolute_path.parent()); @@ -82,6 +75,22 @@ impl TrapWriter { file_label } + fn populate_empty_file(&mut self) -> Label { + let (file_label, fresh) = self.global_id("empty;sourcefile"); + if fresh { + self.add_tuple( + "files", + vec![Arg::Label(file_label), Arg::String("".to_string())], + ); + } + file_label + } + + pub fn populate_empty_location(&mut self) { + let file_label = self.populate_empty_file(); + self.location(file_label, 0, 0, 0, 0); + } + fn populate_parent_folders(&mut self, child_label: Label, path: Option<&Path>) { let mut path = path; let mut child_label = child_label; @@ -100,10 +109,6 @@ impl TrapWriter { vec![ Arg::Label(folder_label), Arg::String(normalize_path(folder)), - Arg::String(match folder.file_name() { - None => "".to_owned(), - Some(file_name) => format!("{}", file_name.to_string_lossy()), - }), ], ); path = folder.parent(); @@ -147,16 +152,22 @@ impl TrapWriter { fn comment(&mut self, text: String) { self.trap_output.push(TrapEntry::Comment(text)); } + + pub fn output(self, writer: &mut dyn Write) -> std::io::Result<()> { + write!(writer, "{}", Program(self.trap_output)) + } } /// Extracts the source file at `path`, which is assumed to be canonicalized. pub fn extract( language: Language, + language_prefix: &str, schema: &NodeTypeMap, + trap_writer: &mut TrapWriter, path: &Path, - source: &Vec, + source: &[u8], ranges: &[Range], -) -> std::io::Result { +) -> std::io::Result<()> { let span = span!( Level::TRACE, "extract", @@ -169,41 +180,32 @@ pub fn extract( let mut parser = Parser::new(); parser.set_language(language).unwrap(); - parser.set_included_ranges(&ranges).unwrap(); + parser.set_included_ranges(ranges).unwrap(); let tree = parser.parse(&source, None).expect("Failed to parse file"); - let mut trap_writer = new_trap_writer(); trap_writer.comment(format!("Auto-generated TRAP file for {}", path.display())); let file_label = &trap_writer.populate_file(path); let mut visitor = Visitor { - source: &source, - trap_writer: trap_writer, + source, + trap_writer, // TODO: should we handle path strings that are not valid UTF8 better? path: format!("{}", path.display()), file_label: *file_label, - token_counter: 0, toplevel_child_counter: 0, stack: Vec::new(), + language_prefix, schema, }; traverse(&tree, &mut visitor); parser.reset(); - Ok(Program(visitor.trap_writer.trap_output)) + Ok(()) } /// Escapes a string for use in a TRAP key, by replacing special characters with /// HTML entities. fn escape_key<'a, S: Into>>(key: S) -> Cow<'a, str> { fn needs_escaping(c: char) -> bool { - match c { - '&' => true, - '{' => true, - '}' => true, - '"' => true, - '@' => true, - '#' => true, - _ => false, - } + matches!(c, '&' | '{' | '}' | '"' | '@' | '#') } let key = key.into(); @@ -286,13 +288,13 @@ struct Visitor<'a> { /// source file. file_label: Label, /// The source code as a UTF-8 byte array - source: &'a Vec, + source: &'a [u8], /// A TrapWriter to accumulate trap entries - trap_writer: TrapWriter, - /// A counter for tokens - token_counter: usize, + trap_writer: &'a mut TrapWriter, /// A counter for top-level child nodes toplevel_child_counter: usize, + /// Language prefix + language_prefix: &'a str, /// A lookup table from type name to node types schema: &'a NodeTypeMap, /// A stack for gathering information from child nodes. Whenever a node is @@ -332,7 +334,7 @@ impl Visitor<'_> { full_error_message: String, node: Node, ) { - let (start_line, start_column, end_line, end_column) = location_for(&self.source, node); + let (start_line, start_column, end_line, end_column) = location_for(self.source, node); let loc = self.trap_writer.location( self.file_label, start_line, @@ -363,7 +365,7 @@ impl Visitor<'_> { let id = self.trap_writer.fresh_id(); self.stack.push((id, 0, Vec::new())); - return true; + true } fn leave_node(&mut self, field_name: Option<&'static str>, node: Node) { @@ -371,7 +373,7 @@ impl Visitor<'_> { return; } let (id, _, child_nodes) = self.stack.pop().expect("Vistor: empty stack"); - let (start_line, start_column, end_line, end_column) = location_for(&self.source, node); + let (start_line, start_column, end_line, end_column) = location_for(self.source, node); let loc = self.trap_writer.location( self.file_label, start_line, @@ -400,7 +402,7 @@ impl Visitor<'_> { match &table.kind { EntryKind::Token { kind_id, .. } => { self.trap_writer.add_tuple( - "ast_node_parent", + &format!("{}_ast_node_parent", self.language_prefix), vec![ Arg::Label(id), Arg::Label(parent_id), @@ -408,17 +410,14 @@ impl Visitor<'_> { ], ); self.trap_writer.add_tuple( - "tokeninfo", + &format!("{}_tokeninfo", self.language_prefix), vec![ Arg::Label(id), Arg::Int(*kind_id), - Arg::Label(self.file_label), - Arg::Int(self.token_counter), sliced_source_arg(self.source, node), Arg::Label(loc), ], ); - self.token_counter += 1; } EntryKind::Table { fields, @@ -426,18 +425,17 @@ impl Visitor<'_> { } => { if let Some(args) = self.complex_node(&node, fields, &child_nodes, id) { self.trap_writer.add_tuple( - "ast_node_parent", + &format!("{}_ast_node_parent", self.language_prefix), vec![ Arg::Label(id), Arg::Label(parent_id), Arg::Int(parent_index), ], ); - let mut all_args = Vec::new(); - all_args.push(Arg::Label(id)); + let mut all_args = vec![Arg::Label(id)]; all_args.extend(args); all_args.push(Arg::Label(loc)); - self.trap_writer.add_tuple(&table_name, all_args); + self.trap_writer.add_tuple(table_name, all_args); } } _ => { @@ -472,8 +470,8 @@ impl Visitor<'_> { fn complex_node( &mut self, node: &Node, - fields: &Vec, - child_nodes: &Vec, + fields: &[Field], + child_nodes: &[ChildNode], parent_id: Label, ) -> Option> { let mut map: Map<&Option, (&Field, Vec)> = Map::new(); @@ -510,22 +508,20 @@ impl Visitor<'_> { ); self.record_parse_error_for_node(error_message, full_error_message, *node); } - } else { - if child_node.field_name.is_some() || child_node.type_name.named { - let error_message = format!( - "value for unknown field: {}::{} and type {:?}", - node.kind(), - &child_node.field_name.unwrap_or("child"), - &child_node.type_name - ); - let full_error_message = format!( - "{}:{}: {}", - &self.path, - node.start_position().row + 1, - error_message - ); - self.record_parse_error_for_node(error_message, full_error_message, *node); - } + } else if child_node.field_name.is_some() || child_node.type_name.named { + let error_message = format!( + "value for unknown field: {}::{} and type {:?}", + node.kind(), + &child_node.field_name.unwrap_or("child"), + &child_node.type_name + ); + let full_error_message = format!( + "{}:{}: {}", + &self.path, + node.start_position().row + 1, + error_message + ); + self.record_parse_error_for_node(error_message, full_error_message, *node); } } let mut args = Vec::new(); @@ -573,13 +569,12 @@ impl Visitor<'_> { ); break; } - let mut args = Vec::new(); - args.push(Arg::Label(parent_id)); + let mut args = vec![Arg::Label(parent_id)]; if *has_index { args.push(Arg::Int(index)) } args.push(child_value.clone()); - self.trap_writer.add_tuple(&table_name, args); + self.trap_writer.add_tuple(table_name, args); } } } @@ -597,13 +592,10 @@ impl Visitor<'_> { if tp == single_type { return true; } - match &self.schema.get(single_type).unwrap().kind { - EntryKind::Union { members } => { - if self.type_matches_set(tp, members) { - return true; - } + if let EntryKind::Union { members } = &self.schema.get(single_type).unwrap().kind { + if self.type_matches_set(tp, members) { + return true; } - _ => {} } } node_types::FieldTypeInfo::Multiple { types, .. } => { @@ -633,7 +625,7 @@ impl Visitor<'_> { } // Emit a slice of a source file as an Arg. -fn sliced_source_arg(source: &Vec, n: Node) -> Arg { +fn sliced_source_arg(source: &[u8], n: Node) -> Arg { let range = n.byte_range(); Arg::String(String::from_utf8_lossy(&source[range.start..range.end]).into_owned()) } @@ -641,7 +633,7 @@ fn sliced_source_arg(source: &Vec, n: Node) -> Arg { // Emit a pair of `TrapEntry`s for the provided node, appropriately calibrated. // The first is the location and label definition, and the second is the // 'Located' entry. -fn location_for<'a>(source: &Vec, n: Node) -> (usize, usize, usize, usize) { +fn location_for(source: &[u8], n: Node) -> (usize, usize, usize, usize) { // Tree-sitter row, column values are 0-based while CodeQL starts // counting at 1. In addition Tree-sitter's row and column for the // end position are exclusive while CodeQL's end positions are inclusive. @@ -720,9 +712,9 @@ impl fmt::Display for Program { } enum TrapEntry { - /// Maps the label to a fresh id, e.g. `#123 = *`. + /// Maps the label to a fresh id, e.g. `#123=*`. FreshId(Label), - /// Maps the label to a key, e.g. `#7 = @"foo"`. + /// Maps the label to a key, e.g. `#7=@"foo"`. MapLabelToKey(Label, String), /// foo_bar(arg*) GenericTuple(String, Vec), @@ -731,15 +723,15 @@ enum TrapEntry { impl fmt::Display for TrapEntry { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - TrapEntry::FreshId(label) => write!(f, "{} = *", label), + TrapEntry::FreshId(label) => write!(f, "{}=*", label), TrapEntry::MapLabelToKey(label, key) => { - write!(f, "{} = @\"{}\"", label, key.replace("\"", "\"\"")) + write!(f, "{}=@\"{}\"", label, key.replace("\"", "\"\"")) } TrapEntry::GenericTuple(name, args) => { write!(f, "{}(", name)?; for (index, arg) in args.iter().enumerate() { if index > 0 { - write!(f, ", ")?; + write!(f, ",")?; } write!(f, "{}", arg)?; } @@ -756,7 +748,7 @@ struct Label(u32); impl fmt::Display for Label { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "#{}", self.0) + write!(f, "#{:x}", self.0) } } @@ -799,18 +791,18 @@ impl fmt::Display for Arg { /// the string is sliced at the provided limit. If there is a multi-byte character /// at the limit then the returned slice will be slightly shorter than the limit to /// avoid splitting that multi-byte character. -fn limit_string(string: &String, max_size: usize) -> &str { +fn limit_string(string: &str, max_size: usize) -> &str { if string.len() <= max_size { return string; } - let p = string.as_ptr(); + let p = string.as_bytes(); let mut index = max_size; // We want to clip the string at [max_size]; however, the character at that position // may span several bytes. We need to find the first byte of the character. In UTF-8 // encoded data any byte that matches the bit pattern 10XXXXXX is not a start byte. // Therefore we decrement the index as long as there are bytes matching this pattern. // This ensures we cut the string at the border between one character and another. - while index > 0 && unsafe { (*p.offset(index as isize) & 0b11000000) == 0b10000000 } { + while index > 0 && (p[index] & 0b11000000) == 0b10000000 { index -= 1; } &string[0..index] @@ -829,9 +821,9 @@ fn escape_key_test() { assert_eq!("foo{}", escape_key("foo{}")); assert_eq!("{}", escape_key("{}")); assert_eq!("", escape_key("")); - assert_eq!("/path/to/foo.ql", escape_key("/path/to/foo.ql")); + assert_eq!("/path/to/foo.rb", escape_key("/path/to/foo.rb")); assert_eq!( - "/path/to/foo&{}"@#.ql", - escape_key("/path/to/foo&{}\"@#.ql") + "/path/to/foo&{}"@#.rb", + escape_key("/path/to/foo&{}\"@#.rb") ); } diff --git a/extractor/src/main.rs b/extractor/src/main.rs index b74126ffd0f..0fcf9607702 100644 --- a/extractor/src/main.rs +++ b/extractor/src/main.rs @@ -2,13 +2,11 @@ mod extractor; extern crate num_cpus; -use clap; use flate2::write::GzEncoder; use rayon::prelude::*; use std::fs; -use std::io::{BufRead, BufWriter, Write}; +use std::io::{BufRead, BufWriter}; use std::path::{Path, PathBuf}; -use tree_sitter::{Language, Parser, Range}; enum TrapCompression { None, @@ -40,8 +38,8 @@ impl TrapCompression { fn extension(&self) -> &str { match self { - TrapCompression::None => ".trap", - TrapCompression::Gzip => ".trap.gz", + TrapCompression::None => "trap", + TrapCompression::Gzip => "trap.gz", } } } @@ -54,28 +52,24 @@ impl TrapCompression { * "If the number is positive, it indicates the number of threads that should * be used. If the number is negative or zero, it should be added to the number * of cores available on the machine to determine how many threads to use - * (minimum of 1). If unspecified, should be considered as set to 1." + * (minimum of 1). If unspecified, should be considered as set to -1." */ fn num_codeql_threads() -> usize { - match std::env::var("CODEQL_THREADS") { - // Use 1 thread if the environment variable isn't set. - Err(_) => 1, + let threads_str = std::env::var("CODEQL_THREADS").unwrap_or_else(|_| "-1".to_owned()); + match threads_str.parse::() { + Ok(num) if num <= 0 => { + let reduction = -num as usize; + std::cmp::max(1, num_cpus::get() - reduction) + } + Ok(num) => num as usize, - Ok(num) => match num.parse::() { - Ok(num) if num <= 0 => { - let reduction = -num as usize; - num_cpus::get() - reduction - } - Ok(num) => num as usize, - - Err(_) => { - tracing::error!( - "Unable to parse CODEQL_THREADS value '{}'; defaulting to 1 thread.", - &num - ); - 1 - } - }, + Err(_) => { + tracing::error!( + "Unable to parse CODEQL_THREADS value '{}'; defaulting to 1 thread.", + &threads_str + ); + 1 + } } } @@ -127,29 +121,55 @@ fn main() -> std::io::Result<()> { let file_list = fs::File::open(file_list)?; let language = tree_sitter_ql::language(); - let schema = node_types::read_node_types_str(tree_sitter_ql::NODE_TYPES)?; + let schema = node_types::read_node_types_str("ql", tree_sitter_ql::NODE_TYPES)?; let lines: std::io::Result> = std::io::BufReader::new(file_list).lines().collect(); let lines = lines?; - lines.par_iter().try_for_each(|line| { - let path = PathBuf::from(line).canonicalize()?; - let trap_file = path_for(&trap_dir, &path, trap_compression.extension()); - let src_archive_file = path_for(&src_archive_dir, &path, ""); - let mut source = std::fs::read(&path)?; - let code_ranges = vec![]; - let trap = extractor::extract(language, &schema, &path, &source, &code_ranges)?; - std::fs::create_dir_all(&src_archive_file.parent().unwrap())?; - std::fs::copy(&path, &src_archive_file)?; - std::fs::create_dir_all(&trap_file.parent().unwrap())?; - let trap_file = std::fs::File::create(&trap_file)?; - let mut trap_file = BufWriter::new(trap_file); - match trap_compression { - TrapCompression::None => write!(trap_file, "{}", trap), - TrapCompression::Gzip => { - let mut compressed_writer = GzEncoder::new(trap_file, flate2::Compression::fast()); - write!(compressed_writer, "{}", trap) - } + lines + .par_iter() + .try_for_each(|line| { + let path = PathBuf::from(line).canonicalize()?; + let src_archive_file = path_for(&src_archive_dir, &path, ""); + let source = std::fs::read(&path)?; + let code_ranges = vec![]; + let mut trap_writer = extractor::new_trap_writer(); + extractor::extract( + language, + "ql", + &schema, + &mut trap_writer, + &path, + &source, + &code_ranges, + )?; + std::fs::create_dir_all(&src_archive_file.parent().unwrap())?; + std::fs::copy(&path, &src_archive_file)?; + write_trap(&trap_dir, path, trap_writer, &trap_compression) + }) + .expect("failed to extract files"); + + let path = PathBuf::from("extras"); + let mut trap_writer = extractor::new_trap_writer(); + trap_writer.populate_empty_location(); + write_trap(&trap_dir, path, trap_writer, &trap_compression) +} + +fn write_trap( + trap_dir: &Path, + path: PathBuf, + trap_writer: extractor::TrapWriter, + trap_compression: &TrapCompression, +) -> std::io::Result<()> { + let trap_file = path_for(trap_dir, &path, trap_compression.extension()); + std::fs::create_dir_all(&trap_file.parent().unwrap())?; + let trap_file = std::fs::File::create(&trap_file)?; + let mut trap_file = BufWriter::new(trap_file); + match trap_compression { + TrapCompression::None => trap_writer.output(&mut trap_file), + TrapCompression::Gzip => { + let mut compressed_writer = GzEncoder::new(trap_file, flate2::Compression::fast()); + trap_writer.output(&mut compressed_writer) } - }) + } } fn path_for(dir: &Path, path: &Path, ext: &str) -> PathBuf { @@ -184,12 +204,18 @@ fn path_for(dir: &Path, path: &Path, ext: &str) -> PathBuf { } } } - if let Some(x) = result.extension() { - let mut new_ext = x.to_os_string(); - new_ext.push(ext); - result.set_extension(new_ext); - } else { - result.set_extension(ext); + if !ext.is_empty() { + match result.extension() { + Some(x) => { + let mut new_ext = x.to_os_string(); + new_ext.push("."); + new_ext.push(ext); + result.set_extension(new_ext); + } + None => { + result.set_extension(ext); + } + } } result } diff --git a/generator/Cargo.toml b/generator/Cargo.toml index 93117ef1c3e..38074ab4e91 100644 --- a/generator/Cargo.toml +++ b/generator/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = "2.33" node-types = { path = "../node-types" } tracing = "0.1" tracing-subscriber = { version = "0.2", features = ["env-filter"] } diff --git a/generator/src/dbscheme.rs b/generator/src/dbscheme.rs index 84cc329d065..335eee1950c 100644 --- a/generator/src/dbscheme.rs +++ b/generator/src/dbscheme.rs @@ -68,10 +68,10 @@ impl<'a> fmt::Display for Table<'a> { } write!(f, "{}", key)?; } - write!(f, "]\n")?; + writeln!(f, "]")?; } - write!(f, "{}(\n", self.name)?; + writeln!(f, "{}(", self.name)?; for (column_index, column) in self.columns.iter().enumerate() { write!(f, " ")?; if column.unique { @@ -92,7 +92,7 @@ impl<'a> fmt::Display for Table<'a> { if column_index + 1 != self.columns.len() { write!(f, ",")?; } - write!(f, "\n")?; + writeln!(f)?; } write!(f, ");")?; @@ -117,17 +117,7 @@ impl<'a> fmt::Display for Union<'a> { } /// Generates the dbscheme by writing the given dbscheme `entries` to the `file`. -pub fn write<'a>( - language_name: &str, - file: &mut dyn std::io::Write, - entries: &'a [Entry], -) -> std::io::Result<()> { - write!(file, "// CodeQL database schema for {}\n", language_name)?; - write!( - file, - "// Automatically generated from the tree-sitter grammar; do not edit\n\n" - )?; - +pub fn write<'a>(file: &mut dyn std::io::Write, entries: &'a [Entry]) -> std::io::Result<()> { for entry in entries { match entry { Entry::Case(case) => write!(file, "{}\n\n", case)?, diff --git a/generator/src/language.rs b/generator/src/language.rs index 4e2f985a21c..f0b0ed1790f 100644 --- a/generator/src/language.rs +++ b/generator/src/language.rs @@ -1,8 +1,4 @@ -use std::path::PathBuf; - pub struct Language { pub name: String, pub node_types: &'static str, - pub dbscheme_path: PathBuf, - pub ql_library_path: PathBuf, } diff --git a/generator/src/main.rs b/generator/src/main.rs index 13922c4b84c..04e7cd61d2c 100644 --- a/generator/src/main.rs +++ b/generator/src/main.rs @@ -8,8 +8,8 @@ use std::collections::BTreeMap as Map; use std::collections::BTreeSet as Set; use std::fs::File; use std::io::LineWriter; +use std::io::Write; use std::path::PathBuf; -use tracing::{error, info}; /// Given the name of the parent node, and its field information, returns a pair, /// the first of which is the field's type. The second is an optional dbscheme @@ -32,7 +32,7 @@ fn make_field_type<'a>( .map(|t| nodes.get(t).unwrap().dbscheme_name.as_str()) .collect(); ( - ql::Type::AtType(&dbscheme_union), + ql::Type::At(dbscheme_union), Some(dbscheme::Entry::Union(dbscheme::Union { name: dbscheme_union, members, @@ -40,14 +40,14 @@ fn make_field_type<'a>( ) } node_types::FieldTypeInfo::Single(t) => { - let dbscheme_name = &nodes.get(&t).unwrap().dbscheme_name; - (ql::Type::AtType(dbscheme_name), None) + let dbscheme_name = &nodes.get(t).unwrap().dbscheme_name; + (ql::Type::At(dbscheme_name), None) } node_types::FieldTypeInfo::ReservedWordInt(int_mapping) => { // The field will be an `int` in the db, and we add a case split to // create other db types for each integer value. let mut branches: Vec<(usize, &'a str)> = Vec::new(); - for (_, (value, name)) in int_mapping { + for (value, name) in int_mapping.values() { branches.push((*value, name)); } let case = dbscheme::Entry::Case(dbscheme::Case { @@ -73,12 +73,12 @@ fn add_field_for_table_storage<'a>( let parent_name = &nodes.get(&field.parent).unwrap().dbscheme_name; // This field can appear zero or multiple times, so put // it in an auxiliary table. - let (field_ql_type, field_type_entry) = make_field_type(parent_name, &field, nodes); + let (field_ql_type, field_type_entry) = make_field_type(parent_name, field, nodes); let parent_column = dbscheme::Column { unique: !has_index, db_type: dbscheme::DbColumnType::Int, - name: &parent_name, - ql_type: ql::Type::AtType(&parent_name), + name: parent_name, + ql_type: ql::Type::At(parent_name), ql_type_is_ref: true, }; let index_column = dbscheme::Column { @@ -96,7 +96,7 @@ fn add_field_for_table_storage<'a>( ql_type_is_ref: true, }; let field_table = dbscheme::Table { - name: &table_name, + name: table_name, columns: if has_index { vec![parent_column, index_column, field_column] } else { @@ -105,7 +105,7 @@ fn add_field_for_table_storage<'a>( // In addition to the field being unique, the combination of // parent+index is unique, so add a keyset for them. keysets: if has_index { - Some(vec![&parent_name, "index"]) + Some(vec![parent_name, "index"]) } else { None }, @@ -121,7 +121,7 @@ fn add_field_for_column_storage<'a>( ) -> (dbscheme::Column<'a>, Option>) { // This field must appear exactly once, so we add it as // a column to the main table for the node type. - let (field_ql_type, field_type_entry) = make_field_type(parent_name, &field, nodes); + let (field_ql_type, field_type_entry) = make_field_type(parent_name, field, nodes); ( dbscheme::Column { unique: false, @@ -135,18 +135,16 @@ fn add_field_for_column_storage<'a>( } /// Converts the given tree-sitter node types into CodeQL dbscheme entries. -fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec> { - let mut entries: Vec = vec![ - create_location_union(), - create_locations_default_table(), - create_sourceline_union(), - create_numlines_table(), - create_files_table(), - create_folders_table(), - create_container_union(), - create_containerparent_table(), - create_source_location_prefix_table(), - ]; +/// Returns a tuple containing: +/// +/// 1. A vector of dbscheme entries. +/// 2. A set of names of the members of the `_ast_node` union. +/// 3. A map where the keys are the dbscheme names for token kinds, and the +/// values are their integer representations. +fn convert_nodes( + nodes: &node_types::NodeTypeMap, +) -> (Vec, Set<&str>, Map<&str, usize>) { + let mut entries: Vec = Vec::new(); let mut ast_node_members: Set<&str> = Set::new(); let token_kinds: Map<&str, usize> = nodes .iter() @@ -157,8 +155,7 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec None, }) .collect(); - ast_node_members.insert("token"); - for (_, node) in nodes { + for node in nodes.values() { match &node.kind { node_types::EntryKind::Union { members: n_members } => { // It's a tree-sitter supertype node, for which we create a union @@ -175,12 +172,12 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec { // It's a product type, defined by a table. let mut main_table = dbscheme::Table { - name: &name, + name, columns: vec![dbscheme::Column { db_type: dbscheme::DbColumnType::Int, name: "id", unique: true, - ql_type: ql::Type::AtType(&node.dbscheme_name), + ql_type: ql::Type::At(&node.dbscheme_name), ql_type_is_ref: false, }], keysets: None, @@ -240,7 +237,7 @@ fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec(nodes: &'a node_types::NodeTypeMap) -> Vec() -> dbscheme::Table<'a> { + +/// Creates a dbscheme table entry representing the parent relation for AST nodes. +/// +/// # Arguments +/// - `name` - the name of both the table to create and the node parent type. +/// - `ast_node_name` - the name of the node child type. +fn create_ast_node_parent_table<'a>(name: &'a str, ast_node_name: &'a str) -> dbscheme::Table<'a> { dbscheme::Table { - name: "ast_node_parent", + name, columns: vec![ dbscheme::Column { db_type: dbscheme::DbColumnType::Int, name: "child", unique: false, - ql_type: ql::Type::AtType("ast_node"), + ql_type: ql::Type::At(ast_node_name), ql_type_is_ref: true, }, dbscheme::Column { db_type: dbscheme::DbColumnType::Int, name: "parent", unique: false, - ql_type: ql::Type::AtType("ast_node_parent"), + ql_type: ql::Type::At(name), ql_type_is_ref: true, }, dbscheme::Column { @@ -306,18 +285,16 @@ fn create_ast_node_parent_table<'a>() -> dbscheme::Table<'a> { } } -fn create_tokeninfo<'a>( - token_kinds: Map<&'a str, usize>, -) -> (dbscheme::Case<'a>, dbscheme::Table<'a>) { - let table = dbscheme::Table { - name: "tokeninfo", +fn create_tokeninfo<'a>(name: &'a str, type_name: &'a str) -> dbscheme::Table<'a> { + dbscheme::Table { + name, keysets: None, columns: vec![ dbscheme::Column { db_type: dbscheme::DbColumnType::Int, name: "id", unique: true, - ql_type: ql::Type::AtType("token"), + ql_type: ql::Type::At(type_name), ql_type_is_ref: false, }, dbscheme::Column { @@ -327,20 +304,6 @@ fn create_tokeninfo<'a>( ql_type: ql::Type::Int, ql_type_is_ref: true, }, - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "file", - ql_type: ql::Type::AtType("file"), - ql_type_is_ref: true, - }, - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "idx", - ql_type: ql::Type::Int, - ql_type_is_ref: true, - }, dbscheme::Column { unique: false, db_type: dbscheme::DbColumnType::String, @@ -352,35 +315,23 @@ fn create_tokeninfo<'a>( unique: false, db_type: dbscheme::DbColumnType::Int, name: "loc", - ql_type: ql::Type::AtType("location"), + ql_type: ql::Type::At("location"), ql_type_is_ref: true, }, ], - }; + } +} + +fn create_token_case<'a>(name: &'a str, token_kinds: Map<&'a str, usize>) -> dbscheme::Case<'a> { let branches: Vec<(usize, &str)> = token_kinds .iter() .map(|(&name, kind_id)| (*kind_id, name)) .collect(); - let case = dbscheme::Case { - name: "token", + dbscheme::Case { + name, column: "kind", - branches: branches, - }; - (case, table) -} - -fn write_dbscheme(language: &Language, entries: &[dbscheme::Entry]) -> std::io::Result<()> { - info!( - "Writing database schema for {} to '{}'", - &language.name, - match language.dbscheme_path.to_str() { - None => "", - Some(p) => p, - } - ); - let file = File::create(&language.dbscheme_path)?; - let mut file = LineWriter::new(file); - dbscheme::write(&language.name, &mut file, &entries) + branches, + } } fn create_location_union<'a>() -> dbscheme::Entry<'a> { @@ -399,7 +350,7 @@ fn create_files_table<'a>() -> dbscheme::Entry<'a> { unique: true, db_type: dbscheme::DbColumnType::Int, name: "id", - ql_type: ql::Type::AtType("file"), + ql_type: ql::Type::At("file"), ql_type_is_ref: false, }, dbscheme::Column { @@ -409,27 +360,6 @@ fn create_files_table<'a>() -> dbscheme::Entry<'a> { ql_type: ql::Type::String, ql_type_is_ref: true, }, - dbscheme::Column { - db_type: dbscheme::DbColumnType::String, - name: "simple", - unique: false, - ql_type: ql::Type::String, - ql_type_is_ref: true, - }, - dbscheme::Column { - db_type: dbscheme::DbColumnType::String, - name: "ext", - unique: false, - ql_type: ql::Type::String, - ql_type_is_ref: true, - }, - dbscheme::Column { - db_type: dbscheme::DbColumnType::Int, - name: "fromSource", - unique: false, - ql_type: ql::Type::Int, - ql_type_is_ref: true, - }, ], }) } @@ -442,7 +372,7 @@ fn create_folders_table<'a>() -> dbscheme::Entry<'a> { unique: true, db_type: dbscheme::DbColumnType::Int, name: "id", - ql_type: ql::Type::AtType("folder"), + ql_type: ql::Type::At("folder"), ql_type_is_ref: false, }, dbscheme::Column { @@ -452,13 +382,6 @@ fn create_folders_table<'a>() -> dbscheme::Entry<'a> { ql_type: ql::Type::String, ql_type_is_ref: true, }, - dbscheme::Column { - db_type: dbscheme::DbColumnType::String, - name: "simple", - unique: false, - ql_type: ql::Type::String, - ql_type_is_ref: true, - }, ], }) } @@ -472,14 +395,14 @@ fn create_locations_default_table<'a>() -> dbscheme::Entry<'a> { unique: true, db_type: dbscheme::DbColumnType::Int, name: "id", - ql_type: ql::Type::AtType("location_default"), + ql_type: ql::Type::At("location_default"), ql_type_is_ref: false, }, dbscheme::Column { unique: false, db_type: dbscheme::DbColumnType::Int, name: "file", - ql_type: ql::Type::AtType("file"), + ql_type: ql::Type::At("file"), ql_type_is_ref: true, }, dbscheme::Column { @@ -514,50 +437,6 @@ fn create_locations_default_table<'a>() -> dbscheme::Entry<'a> { }) } -fn create_sourceline_union<'a>() -> dbscheme::Entry<'a> { - dbscheme::Entry::Union(dbscheme::Union { - name: "sourceline", - members: vec!["file"].into_iter().collect(), - }) -} - -fn create_numlines_table<'a>() -> dbscheme::Entry<'a> { - dbscheme::Entry::Table(dbscheme::Table { - name: "numlines", - columns: vec![ - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "element_id", - ql_type: ql::Type::AtType("sourceline"), - ql_type_is_ref: true, - }, - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "num_lines", - ql_type: ql::Type::Int, - ql_type_is_ref: true, - }, - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "num_code", - ql_type: ql::Type::Int, - ql_type_is_ref: true, - }, - dbscheme::Column { - unique: false, - db_type: dbscheme::DbColumnType::Int, - name: "num_comment", - ql_type: ql::Type::Int, - ql_type_is_ref: true, - }, - ], - keysets: None, - }) -} - fn create_container_union<'a>() -> dbscheme::Entry<'a> { dbscheme::Entry::Union(dbscheme::Union { name: "container", @@ -573,14 +452,14 @@ fn create_containerparent_table<'a>() -> dbscheme::Entry<'a> { unique: false, db_type: dbscheme::DbColumnType::Int, name: "parent", - ql_type: ql::Type::AtType("container"), + ql_type: ql::Type::At("container"), ql_type_is_ref: true, }, dbscheme::Column { unique: true, db_type: dbscheme::DbColumnType::Int, name: "child", - ql_type: ql::Type::AtType("container"), + ql_type: ql::Type::At("container"), ql_type_is_ref: true, }, ], @@ -611,7 +490,7 @@ fn create_diagnostics<'a>() -> (dbscheme::Case<'a>, dbscheme::Table<'a>) { unique: true, db_type: dbscheme::DbColumnType::Int, name: "id", - ql_type: ql::Type::AtType("diagnostic"), + ql_type: ql::Type::At("diagnostic"), ql_type_is_ref: false, }, dbscheme::Column { @@ -646,7 +525,7 @@ fn create_diagnostics<'a>() -> (dbscheme::Case<'a>, dbscheme::Table<'a>) { unique: false, db_type: dbscheme::DbColumnType::Int, name: "location", - ql_type: ql::Type::AtType("location_default"), + ql_type: ql::Type::At("location_default"), ql_type_is_ref: true, }, ], @@ -665,7 +544,7 @@ fn create_diagnostics<'a>() -> (dbscheme::Case<'a>, dbscheme::Table<'a>) { (case, table) } -fn main() { +fn main() -> std::io::Result<()> { tracing_subscriber::fmt() .with_target(false) .without_time() @@ -673,33 +552,114 @@ fn main() { .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .init(); - // TODO: figure out proper dbscheme output path and/or take it from the - // command line. - let ql = Language { + let matches = clap::App::new("QL dbscheme generator") + .version("1.0") + .author("GitHub") + .about("CodeQL QL dbscheme generator") + .args_from_usage( + "--dbscheme= 'Path of the generated dbscheme file' + --library= 'Path of the generated QLL file'", + ) + .get_matches(); + let dbscheme_path = matches.value_of("dbscheme").expect("missing --dbscheme"); + let dbscheme_path = PathBuf::from(dbscheme_path); + + let ql_library_path = matches.value_of("library").expect("missing --library"); + let ql_library_path = PathBuf::from(ql_library_path); + + let languages = vec![Language { name: "QL".to_owned(), node_types: tree_sitter_ql::NODE_TYPES, - dbscheme_path: PathBuf::from("ql/src/ql.dbscheme"), - ql_library_path: PathBuf::from("ql/src/codeql_ql/ast/internal/TreeSitter.qll"), - }; - match node_types::read_node_types_str(&ql.node_types) { - Err(e) => { - error!("Failed to read node-types JSON for {}: {}", ql.name, e); - std::process::exit(1); - } - Ok(nodes) => { - let dbscheme_entries = convert_nodes(&nodes); + }]; + let mut dbscheme_writer = LineWriter::new(File::create(dbscheme_path)?); + write!( + dbscheme_writer, + "// CodeQL database schema for {}\n\ + // Automatically generated from the tree-sitter grammar; do not edit\n\n", + languages[0].name + )?; + let (diagnostics_case, diagnostics_table) = create_diagnostics(); + dbscheme::write( + &mut dbscheme_writer, + &[ + create_location_union(), + create_locations_default_table(), + create_files_table(), + create_folders_table(), + create_container_union(), + create_containerparent_table(), + create_source_location_prefix_table(), + dbscheme::Entry::Table(diagnostics_table), + dbscheme::Entry::Case(diagnostics_case), + ], + )?; - if let Err(e) = write_dbscheme(&ql, &dbscheme_entries) { - error!("Failed to write dbscheme: {}", e); - std::process::exit(2); - } + let mut ql_writer = LineWriter::new(File::create(ql_library_path)?); + write!( + ql_writer, + "/*\n\ + * CodeQL library for {} + * Automatically generated from the tree-sitter grammar; do not edit\n\ + */\n\n", + languages[0].name + )?; + ql::write( + &mut ql_writer, + &[ + ql::TopLevel::Import("codeql.files.FileSystem"), + ql::TopLevel::Import("codeql.Locations"), + ], + )?; - let classes = ql_gen::convert_nodes(&nodes); + for language in languages { + let prefix = node_types::to_snake_case(&language.name); + let ast_node_name = format!("{}_ast_node", &prefix); + let ast_node_parent_name = format!("{}_ast_node_parent", &prefix); + let token_name = format!("{}_token", &prefix); + let tokeninfo_name = format!("{}_tokeninfo", &prefix); + let reserved_word_name = format!("{}_reserved_word", &prefix); + let nodes = node_types::read_node_types_str(&prefix, language.node_types)?; + let (dbscheme_entries, mut ast_node_members, token_kinds) = convert_nodes(&nodes); + ast_node_members.insert(&token_name); + dbscheme::write(&mut dbscheme_writer, &dbscheme_entries)?; + let token_case = create_token_case(&token_name, token_kinds); + dbscheme::write( + &mut dbscheme_writer, + &[ + dbscheme::Entry::Table(create_tokeninfo(&tokeninfo_name, &token_name)), + dbscheme::Entry::Case(token_case), + dbscheme::Entry::Union(dbscheme::Union { + name: &ast_node_name, + members: ast_node_members, + }), + dbscheme::Entry::Union(dbscheme::Union { + name: &ast_node_parent_name, + members: [&ast_node_name, "file"].iter().cloned().collect(), + }), + dbscheme::Entry::Table(create_ast_node_parent_table( + &ast_node_parent_name, + &ast_node_name, + )), + ], + )?; - if let Err(e) = ql_gen::write(&ql, &classes) { - println!("Failed to write QL library: {}", e); - std::process::exit(3); - } - } + let mut body = vec![ + ql::TopLevel::Class(ql_gen::create_ast_node_class( + &ast_node_name, + &ast_node_parent_name, + )), + ql::TopLevel::Class(ql_gen::create_token_class(&token_name, &tokeninfo_name)), + ql::TopLevel::Class(ql_gen::create_reserved_word_class(&reserved_word_name)), + ]; + body.append(&mut ql_gen::convert_nodes(&nodes)); + ql::write( + &mut ql_writer, + &[ql::TopLevel::Module(ql::Module { + qldoc: None, + name: &language.name, + body, + })], + )?; } + Ok(()) } diff --git a/generator/src/ql.rs b/generator/src/ql.rs index b1b2f7529d2..c51903529eb 100644 --- a/generator/src/ql.rs +++ b/generator/src/ql.rs @@ -1,9 +1,11 @@ use std::collections::BTreeSet; use std::fmt; +#[derive(Clone, Eq, PartialEq, Hash)] pub enum TopLevel<'a> { Class(Class<'a>), Import(&'a str), + Module(Module<'a>), } impl<'a> fmt::Display for TopLevel<'a> { @@ -11,6 +13,7 @@ impl<'a> fmt::Display for TopLevel<'a> { match self { TopLevel::Import(x) => write!(f, "private import {}", x), TopLevel::Class(cls) => write!(f, "{}", cls), + TopLevel::Module(m) => write!(f, "{}", m), } } } @@ -40,15 +43,15 @@ impl<'a> fmt::Display for Class<'a> { } write!(f, "{}", supertype)?; } - write!(f, " {{ \n")?; + writeln!(f, " {{ ")?; if let Some(charpred) = &self.characteristic_predicate { - write!( + writeln!( f, - " {}\n", + " {}", Predicate { qldoc: None, - name: self.name.clone(), + name: self.name, overridden: false, return_type: None, formal_parameters: vec![], @@ -58,7 +61,7 @@ impl<'a> fmt::Display for Class<'a> { } for predicate in &self.predicates { - write!(f, " {}\n", predicate)?; + writeln!(f, " {}", predicate)?; } write!(f, "}}")?; @@ -67,6 +70,26 @@ impl<'a> fmt::Display for Class<'a> { } } +#[derive(Clone, Eq, PartialEq, Hash)] +pub struct Module<'a> { + pub qldoc: Option, + pub name: &'a str, + pub body: Vec>, +} + +impl<'a> fmt::Display for Module<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if let Some(qldoc) = &self.qldoc { + write!(f, "/** {} */", qldoc)?; + } + writeln!(f, "module {} {{ ", self.name)?; + for decl in &self.body { + writeln!(f, " {}", decl)?; + } + write!(f, "}}")?; + Ok(()) + } +} // The QL type of a column. #[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] pub enum Type<'a> { @@ -77,7 +100,7 @@ pub enum Type<'a> { String, /// A database type that will need to be referred to with an `@` prefix. - AtType(&'a str), + At(&'a str), /// A user-defined type. Normal(&'a str), @@ -89,7 +112,7 @@ impl<'a> fmt::Display for Type<'a> { Type::Int => write!(f, "int"), Type::String => write!(f, "string"), Type::Normal(name) => write!(f, "{}", name), - Type::AtType(name) => write!(f, "@{}", name), + Type::At(name) => write!(f, "@{}", name), } } } @@ -104,12 +127,13 @@ pub enum Expression<'a> { Or(Vec>), Equals(Box>, Box>), Dot(Box>, &'a str, Vec>), - Aggregate( - &'a str, - Vec>, - Box>, - Box>, - ), + Aggregate { + name: &'a str, + vars: Vec>, + range: Option>>, + expr: Box>, + second_expr: Option>>, + }, } impl<'a> fmt::Display for Expression<'a> { @@ -165,15 +189,31 @@ impl<'a> fmt::Display for Expression<'a> { } write!(f, ")") } - Expression::Aggregate(n, vars, range, term) => { - write!(f, "{}(", n)?; - for (index, var) in vars.iter().enumerate() { - if index > 0 { - write!(f, ", ")?; + Expression::Aggregate { + name, + vars, + range, + expr, + second_expr, + } => { + write!(f, "{}(", name)?; + if !vars.is_empty() { + for (index, var) in vars.iter().enumerate() { + if index > 0 { + write!(f, ", ")?; + } + write!(f, "{}", var)?; } - write!(f, "{}", var)?; + write!(f, " | ")?; } - write!(f, " | {} | {})", range, term) + if let Some(range) = range { + write!(f, "{} | ", range)?; + } + write!(f, "{}", expr)?; + if let Some(second_expr) = second_expr { + write!(f, ", {}", second_expr)?; + } + write!(f, ")") } } } @@ -226,25 +266,10 @@ impl<'a> fmt::Display for FormalParameter<'a> { } } -/// Generates a QL library by writing the given `classes` to the `file`. -pub fn write<'a>( - language_name: &str, - file: &mut dyn std::io::Write, - elements: &'a [TopLevel], -) -> std::io::Result<()> { - write!(file, "/*\n")?; - write!(file, " * CodeQL library for {}\n", language_name)?; - write!( - file, - " * Automatically generated from the tree-sitter grammar; do not edit\n" - )?; - write!(file, " */\n\n")?; - write!(file, "module Generated {{\n")?; - +/// Generates a QL library by writing the given `elements` to the `file`. +pub fn write<'a>(file: &mut dyn std::io::Write, elements: &'a [TopLevel]) -> std::io::Result<()> { for element in elements { write!(file, "{}\n\n", &element)?; } - - write!(file, "}}")?; Ok(()) } diff --git a/generator/src/ql_gen.rs b/generator/src/ql_gen.rs index 4fbe3449e63..a9a276fd9f6 100644 --- a/generator/src/ql_gen.rs +++ b/generator/src/ql_gen.rs @@ -1,32 +1,9 @@ -use crate::language::Language; use crate::ql; use std::collections::BTreeSet; -use std::fs::File; -use std::io::LineWriter; - -/// Writes the QL AST library for the given library. -/// -/// # Arguments -/// -/// `language` - the language for which we're generating a library -/// `classes` - the list of classes to write. -pub fn write(language: &Language, classes: &[ql::TopLevel]) -> std::io::Result<()> { - println!( - "Writing QL library for {} to '{}'", - &language.name, - match language.ql_library_path.to_str() { - None => "", - Some(p) => p, - } - ); - let file = File::create(&language.ql_library_path)?; - let mut file = LineWriter::new(file); - ql::write(&language.name, &mut file, &classes) -} /// Creates the hard-coded `AstNode` class that acts as a supertype of all /// classes we generate. -fn create_ast_node_class<'a>() -> ql::Class<'a> { +pub fn create_ast_node_class<'a>(ast_node: &'a str, ast_node_parent: &'a str) -> ql::Class<'a> { // Default implementation of `toString` calls `this.getAPrimaryQlClass()` let to_string = ql::Predicate { qldoc: Some(String::from( @@ -64,7 +41,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { return_type: Some(ql::Type::Normal("AstNode")), formal_parameters: vec![], body: ql::Expression::Pred( - "ast_node_parent", + ast_node_parent, vec![ ql::Expression::Var("this"), ql::Expression::Var("result"), @@ -81,7 +58,7 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { return_type: Some(ql::Type::Int), formal_parameters: vec![], body: ql::Expression::Pred( - "ast_node_parent", + ast_node_parent, vec![ ql::Expression::Var("this"), ql::Expression::Var("_"), @@ -102,11 +79,36 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { Box::new(ql::Expression::String("???")), ), }; + let get_primary_ql_classes = ql::Predicate { + qldoc: Some( + "Gets a comma-separated list of the names of the primary CodeQL \ + classes to which this element belongs." + .to_owned(), + ), + name: "getPrimaryQlClasses", + overridden: false, + return_type: Some(ql::Type::String), + formal_parameters: vec![], + body: ql::Expression::Equals( + Box::new(ql::Expression::Var("result")), + Box::new(ql::Expression::Aggregate { + name: "concat", + vars: vec![], + range: None, + expr: Box::new(ql::Expression::Dot( + Box::new(ql::Expression::Var("this")), + "getAPrimaryQlClass", + vec![], + )), + second_expr: Some(Box::new(ql::Expression::String(","))), + }), + ), + }; ql::Class { qldoc: Some(String::from("The base class for all AST nodes")), name: "AstNode", is_abstract: false, - supertypes: vec![ql::Type::AtType("ast_node")].into_iter().collect(), + supertypes: vec![ql::Type::At(ast_node)].into_iter().collect(), characteristic_predicate: None, predicates: vec![ to_string, @@ -115,19 +117,20 @@ fn create_ast_node_class<'a>() -> ql::Class<'a> { get_parent_index, get_a_field_or_child, get_a_primary_ql_class, + get_primary_ql_classes, ], } } -fn create_token_class<'a>() -> ql::Class<'a> { - let tokeninfo_arity = 6; +pub fn create_token_class<'a>(token_type: &'a str, tokeninfo: &'a str) -> ql::Class<'a> { + let tokeninfo_arity = 4; let get_value = ql::Predicate { qldoc: Some(String::from("Gets the value of this token.")), name: "getValue", overridden: false, return_type: Some(ql::Type::String), formal_parameters: vec![], - body: create_get_field_expr_for_column_storage("result", "tokeninfo", 3, tokeninfo_arity), + body: create_get_field_expr_for_column_storage("result", tokeninfo, 1, tokeninfo_arity), }; let get_location = ql::Predicate { qldoc: Some(String::from("Gets the location of this token.")), @@ -135,7 +138,7 @@ fn create_token_class<'a>() -> ql::Class<'a> { overridden: true, return_type: Some(ql::Type::Normal("Location")), formal_parameters: vec![], - body: create_get_field_expr_for_column_storage("result", "tokeninfo", 4, tokeninfo_arity), + body: create_get_field_expr_for_column_storage("result", tokeninfo, 2, tokeninfo_arity), }; let to_string = ql::Predicate { qldoc: Some(String::from( @@ -147,14 +150,18 @@ fn create_token_class<'a>() -> ql::Class<'a> { formal_parameters: vec![], body: ql::Expression::Equals( Box::new(ql::Expression::Var("result")), - Box::new(ql::Expression::Pred("getValue", vec![])), + Box::new(ql::Expression::Dot( + Box::new(ql::Expression::Var("this")), + "getValue", + vec![], + )), ), }; ql::Class { qldoc: Some(String::from("A token.")), name: "Token", is_abstract: false, - supertypes: vec![ql::Type::AtType("token"), ql::Type::Normal("AstNode")] + supertypes: vec![ql::Type::At(token_type), ql::Type::Normal("AstNode")] .into_iter() .collect(), characteristic_predicate: None, @@ -168,15 +175,14 @@ fn create_token_class<'a>() -> ql::Class<'a> { } // Creates the `ReservedWord` class. -fn create_reserved_word_class<'a>() -> ql::Class<'a> { - let db_name = "reserved_word"; +pub fn create_reserved_word_class(db_name: &str) -> ql::Class { let class_name = "ReservedWord"; - let get_a_primary_ql_class = create_get_a_primary_ql_class(&class_name); + let get_a_primary_ql_class = create_get_a_primary_ql_class(class_name); ql::Class { qldoc: Some(String::from("A reserved word.")), name: class_name, is_abstract: false, - supertypes: vec![ql::Type::AtType(db_name), ql::Type::Normal("Token")] + supertypes: vec![ql::Type::At(db_name), ql::Type::Normal("Token")] .into_iter() .collect(), characteristic_predicate: None, @@ -192,8 +198,8 @@ fn create_none_predicate<'a>( return_type: Option>, ) -> ql::Predicate<'a> { ql::Predicate { - qldoc: qldoc, - name: name, + qldoc, + name, overridden, return_type, formal_parameters: Vec::new(), @@ -203,7 +209,7 @@ fn create_none_predicate<'a>( /// Creates an overridden `getAPrimaryQlClass` predicate that returns the given /// name. -fn create_get_a_primary_ql_class<'a>(class_name: &'a str) -> ql::Predicate<'a> { +fn create_get_a_primary_ql_class(class_name: &str) -> ql::Predicate { ql::Predicate { qldoc: Some(String::from( "Gets the name of the primary QL class for this element.", @@ -225,7 +231,7 @@ fn create_get_a_primary_ql_class<'a>(class_name: &'a str) -> ql::Predicate<'a> { /// /// `def_table` - the name of the table that defines the entity and its location. /// `arity` - the total number of columns in the table -fn create_get_location_predicate<'a>(def_table: &'a str, arity: usize) -> ql::Predicate<'a> { +fn create_get_location_predicate(def_table: &str, arity: usize) -> ql::Predicate { ql::Predicate { qldoc: Some(String::from("Gets the location of this element.")), name: "getLocation", @@ -250,7 +256,7 @@ fn create_get_location_predicate<'a>(def_table: &'a str, arity: usize) -> ql::Pr /// # Arguments /// /// `def_table` - the name of the table that defines the entity and its text. -fn create_get_text_predicate<'a>(def_table: &'a str) -> ql::Predicate<'a> { +fn create_get_text_predicate(def_table: &str) -> ql::Predicate { ql::Predicate { qldoc: Some(String::from("Gets the text content of this element.")), name: "getText", @@ -341,13 +347,13 @@ fn create_field_getters<'a>( ) -> (ql::Predicate<'a>, Option>) { let return_type = match &field.type_info { node_types::FieldTypeInfo::Single(t) => { - Some(ql::Type::Normal(&nodes.get(&t).unwrap().ql_class_name)) + Some(ql::Type::Normal(&nodes.get(t).unwrap().ql_class_name)) } node_types::FieldTypeInfo::Multiple { types: _, dbscheme_union: _, ql_class, - } => Some(ql::Type::Normal(&ql_class)), + } => Some(ql::Type::Normal(ql_class)), node_types::FieldTypeInfo::ReservedWordInt(_) => Some(ql::Type::String), }; let formal_parameters = match &field.storage { @@ -383,13 +389,13 @@ fn create_field_getters<'a>( ( create_get_field_expr_for_column_storage( get_value_result_var_name, - &main_table_name, + main_table_name, column_index, main_table_arity, ), create_get_field_expr_for_column_storage( get_value_result_var_name, - &main_table_name, + main_table_name, column_index, main_table_arity, ), @@ -402,12 +408,12 @@ fn create_field_getters<'a>( } => ( create_get_field_expr_for_table_storage( get_value_result_var_name, - &field_table_name, + field_table_name, if *has_index { Some("i") } else { None }, ), create_get_field_expr_for_table_storage( get_value_result_var_name, - &field_table_name, + field_table_name, if *has_index { Some("_") } else { None }, ), ), @@ -434,15 +440,16 @@ fn create_field_getters<'a>( }) .collect(); ( - ql::Expression::Aggregate( - "exists", - vec![ql::FormalParameter { + ql::Expression::Aggregate { + name: "exists", + vars: vec![ql::FormalParameter { name: "value", param_type: ql::Type::Int, }], - Box::new(get_value), - Box::new(ql::Expression::Or(disjuncts)), - ), + range: Some(Box::new(get_value)), + expr: Box::new(ql::Expression::Or(disjuncts)), + second_expr: None, + }, // Since the getter returns a string and not an AstNode, it won't be part of getAFieldOrChild: None, ) @@ -452,11 +459,9 @@ fn create_field_getters<'a>( } }; let qldoc = match &field.name { - Some(name) => { - format!("Gets the node corresponding to the field `{}`.", name) - } + Some(name) => format!("Gets the node corresponding to the field `{}`.", name), None => { - if formal_parameters.len() == 0 { + if formal_parameters.is_empty() { "Gets the child of this node.".to_owned() } else { "Gets the `i`th child of this node.".to_owned() @@ -477,14 +482,8 @@ fn create_field_getters<'a>( } /// Converts the given node types into CodeQL classes wrapping the dbscheme. -pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec> { - let mut classes: Vec = vec![ - ql::TopLevel::Import("codeql.files.FileSystem"), - ql::TopLevel::Import("codeql.Locations"), - ql::TopLevel::Class(create_ast_node_class()), - ql::TopLevel::Class(create_token_class()), - ql::TopLevel::Class(create_reserved_word_class()), - ]; +pub fn convert_nodes(nodes: &node_types::NodeTypeMap) -> Vec { + let mut classes: Vec = Vec::new(); let mut token_kinds = BTreeSet::new(); for (type_name, node) in nodes { if let node_types::EntryKind::Token { .. } = &node.kind { @@ -500,7 +499,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec = BTreeSet::new(); - supertypes.insert(ql::Type::AtType(&node.dbscheme_name)); + supertypes.insert(ql::Type::At(&node.dbscheme_name)); supertypes.insert(ql::Type::Normal("Token")); classes.push(ql::TopLevel::Class(ql::Class { qldoc: Some(format!("A class representing `{}` tokens.", type_name.kind)), @@ -520,7 +519,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec(nodes: &'a node_types::NodeTypeMap) -> Vec = Vec::new(); @@ -580,7 +579,7 @@ pub fn convert_nodes<'a>(nodes: &'a node_types::NodeTypeMap) -> Vec std::io::Result { +pub fn read_node_types(prefix: &str, node_types_path: &Path) -> std::io::Result { let file = fs::File::open(node_types_path)?; - let node_types = serde_json::from_reader(file)?; - Ok(convert_nodes(&node_types)) + let node_types: Vec = serde_json::from_reader(file)?; + Ok(convert_nodes(prefix, &node_types)) } -pub fn read_node_types_str(node_types_json: &str) -> std::io::Result { - let node_types = serde_json::from_str(node_types_json)?; - Ok(convert_nodes(&node_types)) +pub fn read_node_types_str(prefix: &str, node_types_json: &str) -> std::io::Result { + let node_types: Vec = serde_json::from_str(node_types_json)?; + Ok(convert_nodes(prefix, &node_types)) } fn convert_type(node_type: &NodeType) -> TypeName { @@ -99,32 +99,33 @@ fn convert_type(node_type: &NodeType) -> TypeName { } } -fn convert_types(node_types: &Vec) -> Set { - let iter = node_types.iter().map(convert_type).collect(); - std::collections::BTreeSet::from(iter) +fn convert_types(node_types: &[NodeType]) -> Set { + node_types.iter().map(convert_type).collect() } -pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { +pub fn convert_nodes(prefix: &str, nodes: &[NodeInfo]) -> NodeTypeMap { let mut entries = NodeTypeMap::new(); let mut token_kinds = Set::new(); // First, find all the token kinds for node in nodes { - if node.subtypes.is_none() { - if node.fields.as_ref().map_or(0, |x| x.len()) == 0 && node.children.is_none() { - let type_name = TypeName { - kind: node.kind.clone(), - named: node.named, - }; - token_kinds.insert(type_name); - } + if node.subtypes.is_none() + && node.fields.as_ref().map_or(0, |x| x.len()) == 0 + && node.children.is_none() + { + let type_name = TypeName { + kind: node.kind.clone(), + named: node.named, + }; + token_kinds.insert(type_name); } } for node in nodes { let flattened_name = &node_type_name(&node.kind, node.named); - let dbscheme_name = escape_name(&flattened_name); + let dbscheme_name = escape_name(flattened_name); let ql_class_name = dbscheme_name_to_class_name(&dbscheme_name); + let dbscheme_name = format!("{}_{}", prefix, &dbscheme_name); if let Some(subtypes) = &node.subtypes { // It's a tree-sitter supertype node, for which we create a union // type. @@ -137,7 +138,7 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { dbscheme_name, ql_class_name, kind: EntryKind::Union { - members: convert_types(&subtypes), + members: convert_types(subtypes), }, }, ); @@ -150,6 +151,8 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { named: node.named, }; let table_name = escape_name(&(format!("{}_def", &flattened_name))); + let table_name = format!("{}_{}", prefix, &table_name); + let mut fields = Vec::new(); // If the type also has fields or children, then we create either @@ -157,6 +160,7 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { if let Some(node_fields) = &node.fields { for (field_name, field_info) in node_fields { add_field( + prefix, &type_name, Some(field_name.to_string()), field_info, @@ -167,7 +171,14 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { } if let Some(children) = &node.children { // Treat children as if they were a field called 'child'. - add_field(&type_name, None, children, &mut fields, &token_kinds); + add_field( + prefix, + &type_name, + None, + children, + &mut fields, + &token_kinds, + ); } entries.insert( type_name, @@ -188,13 +199,13 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { counter += 1; let unprefixed_name = node_type_name(&type_name.kind, true); Entry { - dbscheme_name: escape_name(&format!("token_{}", &unprefixed_name)), + dbscheme_name: escape_name(&format!("{}_token_{}", &prefix, &unprefixed_name)), ql_class_name: dbscheme_name_to_class_name(&escape_name(&unprefixed_name)), kind: EntryKind::Token { kind_id: counter }, } } else { Entry { - dbscheme_name: "reserved_word".to_owned(), + dbscheme_name: format!("{}_reserved_word", &prefix), ql_class_name: "ReservedWord".to_owned(), kind: EntryKind::Token { kind_id: 0 }, } @@ -205,6 +216,7 @@ pub fn convert_nodes(nodes: &Vec) -> NodeTypeMap { } fn add_field( + prefix: &str, parent_type_name: &TypeName, field_name: Option, field_info: &FieldInfo, @@ -221,7 +233,8 @@ fn add_field( // Put the field in an auxiliary table. let has_index = field_info.multiple; let field_table_name = escape_name(&format!( - "{}_{}", + "{}_{}_{}", + &prefix, parent_flattened_name, &name_for_field_or_child(&field_name) )); @@ -240,13 +253,11 @@ fn add_field( // All possible types for this field are reserved words. The db // representation will be an `int` with a `case @foo.field = ...` to // enumerate the possible values. - let mut counter = 0; let mut field_token_ints: BTreeMap = BTreeMap::new(); - for t in converted_types { + for (counter, t) in converted_types.into_iter().enumerate() { let dbscheme_variant_name = - escape_name(&format!("{}_{}", parent_flattened_name, t.kind)); + escape_name(&format!("{}_{}_{}", &prefix, parent_flattened_name, t.kind)); field_token_ints.insert(t.kind.to_owned(), (counter, dbscheme_variant_name)); - counter += 1; } FieldTypeInfo::ReservedWordInt(field_token_ints) } else if field_info.types.len() == 1 { @@ -256,7 +267,8 @@ fn add_field( FieldTypeInfo::Multiple { types: converted_types, dbscheme_union: format!( - "{}_{}_type", + "{}_{}_{}_type", + &prefix, &parent_flattened_name, &name_for_field_or_child(&field_name) ), @@ -316,7 +328,7 @@ fn node_type_name(kind: &str, named: bool) -> String { } } -const RESERVED_KEYWORDS: [&'static str; 14] = [ +const RESERVED_KEYWORDS: [&str; 14] = [ "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype", "type", "unique", "varchar", ]; @@ -380,6 +392,23 @@ fn escape_name(name: &str) -> String { result } +pub fn to_snake_case(word: &str) -> String { + let mut prev_upper = true; + let mut result = String::new(); + for c in word.chars() { + if c.is_uppercase() { + if !prev_upper { + result.push('_') + } + prev_upper = true; + result.push(c.to_ascii_lowercase()); + } else { + prev_upper = false; + result.push(c); + } + } + result +} /// Given a valid dbscheme name (i.e. in snake case), produces the equivalent QL /// name (i.e. in CamelCase). For example, "foo_bar_baz" becomes "FooBarBaz". fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String { @@ -402,3 +431,10 @@ fn dbscheme_name_to_class_name(dbscheme_name: &str) -> String { .collect::>() .join("") } + +#[test] +fn to_snake_case_test() { + assert_eq!("python", to_snake_case("Python")); + assert_eq!("yaml", to_snake_case("YAML")); + assert_eq!("set_literal", to_snake_case("SetLiteral")); +} diff --git a/ql/consistency-queries/BuildinsConsistency.ql b/ql/consistency-queries/BuildinsConsistency.ql new file mode 100644 index 00000000000..d70e9ed077a --- /dev/null +++ b/ql/consistency-queries/BuildinsConsistency.ql @@ -0,0 +1 @@ +import codeql_ql.ast.internal.Builtins::BuildinsConsistency diff --git a/ql/src/codeql/files/FileSystem.qll b/ql/src/codeql/files/FileSystem.qll index 7573ff9e905..aca3c2fe0ac 100644 --- a/ql/src/codeql/files/FileSystem.qll +++ b/ql/src/codeql/files/FileSystem.qll @@ -9,10 +9,10 @@ abstract class Container extends @container { Container getAChildContainer() { this = result.getParentContainer() } /** Gets a file in this container. */ - File getAFile() { result = getAChildContainer() } + File getAFile() { result = this.getAChildContainer() } /** Gets a sub-folder in this container. */ - Folder getAFolder() { result = getAChildContainer() } + Folder getAFolder() { result = this.getAChildContainer() } /** * Gets the absolute, canonical path of this container, using forward slashes @@ -58,7 +58,7 @@ abstract class Container extends @container { * */ string getBaseName() { - result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) + result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1) } /** @@ -84,17 +84,19 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""gz" * */ - string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) } + string getExtension() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) + } /** Gets the file in this container that has the given `baseName`, if any. */ File getFile(string baseName) { - result = getAFile() and + result = this.getAFile() and result.getBaseName() = baseName } /** Gets the sub-folder in this container that has the given `baseName`, if any. */ Folder getFolder(string baseName) { - result = getAFolder() and + result = this.getAFolder() and result.getBaseName() = baseName } @@ -111,7 +113,7 @@ abstract class Container extends @container { */ string getRelativePath() { exists(string absPath, string pref | - absPath = getAbsolutePath() and sourceLocationPrefix(pref) + absPath = this.getAbsolutePath() and sourceLocationPrefix(pref) | absPath = pref and result = "" or @@ -137,7 +139,9 @@ abstract class Container extends @container { * "/tmp/x.tar.gz""x.tar" * */ - string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) } + string getStem() { + result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) + } /** * Gets a URL representing the location of this container. @@ -151,34 +155,34 @@ abstract class Container extends @container { * * This is the absolute path of the container. */ - string toString() { result = getAbsolutePath() } + string toString() { result = this.getAbsolutePath() } } /** A folder. */ class Folder extends Container, @folder { - override string getAbsolutePath() { folders(this, result, _) } + override string getAbsolutePath() { folders(this, result) } /** Gets the URL of this folder. */ - override string getURL() { result = "folder://" + getAbsolutePath() } + override string getURL() { result = "folder://" + this.getAbsolutePath() } } /** A file. */ class File extends Container, @file { - override string getAbsolutePath() { files(this, result, _, _, _) } + override string getAbsolutePath() { files(this, result) } /** Gets the URL of this file. */ override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" } /** Gets a token in this file. */ - private Generated::Token getAToken() { result.getLocation().getFile() = this } + private QL::Token getAToken() { result.getLocation().getFile() = this } /** Holds if `line` contains a token. */ private predicate line(int line, boolean comment) { - exists(Generated::Token token, Location l | + exists(QL::Token token, Location l | token = this.getAToken() and l = token.getLocation() and line in [l.getStartLine() .. l.getEndLine()] and - if token instanceof @token_block_comment or token instanceof @token_line_comment + if token instanceof @ql_token_block_comment or token instanceof @ql_token_line_comment then comment = true else comment = false ) @@ -194,5 +198,5 @@ class File extends Container, @file { int getNumberOfLinesOfComments() { result = count(int line | this.line(line, true)) } /** Holds if this file was extracted from ordinary source code. */ - predicate fromSource() { files(this, _, _, _, 1) } + predicate fromSource() { any() } } diff --git a/ql/src/codeql_ql/ast/Ast.qll b/ql/src/codeql_ql/ast/Ast.qll index 2c93da2af47..bb819b59a53 100644 --- a/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/src/codeql_ql/ast/Ast.qll @@ -19,15 +19,15 @@ private string stringIndexedMember(string name, string index) { /** An AST node of a QL program */ class AstNode extends TAstNode { - string toString() { result = getAPrimaryQlClass() } + string toString() { result = this.getAPrimaryQlClass() } /** * Gets the location of the AST node. */ cached Location getLocation() { - exists(Generated::AstNode node | not node instanceof Generated::ParExpr | - node = toGenerated(this) and + exists(QL::AstNode node | not node instanceof QL::ParExpr | + node = toQL(this) and result = node.getLocation() ) } @@ -35,8 +35,8 @@ class AstNode extends TAstNode { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - if exists(getLocation()) - then getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + if exists(this.getLocation()) + then this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) else ( filepath = "" and startline = 0 and @@ -70,7 +70,10 @@ class AstNode extends TAstNode { predicate hasAnnotation(string name) { this.getAnAnnotation().getName() = name } /** Gets an annotation of this AST node. */ - Annotation getAnAnnotation() { toGenerated(this).getParent() = toGenerated(result).getParent() } + cached + Annotation getAnAnnotation() { + toQL(this).getParent() = pragma[only_bind_out](toQL(result)).getParent() + } /** * Gets the predicate that contains this AST node. @@ -78,13 +81,13 @@ class AstNode extends TAstNode { pragma[noinline] Predicate getEnclosingPredicate() { not this instanceof Predicate and - toGenerated(result) = toGenerated(this).getParent+() + toQL(result) = toQL(this).getParent+() } } /** A toplevel QL program, i.e. a file. */ class TopLevel extends TTopLevel, AstNode { - Generated::Ql file; + QL::Ql file; TopLevel() { this = TTopLevel(file) } @@ -92,12 +95,10 @@ class TopLevel extends TTopLevel, AstNode { * Gets a member from contained in this top-level module. * Includes private members. */ - ModuleMember getAMember() { result = getMember(_) } + ModuleMember getAMember() { result = this.getMember(_) } /** Gets the `i`'th member of this top-level module. */ - ModuleMember getMember(int i) { - toGenerated(result) = file.getChild(i).(Generated::ModuleMember).getChild(_) - } + ModuleMember getMember(int i) { toQL(result) = file.getChild(i).(QL::ModuleMember).getChild(_) } /** Gets a top-level import in this module. */ Import getAnImport() { result = this.getAMember() } @@ -138,7 +139,7 @@ class TopLevel extends TTopLevel, AstNode { } class QLDoc extends TQLDoc, AstNode { - Generated::Qldoc qldoc; + QL::Qldoc qldoc; QLDoc() { this = TQLDoc(qldoc) } @@ -151,29 +152,27 @@ class QLDoc extends TQLDoc, AstNode { * The `from, where, select` part of a QL query. */ class Select extends TSelect, AstNode { - Generated::Select sel; + QL::Select sel; Select() { this = TSelect(sel) } /** * Gets the `i`th variable in the `from` clause. */ - VarDecl getVarDecl(int i) { toGenerated(result) = sel.getChild(i) } + VarDecl getVarDecl(int i) { toQL(result) = sel.getChild(i) } /** * Gets the formula in the `where`. */ - Formula getWhere() { toGenerated(result) = sel.getChild(_) } + Formula getWhere() { toQL(result) = sel.getChild(_) } /** * Gets the `i`th expression in the `select` clause. */ - Expr getExpr(int i) { toGenerated(result) = sel.getChild(_).(Generated::AsExprs).getChild(i) } + Expr getExpr(int i) { toQL(result) = sel.getChild(_).(QL::AsExprs).getChild(i) } // TODO: This gets the `i`th order-by, but some expressions might not have an order-by. - Expr getOrderBy(int i) { - toGenerated(result) = sel.getChild(_).(Generated::OrderBys).getChild(i).getChild(0) - } + Expr getOrderBy(int i) { toQL(result) = sel.getChild(_).(QL::OrderBys).getChild(i).getChild(0) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -201,13 +200,13 @@ class PredicateOrBuiltin extends TPredOrBuiltin, AstNode { Type getReturnType() { none() } - int getArity() { result = count(getParameterType(_)) } + int getArity() { result = count(int i | exists(this.getParameterType(i))) } predicate isPrivate() { none() } } class BuiltinPredicate extends PredicateOrBuiltin, TBuiltin { - override string toString() { result = getName() } + override string toString() { result = this.getName() } override string getAPrimaryQlClass() { result = "BuiltinPredicate" } } @@ -268,7 +267,7 @@ class Predicate extends TPredicate, AstNode, PredicateOrBuiltin, Declaration { */ override int getArity() { not this.(ClasslessPredicate).getAlias() instanceof PredicateExpr and - result = count(getParameter(_)) + result = count(this.getParameter(_)) or exists(PredicateExpr alias | alias = this.(ClasslessPredicate).getAlias() | result = alias.getArity() @@ -278,7 +277,7 @@ class Predicate extends TPredicate, AstNode, PredicateOrBuiltin, Declaration { /** * Holds if this predicate is private. */ - override predicate isPrivate() { hasAnnotation("private") } + override predicate isPrivate() { this.hasAnnotation("private") } /** * Gets the return type (if any) of the predicate. @@ -306,7 +305,7 @@ class Predicate extends TPredicate, AstNode, PredicateOrBuiltin, Declaration { * A relation in the database. */ class Relation extends TDBRelation, AstNode, Declaration { - Generated::DbTable table; + QL::DbTable table; Relation() { this = TDBRelation(table) } @@ -315,9 +314,9 @@ class Relation extends TDBRelation, AstNode, Declaration { */ override string getName() { result = table.getTableName().getChild().getValue() } - private Generated::DbColumn getColumn(int i) { + private QL::DbColumn getColumn(int i) { result = - rank[i + 1](Generated::DbColumn column, int child | + rank[i + 1](QL::DbColumn column, int child | table.getChild(child) = column | column order by child @@ -325,18 +324,18 @@ class Relation extends TDBRelation, AstNode, Declaration { } /** Gets the `i`th parameter name */ - string getParameterName(int i) { result = getColumn(i).getColName().getValue() } + string getParameterName(int i) { result = this.getColumn(i).getColName().getValue() } /** Gets the `i`th parameter type */ string getParameterType(int i) { // TODO: This is just using the name of the type, not the actual type. Checkout Type.qll - result = getColumn(i).getColType().getChild().(Generated::Token).getValue() + result = this.getColumn(i).getColType().getChild().(QL::Token).getValue() } /** * Gets the number of parameters. */ - int getArity() { result = count(getColumn(_)) } + int getArity() { result = count(this.getColumn(_)) } override string getAPrimaryQlClass() { result = "Relation" } } @@ -345,7 +344,7 @@ class Relation extends TDBRelation, AstNode, Declaration { * An expression that refers to a predicate, e.g. `BasicBlock::succ/2`. */ class PredicateExpr extends TPredicateExpr, AstNode { - Generated::PredicateExpr pe; + QL::PredicateExpr pe; PredicateExpr() { this = TPredicateExpr(pe) } @@ -356,7 +355,7 @@ class PredicateExpr extends TPredicateExpr, AstNode { * E.g. for `BasicBlock::succ/2` the result is "succ". */ string getName() { - exists(Generated::AritylessPredicateExpr ape, Generated::LiteralId id | + exists(QL::AritylessPredicateExpr ape, QL::LiteralId id | ape.getParent() = pe and id.getParent() = ape and result = id.getValue() @@ -368,7 +367,7 @@ class PredicateExpr extends TPredicateExpr, AstNode { * E.g. for `BasicBlock::succ/2` the result is 2. */ int getArity() { - exists(Generated::Integer i | + exists(QL::Integer i | i.getParent() = pe and result = i.getValue().toInt() ) @@ -379,9 +378,9 @@ class PredicateExpr extends TPredicateExpr, AstNode { * E.g. for `BasicBlock::succ/2` the result is a `ModuleExpr` representing "BasicBlock". */ ModuleExpr getQualifier() { - exists(Generated::AritylessPredicateExpr ape | + exists(QL::AritylessPredicateExpr ape | ape.getParent() = pe and - toGenerated(result).getParent() = ape + toQL(result).getParent() = ape ) } @@ -403,7 +402,7 @@ class PredicateExpr extends TPredicateExpr, AstNode { * A classless predicate. */ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclaration { - Generated::ClasslessPredicate pred; + QL::ClasslessPredicate pred; ClasslessPredicate() { this = TClasslessPredicate(pred) } @@ -413,30 +412,26 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati * The result is either a `PredicateExpr` or `HigherOrderFormula`. */ final AstNode getAlias() { - exists(Generated::PredicateAliasBody alias | + exists(QL::PredicateAliasBody alias | alias.getParent() = pred and - toGenerated(result).getParent() = alias + toQL(result).getParent() = alias ) or - toGenerated(result) = pred.getChild(_).(Generated::HigherOrderTerm) + toQL(result) = pred.getChild(_).(QL::HigherOrderTerm) } override string getAPrimaryQlClass() { result = "ClasslessPredicate" } - override Formula getBody() { toGenerated(result) = pred.getChild(_).(Generated::Body).getChild() } + override Formula getBody() { toQL(result) = pred.getChild(_).(QL::Body).getChild() } override string getName() { result = pred.getName().getValue() } override VarDecl getParameter(int i) { - toGenerated(result) = - rank[i + 1](Generated::VarDecl decl, int index | - decl = pred.getChild(index) - | - decl order by index - ) + toQL(result) = + rank[i + 1](QL::VarDecl decl, int index | decl = pred.getChild(index) | decl order by index) } - override TypeExpr getReturnTypeExpr() { toGenerated(result) = pred.getReturnType() } + override TypeExpr getReturnTypeExpr() { toQL(result) = pred.getReturnType() } override AstNode getAChild(string pred_name) { result = Predicate.super.getAChild(pred_name) @@ -457,13 +452,13 @@ class ClasslessPredicate extends TClasslessPredicate, Predicate, ModuleDeclarati * A predicate in a class. */ class ClassPredicate extends TClassPredicate, Predicate { - Generated::MemberPredicate pred; + QL::MemberPredicate pred; ClassPredicate() { this = TClassPredicate(pred) } override string getName() { result = pred.getName().getValue() } - override Formula getBody() { toGenerated(result) = pred.getChild(_).(Generated::Body).getChild() } + override Formula getBody() { toQL(result) = pred.getChild(_).(QL::Body).getChild() } override string getAPrimaryQlClass() { result = "ClassPredicate" } @@ -472,25 +467,21 @@ class ClassPredicate extends TClassPredicate, Predicate { /** * Holds if this predicate is annotated as overriding another predicate. */ - predicate isOverride() { hasAnnotation("override") } + predicate isOverride() { this.hasAnnotation("override") } override VarDecl getParameter(int i) { - toGenerated(result) = - rank[i + 1](Generated::VarDecl decl, int index | - decl = pred.getChild(index) - | - decl order by index - ) + toQL(result) = + rank[i + 1](QL::VarDecl decl, int index | decl = pred.getChild(index) | decl order by index) } /** * Gets the type representing this class. */ - override ClassType getDeclaringType() { result.getDeclaration() = getParent() } + override ClassType getDeclaringType() { result.getDeclaration() = this.getParent() } predicate overrides(ClassPredicate other) { predOverrides(this, other) } - override TypeExpr getReturnTypeExpr() { toGenerated(result) = pred.getReturnType() } + override TypeExpr getReturnTypeExpr() { toQL(result) = pred.getReturnType() } override AstNode getAChild(string pred_name) { result = super.getAChild(pred_name) @@ -507,15 +498,15 @@ class ClassPredicate extends TClassPredicate, Predicate { * A characteristic predicate of a class. */ class CharPred extends TCharPred, Predicate { - Generated::Charpred pred; + QL::Charpred pred; CharPred() { this = TCharPred(pred) } override string getAPrimaryQlClass() { result = "CharPred" } - override Formula getBody() { toGenerated(result) = pred.getBody() } + override Formula getBody() { toQL(result) = pred.getBody() } - override string getName() { result = getParent().(Class).getName() } + override string getName() { result = this.getParent().(Class).getName() } override AstNode getAChild(string pred_name) { result = super.getAChild(pred_name) @@ -523,7 +514,7 @@ class CharPred extends TCharPred, Predicate { pred_name = directMember("getBody") and result = this.getBody() } - override ClassType getDeclaringType() { result.getDeclaration() = getParent() } + override ClassType getDeclaringType() { result.getDeclaration() = this.getParent() } } /** @@ -545,11 +536,11 @@ class VarDef extends TVarDef, AstNode { * A variable declaration, with a type and a name. */ class VarDecl extends TVarDecl, VarDef, Declaration { - Generated::VarDecl var; + QL::VarDecl var; VarDecl() { this = TVarDecl(var) } - override string getName() { result = var.getChild(1).(Generated::VarName).getChild().getValue() } + override string getName() { result = var.getChild(1).(QL::VarName).getChild().getValue() } override Type getType() { result = this.getTypeExpr().getResolvedType() } @@ -558,15 +549,15 @@ class VarDecl extends TVarDecl, VarDef, Declaration { /** * Gets the type part of this variable declaration. */ - TypeExpr getTypeExpr() { toGenerated(result) = var.getChild(0) } + TypeExpr getTypeExpr() { toQL(result) = var.getChild(0) } /** * Holds if this variable declaration is a private field on a class. */ predicate isPrivate() { - exists(Generated::ClassMember member | - var = member.getChild(_).(Generated::Field).getChild() and - member.getAFieldOrChild().(Generated::Annotation).getName().getValue() = "private" + exists(QL::ClassMember member | + var = member.getChild(_).(QL::Field).getChild() and + member.getAFieldOrChild().(QL::Annotation).getName().getValue() = "private" ) } @@ -591,7 +582,7 @@ class VarDecl extends TVarDecl, VarDef, Declaration { * A type reference, such as `DataFlow::Node`. */ class TypeExpr extends TType, AstNode { - Generated::TypeExpr type; + QL::TypeExpr type; TypeExpr() { this = TType(type) } @@ -606,26 +597,26 @@ class TypeExpr extends TType, AstNode { string getClassName() { result = type.getName().getValue() or - result = type.getChild().(Generated::PrimitiveType).getValue() + result = type.getChild().(QL::PrimitiveType).getValue() or - result = type.getChild().(Generated::Dbtype).getValue() + result = type.getChild().(QL::Dbtype).getValue() } /** * Holds if this type is a primitive such as `string` or `int`. */ - predicate isPrimitive() { type.getChild() instanceof Generated::PrimitiveType } + predicate isPrimitive() { type.getChild() instanceof QL::PrimitiveType } /** * Holds if this type is a db-type. */ - predicate isDBType() { type.getChild() instanceof Generated::Dbtype } + predicate isDBType() { type.getChild() instanceof QL::Dbtype } /** * Gets the module of the type, if it exists. * E.g. `DataFlow` in `DataFlow::Node`. */ - ModuleExpr getModule() { toGenerated(result) = type.getChild() } + ModuleExpr getModule() { toQL(result) = type.getChild() } /** * Gets the type that this type reference refers to. @@ -643,33 +634,27 @@ class TypeExpr extends TType, AstNode { * A QL module. */ class Module extends TModule, ModuleDeclaration { - Generated::Module mod; + QL::Module mod; Module() { this = TModule(mod) } override string getAPrimaryQlClass() { result = "Module" } - override string getName() { result = mod.getName().(Generated::ModuleName).getChild().getValue() } + override string getName() { result = mod.getName().(QL::ModuleName).getChild().getValue() } /** * Gets a member of the module. */ - AstNode getAMember() { - toGenerated(result) = mod.getChild(_).(Generated::ModuleMember).getChild(_) - } + AstNode getAMember() { toQL(result) = mod.getChild(_).(QL::ModuleMember).getChild(_) } - AstNode getMember(int i) { - toGenerated(result) = mod.getChild(i).(Generated::ModuleMember).getChild(_) - } + AstNode getMember(int i) { toQL(result) = mod.getChild(i).(QL::ModuleMember).getChild(_) } QLDoc getQLDocFor(AstNode m) { exists(int i | result = this.getMember(i) and m = this.getMember(i + 1)) } /** Gets the module expression that this module is an alias for, if any. */ - ModuleExpr getAlias() { - toGenerated(result) = mod.getAFieldOrChild().(Generated::ModuleAliasBody).getChild() - } + ModuleExpr getAlias() { toQL(result) = mod.getAFieldOrChild().(QL::ModuleAliasBody).getChild() } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -685,7 +670,7 @@ class Module extends TModule, ModuleDeclaration { */ class ModuleMember extends TModuleMember, AstNode { /** Holds if this member is declared as `private`. */ - predicate isPrivate() { hasAnnotation("private") } + predicate isPrivate() { this.hasAnnotation("private") } } /** A declaration. E.g. a class, type, predicate, newtype... */ @@ -720,7 +705,7 @@ class TypeDeclaration extends TTypeDeclaration, Declaration { } * A QL class. */ class Class extends TClass, TypeDeclaration, ModuleDeclaration { - Generated::Dataclass cls; + QL::Dataclass cls; Class() { this = TClass(cls) } @@ -731,14 +716,11 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration { /** * Gets the charateristic predicate for this class. */ - CharPred getCharPred() { - toGenerated(result) = cls.getChild(_).(Generated::ClassMember).getChild(_) - } + CharPred getCharPred() { toQL(result) = cls.getChild(_).(QL::ClassMember).getChild(_) } AstNode getMember(int i) { - toGenerated(result) = cls.getChild(i).(Generated::ClassMember).getChild(_) or - toGenerated(result) = - cls.getChild(i).(Generated::ClassMember).getChild(_).(Generated::Field).getChild() + toQL(result) = cls.getChild(i).(QL::ClassMember).getChild(_) or + toQL(result) = cls.getChild(i).(QL::ClassMember).getChild(_).(QL::Field).getChild() } QLDoc getQLDocFor(AstNode m) { @@ -749,14 +731,14 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration { * Gets a predicate in this class. */ ClassPredicate getAClassPredicate() { - toGenerated(result) = cls.getChild(_).(Generated::ClassMember).getChild(_) + toQL(result) = cls.getChild(_).(QL::ClassMember).getChild(_) } /** * Gets predicate `name` implemented in this class. */ ClassPredicate getClassPredicate(string name) { - result = getAClassPredicate() and + result = this.getAClassPredicate() and result.getName() = name } @@ -764,24 +746,24 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration { * Gets a field in this class. */ VarDecl getAField() { - toGenerated(result) = - cls.getChild(_).(Generated::ClassMember).getChild(_).(Generated::Field).getChild() + toQL(result) = cls.getChild(_).(QL::ClassMember).getChild(_).(QL::Field).getChild() } /** * Gets a super-type referenced in the `extends` part of the class declaration. */ - TypeExpr getASuperType() { toGenerated(result) = cls.getExtends(_) } + TypeExpr getASuperType() { toQL(result) = cls.getExtends(_) } + + /** + * Gets a type referenced in the `instanceof` part of the class declaration. + */ + TypeExpr getAnInstanceofType() { toQL(result) = cls.getInstanceof(_) } /** Gets the type that this class is defined to be an alias of. */ - TypeExpr getAliasType() { - toGenerated(result) = cls.getChild(_).(Generated::TypeAliasBody).getChild() - } + TypeExpr getAliasType() { toQL(result) = cls.getChild(_).(QL::TypeAliasBody).getChild() } /** Gets the type of one of the members that this class is defined to be a union of. */ - TypeExpr getUnionMember() { - toGenerated(result) = cls.getChild(_).(Generated::TypeUnionBody).getChild(_) - } + TypeExpr getUnionMember() { toQL(result) = cls.getChild(_).(QL::TypeUnionBody).getChild(_) } /** Gets the class type defined by this class declaration. */ Type getType() { result.getDeclaration() = this } @@ -804,13 +786,16 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration { result = this.getClassPredicate(name) ) } + + /** Holds if this class is abstract. */ + predicate isAbstract() { hasAnnotation("abstract") } } /** * A `newtype Foo` declaration. */ class NewType extends TNewType, TypeDeclaration, ModuleDeclaration { - Generated::Datatype type; + QL::Datatype type; NewType() { this = TNewType(type) } @@ -821,7 +806,7 @@ class NewType extends TNewType, TypeDeclaration, ModuleDeclaration { /** * Gets a branch in this `newtype`. */ - NewTypeBranch getABranch() { toGenerated(result) = type.getChild().getChild(_) } + NewTypeBranch getABranch() { toQL(result) = type.getChild().getChild(_) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -835,7 +820,7 @@ class NewType extends TNewType, TypeDeclaration, ModuleDeclaration { * E.g. `Bar()` or `Baz()` in `newtype Foo = Bar() or Baz()`. */ class NewTypeBranch extends TNewTypeBranch, PredicateOrBuiltin, TypeDeclaration { - Generated::DatatypeBranch branch; + QL::DatatypeBranch branch; NewTypeBranch() { this = TNewTypeBranch(branch) } @@ -845,16 +830,12 @@ class NewTypeBranch extends TNewTypeBranch, PredicateOrBuiltin, TypeDeclaration /** Gets a field in this branch. */ VarDecl getField(int i) { - toGenerated(result) = - rank[i + 1](Generated::VarDecl var, int index | - var = branch.getChild(index) - | - var order by index - ) + toQL(result) = + rank[i + 1](QL::VarDecl var, int index | var = branch.getChild(index) | var order by index) } /** Gets the body of this branch. */ - Formula getBody() { toGenerated(result) = branch.getChild(_).(Generated::Body).getChild() } + Formula getBody() { toQL(result) = branch.getChild(_).(QL::Body).getChild() } override NewTypeBranchType getReturnType() { result.getDeclaration() = this } @@ -866,7 +847,7 @@ class NewTypeBranch extends TNewTypeBranch, PredicateOrBuiltin, TypeDeclaration override predicate isPrivate() { this.getNewType().isPrivate() } - override QLDoc getQLDoc() { toGenerated(result) = branch.getChild(_) } + override QLDoc getQLDoc() { toQL(result) = branch.getChild(_) } NewType getNewType() { result.getABranch() = this } @@ -894,7 +875,7 @@ class Call extends TCall, Expr, Formula { } /** Gets an argument of this call, if any. */ - final Expr getAnArgument() { result = getArgument(_) } + final Expr getAnArgument() { result = this.getArgument(_) } PredicateOrBuiltin getTarget() { resolveCall(this, result) } @@ -917,35 +898,31 @@ class Call extends TCall, Expr, Formula { * E.g. `foo()` or `Foo::bar()`. */ class PredicateCall extends TPredicateCall, Call { - Generated::CallOrUnqualAggExpr expr; + QL::CallOrUnqualAggExpr expr; PredicateCall() { this = TPredicateCall(expr) } override Expr getArgument(int i) { - exists(Generated::CallBody body | body.getParent() = expr | - toGenerated(result) = body.getChild(i) - ) + exists(QL::CallBody body | body.getParent() = expr | toQL(result) = body.getChild(i)) } final override ModuleExpr getQualifier() { - exists(Generated::AritylessPredicateExpr ape | + exists(QL::AritylessPredicateExpr ape | ape.getParent() = expr and - toGenerated(result).getParent() = ape + toQL(result).getParent() = ape ) } override string getAPrimaryQlClass() { result = "PredicateCall" } - override predicate isClosure(string kind) { - kind = expr.getChild(_).(Generated::Closure).getValue() - } + override predicate isClosure(string kind) { kind = expr.getChild(_).(QL::Closure).getValue() } /** * Gets the name of the predicate called. * E.g. for `foo()` the result is "foo". */ string getPredicateName() { - result = expr.getChild(0).(Generated::AritylessPredicateExpr).getName().getValue() + result = expr.getChild(0).(QL::AritylessPredicateExpr).getName().getValue() } override AstNode getAChild(string pred) { @@ -962,7 +939,7 @@ class PredicateCall extends TPredicateCall, Call { * E.g. `foo.bar()`. */ class MemberCall extends TMemberCall, Call { - Generated::QualifiedExpr expr; + QL::QualifiedExpr expr; MemberCall() { this = TMemberCall(expr) } @@ -972,12 +949,10 @@ class MemberCall extends TMemberCall, Call { * Gets the name of the member called. * E.g. for `foo.bar()` the result is "bar". */ - string getMemberName() { - result = expr.getChild(_).(Generated::QualifiedRhs).getName().getValue() - } + string getMemberName() { result = expr.getChild(_).(QL::QualifiedRhs).getName().getValue() } override predicate isClosure(string kind) { - kind = expr.getChild(_).(Generated::QualifiedRhs).getChild(_).(Generated::Closure).getValue() + kind = expr.getChild(_).(QL::QualifiedRhs).getChild(_).(QL::Closure).getValue() } /** @@ -985,14 +960,12 @@ class MemberCall extends TMemberCall, Call { * * Only yields a result if this is actually a `super` call. */ - TypeExpr getSuperType() { - toGenerated(result) = expr.getChild(_).(Generated::SuperRef).getChild(0) - } + TypeExpr getSuperType() { toQL(result) = expr.getChild(_).(QL::SuperRef).getChild(0) } override Expr getArgument(int i) { result = rank[i + 1](Expr e, int index | - toGenerated(e) = expr.getChild(_).(Generated::QualifiedRhs).getChild(index) + toQL(e) = expr.getChild(_).(QL::QualifiedRhs).getChild(index) | e order by index ) @@ -1002,7 +975,7 @@ class MemberCall extends TMemberCall, Call { * Gets the base of the member call. * E.g. for `foo.(Bar).baz()` the result is `foo.(Bar)`. */ - Expr getBase() { toGenerated(result) = expr.getChild(0) } + Expr getBase() { toQL(result) = expr.getChild(0) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1019,7 +992,7 @@ class MemberCall extends TMemberCall, Call { * A call to the special `none()` predicate. */ class NoneCall extends TNoneCall, Call, Formula { - Generated::SpecialCall call; + QL::SpecialCall call; NoneCall() { this = TNoneCall(call) } @@ -1032,7 +1005,7 @@ class NoneCall extends TNoneCall, Call, Formula { * A call to the special `any()` predicate. */ class AnyCall extends TAnyCall, Call { - Generated::Aggregate agg; + QL::Aggregate agg; AnyCall() { this = TAnyCall(agg) } @@ -1043,7 +1016,7 @@ class AnyCall extends TAnyCall, Call { * An inline cast, e.g. `foo.(Bar)`. */ class InlineCast extends TInlineCast, Expr { - Generated::QualifiedExpr expr; + QL::QualifiedExpr expr; InlineCast() { this = TInlineCast(expr) } @@ -1053,9 +1026,7 @@ class InlineCast extends TInlineCast, Expr { * Gets the type being cast to. * E.g. for `foo.(Bar)` the result is `Bar`. */ - TypeExpr getTypeExpr() { - toGenerated(result) = expr.getChild(_).(Generated::QualifiedRhs).getChild(_) - } + TypeExpr getTypeExpr() { toQL(result) = expr.getChild(_).(QL::QualifiedRhs).getChild(_) } override Type getType() { result = this.getTypeExpr().getResolvedType() } @@ -1063,7 +1034,7 @@ class InlineCast extends TInlineCast, Expr { * Gets the expression being cast. * E.g. for `foo.(Bar)` the result is `foo`. */ - Expr getBase() { toGenerated(result) = expr.getChild(0) } + Expr getBase() { toQL(result) = expr.getChild(0) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1084,7 +1055,7 @@ class ModuleRef extends AstNode, TModuleRef { * An import statement. */ class Import extends TImport, ModuleMember, ModuleRef { - Generated::ImportDirective imp; + QL::ImportDirective imp; Import() { this = TImport(imp) } @@ -1097,7 +1068,7 @@ class Import extends TImport, ModuleMember, ModuleRef { * import semmle.javascript.dataflow.Configuration as Flow * ``` */ - string importedAs() { result = imp.getChild(1).(Generated::ModuleName).getChild().getValue() } + string importedAs() { result = imp.getChild(1).(QL::ModuleName).getChild().getValue() } /** * Gets the `i`th selected name from the imported module. @@ -1106,7 +1077,7 @@ class Import extends TImport, ModuleMember, ModuleRef { * It is true that `getSelectionName(0) = "Baz"` and `getSelectionName(1) = "Qux"`. */ string getSelectionName(int i) { - result = imp.getChild(0).(Generated::ImportModuleExpr).getName(i).getValue() + result = imp.getChild(0).(QL::ImportModuleExpr).getName(i).getValue() } /** @@ -1116,7 +1087,7 @@ class Import extends TImport, ModuleMember, ModuleRef { * It is true that `getQualifiedName(0) = "foo"` and `getQualifiedName(1) = "bar"`. */ string getQualifiedName(int i) { - result = imp.getChild(0).(Generated::ImportModuleExpr).getChild().getName(i).getValue() + result = imp.getChild(0).(QL::ImportModuleExpr).getChild().getName(i).getValue() } final override FileOrModule getResolvedModule() { resolve(this, result) } @@ -1127,14 +1098,14 @@ class Formula extends TFormula, AstNode { } /** An `and` formula, with 2 or more operands. */ class Conjunction extends TConjunction, AstNode, Formula { - Generated::Conjunction conj; + QL::Conjunction conj; Conjunction() { this = TConjunction(conj) } override string getAPrimaryQlClass() { result = "Conjunction" } /** Gets an operand to this formula. */ - Formula getAnOperand() { toGenerated(result) in [conj.getLeft(), conj.getRight()] } + Formula getAnOperand() { toQL(result) in [conj.getLeft(), conj.getRight()] } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1145,14 +1116,14 @@ class Conjunction extends TConjunction, AstNode, Formula { /** An `or` formula, with 2 or more operands. */ class Disjunction extends TDisjunction, AstNode, Formula { - Generated::Disjunction disj; + QL::Disjunction disj; Disjunction() { this = TDisjunction(disj) } override string getAPrimaryQlClass() { result = "Disjunction" } /** Gets an operand to this formula. */ - Formula getAnOperand() { toGenerated(result) in [disj.getLeft(), disj.getRight()] } + Formula getAnOperand() { toQL(result) in [disj.getLeft(), disj.getRight()] } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1165,7 +1136,7 @@ class Disjunction extends TDisjunction, AstNode, Formula { * A comparison operator, such as `<` or `=`. */ class ComparisonOp extends TComparisonOp, AstNode { - Generated::Compop op; + QL::Compop op; ComparisonOp() { this = TComparisonOp(op) } @@ -1182,7 +1153,7 @@ class ComparisonOp extends TComparisonOp, AstNode { * A literal expression, such as `6` or `true` or `"foo"`. */ class Literal extends TLiteral, Expr { - Generated::Literal lit; + QL::Literal lit; Literal() { this = TLiteral(lit) } @@ -1191,7 +1162,7 @@ class Literal extends TLiteral, Expr { /** A string literal. */ class String extends Literal { - String() { lit.getChild() instanceof Generated::String } + String() { lit.getChild() instanceof QL::String } override string getAPrimaryQlClass() { result = "String" } @@ -1199,7 +1170,7 @@ class String extends Literal { /** Gets the string value of this literal. */ string getValue() { - exists(string raw | raw = lit.getChild().(Generated::String).getValue() | + exists(string raw | raw = lit.getChild().(QL::String).getValue() | result = raw.substring(1, raw.length() - 1) ) } @@ -1207,39 +1178,39 @@ class String extends Literal { /** An integer literal. */ class Integer extends Literal { - Integer() { lit.getChild() instanceof Generated::Integer } + Integer() { lit.getChild() instanceof QL::Integer } override string getAPrimaryQlClass() { result = "Integer" } override PrimitiveType getType() { result.getName() = "int" } /** Gets the integer value of this literal. */ - int getValue() { result = lit.getChild().(Generated::Integer).getValue().toInt() } + int getValue() { result = lit.getChild().(QL::Integer).getValue().toInt() } } /** A float literal. */ class Float extends Literal { - Float() { lit.getChild() instanceof Generated::Float } + Float() { lit.getChild() instanceof QL::Float } override string getAPrimaryQlClass() { result = "Float" } override PrimitiveType getType() { result.getName() = "float" } /** Gets the float value of this literal. */ - float getValue() { result = lit.getChild().(Generated::Float).getValue().toFloat() } + float getValue() { result = lit.getChild().(QL::Float).getValue().toFloat() } } /** A boolean literal */ class Boolean extends Literal { - Generated::Bool bool; + QL::Bool bool; Boolean() { lit.getChild() = bool } /** Holds if the value is `true` */ - predicate isTrue() { bool.getChild() instanceof Generated::True } + predicate isTrue() { bool.getChild() instanceof QL::True } /** Holds if the value is `false` */ - predicate isFalse() { bool.getChild() instanceof Generated::False } + predicate isFalse() { bool.getChild() instanceof QL::False } override PrimitiveType getType() { result.getName() = "boolean" } @@ -1260,21 +1231,21 @@ class ComparisonSymbol extends string { /** A comparison formula, such as `x < 3` or `y = true`. */ class ComparisonFormula extends TComparisonFormula, Formula { - Generated::CompTerm comp; + QL::CompTerm comp; ComparisonFormula() { this = TComparisonFormula(comp) } /** Gets the left operand of this comparison. */ - Expr getLeftOperand() { toGenerated(result) = comp.getLeft() } + Expr getLeftOperand() { toQL(result) = comp.getLeft() } /** Gets the right operand of this comparison. */ - Expr getRightOperand() { toGenerated(result) = comp.getRight() } + Expr getRightOperand() { toQL(result) = comp.getRight() } /** Gets an operand of this comparison. */ - Expr getAnOperand() { result in [getLeftOperand(), getRightOperand()] } + Expr getAnOperand() { result in [this.getLeftOperand(), this.getRightOperand()] } /** Gets the operator of this comparison. */ - ComparisonOp getOperator() { toGenerated(result) = comp.getChild() } + ComparisonOp getOperator() { toQL(result) = comp.getChild() } /** Gets the symbol of this comparison (as a string). */ ComparisonSymbol getSymbol() { result = this.getOperator().getSymbol() } @@ -1294,42 +1265,42 @@ class ComparisonFormula extends TComparisonFormula, Formula { /** A quantifier formula, such as `exists` or `forall`. */ class Quantifier extends TQuantifier, Formula { - Generated::Quantified quant; + QL::Quantified quant; string kind; Quantifier() { - this = TQuantifier(quant) and kind = quant.getChild(0).(Generated::Quantifier).getValue() + this = TQuantifier(quant) and kind = quant.getChild(0).(QL::Quantifier).getValue() } /** Gets the ith variable declaration of this quantifier. */ VarDecl getArgument(int i) { i >= 1 and - toGenerated(result) = quant.getChild(i - 1) + toQL(result) = quant.getChild(i - 1) } /** Gets an argument of this quantifier. */ VarDecl getAnArgument() { result = this.getArgument(_) } /** Gets the formula restricting the range of this quantifier, if any. */ - Formula getRange() { toGenerated(result) = quant.getRange() } + Formula getRange() { toQL(result) = quant.getRange() } /** Holds if this quantifier has a range formula. */ predicate hasRange() { exists(this.getRange()) } /** Gets the main body of the quantifier. */ - Formula getFormula() { toGenerated(result) = quant.getFormula() } + Formula getFormula() { toQL(result) = quant.getFormula() } /** * Gets the expression of this quantifier, if the quantifier is * of the form `exists( expr )`. */ - Expr getExpr() { toGenerated(result) = quant.getExpr() } + Expr getExpr() { toQL(result) = quant.getExpr() } /** * Holds if this is the "expression only" form of an exists quantifier. * In other words, the quantifier is of the form `exists( expr )`. */ - predicate hasExpr() { exists(getExpr()) } + predicate hasExpr() { exists(this.getExpr()) } override string getAPrimaryQlClass() { result = "Quantifier" } @@ -1369,18 +1340,18 @@ class Forex extends Quantifier { /** A conditional formula, of the form `if a then b else c`. */ class IfFormula extends TIfFormula, Formula { - Generated::IfTerm ifterm; + QL::IfTerm ifterm; IfFormula() { this = TIfFormula(ifterm) } /** Gets the condition (the `if` part) of this formula. */ - Formula getCondition() { toGenerated(result) = ifterm.getCond() } + Formula getCondition() { toQL(result) = ifterm.getCond() } /** Gets the `then` part of this formula. */ - Formula getThenPart() { toGenerated(result) = ifterm.getFirst() } + Formula getThenPart() { toQL(result) = ifterm.getFirst() } /** Gets the `else` part of this formula. */ - Formula getElsePart() { toGenerated(result) = ifterm.getSecond() } + Formula getElsePart() { toQL(result) = ifterm.getSecond() } override string getAPrimaryQlClass() { result = "IfFormula" } @@ -1399,15 +1370,15 @@ class IfFormula extends TIfFormula, Formula { * An implication formula, of the form `foo implies bar`. */ class Implication extends TImplication, Formula { - Generated::Implication imp; + QL::Implication imp; Implication() { this = TImplication(imp) } /** Gets the left operand of this implication. */ - Formula getLeftOperand() { toGenerated(result) = imp.getLeft() } + Formula getLeftOperand() { toQL(result) = imp.getLeft() } /** Gets the right operand of this implication. */ - Formula getRightOperand() { toGenerated(result) = imp.getRight() } + Formula getRightOperand() { toQL(result) = imp.getRight() } override string getAPrimaryQlClass() { result = "Implication" } @@ -1424,15 +1395,15 @@ class Implication extends TImplication, Formula { * A type check formula, of the form `foo instanceof bar`. */ class InstanceOf extends TInstanceOf, Formula { - Generated::InstanceOf inst; + QL::InstanceOf inst; InstanceOf() { this = TInstanceOf(inst) } /** Gets the expression being checked. */ - Expr getExpr() { toGenerated(result) = inst.getChild(0) } + Expr getExpr() { toQL(result) = inst.getChild(0) } /** Gets the reference to the type being checked. */ - TypeExpr getType() { toGenerated(result) = inst.getChild(1) } + TypeExpr getType() { toQL(result) = inst.getChild(1) } override string getAPrimaryQlClass() { result = "InstanceOf" } @@ -1450,7 +1421,7 @@ class InstanceOf extends TInstanceOf, Formula { * The formula holds if the lhs is in the rhs. */ class InFormula extends TInFormula, Formula { - Generated::InExpr inexpr; + QL::InExpr inexpr; InFormula() { this = TInFormula(inexpr) } @@ -1458,13 +1429,13 @@ class InFormula extends TInFormula, Formula { * Gets the expression that is checked for membership. * E.g. for `foo in [2, 3]` the result is `foo`. */ - Expr getExpr() { toGenerated(result) = inexpr.getLeft() } + Expr getExpr() { toQL(result) = inexpr.getLeft() } /** * Gets the range for this in formula. * E.g. for `foo in [2, 3]` the result is `[2, 3]`. */ - Expr getRange() { toGenerated(result) = inexpr.getRight() } + Expr getRange() { toQL(result) = inexpr.getRight() } override string getAPrimaryQlClass() { result = "InFormula" } @@ -1482,7 +1453,7 @@ class InFormula extends TInFormula, Formula { * E.g. `fastTC(pathSucc/2)(n1, n2)`. */ class HigherOrderFormula extends THigherOrderFormula, Formula { - Generated::HigherOrderTerm hop; + QL::HigherOrderTerm hop; HigherOrderFormula() { this = THigherOrderFormula(hop) } @@ -1490,7 +1461,7 @@ class HigherOrderFormula extends THigherOrderFormula, Formula { * Gets the `i`th input to this higher-order formula. * E.g. for `fastTC(pathSucc/2)(n1, n2)` the result is `pathSucc/2`. */ - PredicateExpr getInput(int i) { toGenerated(result) = hop.getChild(i).(Generated::PredicateExpr) } + PredicateExpr getInput(int i) { toQL(result) = hop.getChild(i).(QL::PredicateExpr) } /** * Gets the number of inputs. @@ -1501,7 +1472,7 @@ class HigherOrderFormula extends THigherOrderFormula, Formula { * Gets the `i`th argument to this higher-order formula. * E.g. for `fastTC(pathSucc/2)(n1, n2)` the result is `n1` and `n2`. */ - Expr getArgument(int i) { toGenerated(result) = hop.getChild(i + getNumInputs()) } + Expr getArgument(int i) { toQL(result) = hop.getChild(i + this.getNumInputs()) } /** * Gets the name of this higher-order predicate. @@ -1525,7 +1496,7 @@ class HigherOrderFormula extends THigherOrderFormula, Formula { class Aggregate extends TAggregate, Expr { string getKind() { none() } - Generated::Aggregate getAggregate() { none() } + QL::Aggregate getAggregate() { none() } } /** @@ -1533,13 +1504,13 @@ class Aggregate extends TAggregate, Expr { * E.g. `min(getAPredicate().getArity())`. */ class ExprAggregate extends TExprAggregate, Aggregate { - Generated::Aggregate agg; - Generated::ExprAggregateBody body; + QL::Aggregate agg; + QL::ExprAggregateBody body; string kind; ExprAggregate() { this = TExprAggregate(agg) and - kind = agg.getChild(0).(Generated::AggId).getValue() and + kind = agg.getChild(0).(QL::AggId).getValue() and body = agg.getChild(_) } @@ -1549,23 +1520,23 @@ class ExprAggregate extends TExprAggregate, Aggregate { */ override string getKind() { result = kind } - override Generated::Aggregate getAggregate() { result = agg } + override QL::Aggregate getAggregate() { result = agg } /** * Gets the ith "as" expression of this aggregate, if any. */ - Expr getExpr(int i) { toGenerated(result) = body.getAsExprs().getChild(i) } + Expr getExpr(int i) { toQL(result) = body.getAsExprs().getChild(i) } /** * Gets the ith "order by" expression of this aggregate, if any. */ - Expr getOrderBy(int i) { toGenerated(result) = body.getOrderBys().getChild(i).getChild(0) } + Expr getOrderBy(int i) { toQL(result) = body.getOrderBys().getChild(i).getChild(0) } /** * Gets the direction (ascending or descending) of the ith "order by" expression of this aggregate. */ string getOrderbyDirection(int i) { - result = body.getOrderBys().getChild(i).getChild(1).(Generated::Direction).getValue() + result = body.getOrderBys().getChild(i).getChild(1).(QL::Direction).getValue() } override string getAPrimaryQlClass() { result = "ExprAggregate[" + kind + "]" } @@ -1590,19 +1561,19 @@ class ExprAggregate extends TExprAggregate, Aggregate { ) or not kind = ["count", "strictcount"] and - result = getExpr(0).getType() + result = this.getExpr(0).getType() } } /** An aggregate expression, such as `count` or `sum`. */ class FullAggregate extends TFullAggregate, Aggregate { - Generated::Aggregate agg; + QL::Aggregate agg; string kind; - Generated::FullAggregateBody body; + QL::FullAggregateBody body; FullAggregate() { this = TFullAggregate(agg) and - kind = agg.getChild(0).(Generated::AggId).getValue() and + kind = agg.getChild(0).(QL::AggId).getValue() and body = agg.getChild(_) } @@ -1612,10 +1583,10 @@ class FullAggregate extends TFullAggregate, Aggregate { */ override string getKind() { result = kind } - override Generated::Aggregate getAggregate() { result = agg } + override QL::Aggregate getAggregate() { result = agg } /** Gets the ith declared argument of this quantifier. */ - VarDecl getArgument(int i) { toGenerated(result) = body.getChild(i) } + VarDecl getArgument(int i) { toQL(result) = body.getChild(i) } /** Gets an argument of this quantifier. */ VarDecl getAnArgument() { result = this.getArgument(_) } @@ -1623,23 +1594,23 @@ class FullAggregate extends TFullAggregate, Aggregate { /** * Gets the formula restricting the range of this quantifier, if any. */ - Formula getRange() { toGenerated(result) = body.getGuard() } + Formula getRange() { toQL(result) = body.getGuard() } /** * Gets the ith "as" expression of this aggregate, if any. */ - Expr getExpr(int i) { toGenerated(result) = body.getAsExprs().getChild(i) } + Expr getExpr(int i) { toQL(result) = body.getAsExprs().getChild(i) } /** * Gets the ith "order by" expression of this aggregate, if any. */ - Expr getOrderBy(int i) { toGenerated(result) = body.getOrderBys().getChild(i).getChild(0) } + Expr getOrderBy(int i) { toQL(result) = body.getOrderBys().getChild(i).getChild(0) } /** * Gets the direction (ascending or descending) of the ith "order by" expression of this aggregate. */ string getOrderbyDirection(int i) { - result = body.getOrderBys().getChild(i).getChild(1).(Generated::Direction).getValue() + result = body.getOrderBys().getChild(i).getChild(1).(QL::Direction).getValue() } override string getAPrimaryQlClass() { kind != "rank" and result = "FullAggregate[" + kind + "]" } @@ -1654,11 +1625,11 @@ class FullAggregate extends TFullAggregate, Aggregate { ) or kind = ["any", "min", "max", "unique"] and - not exists(getExpr(_)) and - result = getArgument(0).getTypeExpr().getResolvedType() + not exists(this.getExpr(_)) and + result = this.getArgument(0).getTypeExpr().getResolvedType() or not kind = ["count", "strictcount"] and - result = getExpr(0).getType() + result = this.getExpr(0).getType() } override AstNode getAChild(string pred) { @@ -1687,7 +1658,7 @@ class Rank extends Aggregate { /** * The `i` in `rank[i]( | | )`. */ - Expr getRankExpr() { toGenerated(result) = this.getAggregate().getChild(1) } + Expr getRankExpr() { toQL(result) = this.getAggregate().getChild(1) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1700,7 +1671,7 @@ class Rank extends Aggregate { * An "as" expression, such as `foo as bar`. */ class AsExpr extends TAsExpr, VarDef, Expr { - Generated::AsExpr asExpr; + QL::AsExpr asExpr; AsExpr() { this = TAsExpr(asExpr) } @@ -1714,13 +1685,13 @@ class AsExpr extends TAsExpr, VarDef, Expr { * Gets the name the inner expression gets "saved" under. * For example this is `bar` in the expression `foo as bar`. */ - string getAsName() { result = asExpr.getChild(1).(Generated::VarName).getChild().getValue() } + string getAsName() { result = asExpr.getChild(1).(QL::VarName).getChild().getValue() } /** * Gets the inner expression of the "as" expression. For example, this is `foo` in * the expression `foo as bar`. */ - Expr getInnerExpr() { toGenerated(result) = asExpr.getChild(0) } + Expr getInnerExpr() { toQL(result) = asExpr.getChild(0) } override AstNode getAChild(string pred) { result = super.getAChild(pred) @@ -1733,7 +1704,7 @@ class AsExpr extends TAsExpr, VarDef, Expr { * An identifier, such as `foo`. */ class Identifier extends TIdentifier, Expr { - Generated::Variable id; + QL::Variable id; Identifier() { this = TIdentifier(id) } @@ -1753,7 +1724,7 @@ class VarAccess extends Identifier { /** Gets the accessed variable. */ VarDef getDeclaration() { result = decl } - override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() } + override string getName() { result = id.getChild().(QL::VarName).getChild().getValue() } override Type getType() { result = this.getDeclaration().getType() } @@ -1769,7 +1740,7 @@ class FieldAccess extends Identifier { /** Gets the accessed field. */ VarDecl getDeclaration() { result = decl } - override string getName() { result = id.getChild().(Generated::VarName).getChild().getValue() } + override string getName() { result = id.getChild().(QL::VarName).getChild().getValue() } override Type getType() { result = this.getDeclaration().getType() } @@ -1778,7 +1749,7 @@ class FieldAccess extends Identifier { /** An access to `this`. */ class ThisAccess extends Identifier { - ThisAccess() { any(Generated::This t).getParent() = id } + ThisAccess() { any(QL::This t).getParent() = id } override Type getType() { result = this.getParent+().(Class).getType() } @@ -1796,7 +1767,7 @@ class Super extends TSuper, Expr { /** An access to `result`. */ class ResultAccess extends Identifier { - ResultAccess() { any(Generated::Result r).getParent() = id } + ResultAccess() { any(QL::Result r).getParent() = id } override Type getType() { result = this.getParent+().(Predicate).getReturnType() } @@ -1807,12 +1778,12 @@ class ResultAccess extends Identifier { /** A `not` formula. */ class Negation extends TNegation, Formula { - Generated::Negation neg; + QL::Negation neg; Negation() { this = TNegation(neg) } /** Gets the formula being negated. */ - Formula getFormula() { toGenerated(result) = neg.getChild() } + Formula getFormula() { toQL(result) = neg.getChild() } override string getAPrimaryQlClass() { result = "Negation" } @@ -1830,7 +1801,7 @@ class Expr extends TExpr, AstNode { /** An expression annotation, such as `pragma[only_bind_into](config)`. */ class ExprAnnotation extends TExprAnnotation, Expr { - Generated::ExprAnnotation expr_anno; + QL::ExprAnnotation expr_anno; ExprAnnotation() { this = TExprAnnotation(expr_anno) } @@ -1850,7 +1821,7 @@ class ExprAnnotation extends TExprAnnotation, Expr { * Gets the inner expression. * E.g. for `pragma[only_bind_into](config)` the result is `config`. */ - Expr getExpression() { toGenerated(result) = expr_anno.getChild() } + Expr getExpression() { toQL(result) = expr_anno.getChild() } override Type getType() { result = this.getExpression().getType() } @@ -1882,21 +1853,21 @@ class BinOpExpr extends TBinOpExpr, Expr { FunctionSymbol getOperator() { none() } // overriden in subclasses /* Gets an operand of the binary expression. */ - final Expr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } + final Expr getAnOperand() { result = this.getLeftOperand() or result = this.getRightOperand() } } /** * An addition or subtraction expression. */ class AddSubExpr extends TAddSubExpr, BinOpExpr { - Generated::AddExpr expr; + QL::AddExpr expr; FunctionSymbol operator; AddSubExpr() { this = TAddSubExpr(expr) and operator = expr.getChild().getValue() } - override Expr getLeftOperand() { toGenerated(result) = expr.getLeft() } + override Expr getLeftOperand() { toQL(result) = expr.getLeft() } - override Expr getRightOperand() { toGenerated(result) = expr.getRight() } + override Expr getRightOperand() { toQL(result) = expr.getRight() } override FunctionSymbol getOperator() { result = operator } @@ -1952,16 +1923,16 @@ class SubExpr extends AddSubExpr { * A multiplication, division, or modulo expression. */ class MulDivModExpr extends TMulDivModExpr, BinOpExpr { - Generated::MulExpr expr; + QL::MulExpr expr; FunctionSymbol operator; MulDivModExpr() { this = TMulDivModExpr(expr) and operator = expr.getChild().getValue() } /** Gets the left operand of the binary expression. */ - override Expr getLeftOperand() { toGenerated(result) = expr.getLeft() } + override Expr getLeftOperand() { toQL(result) = expr.getLeft() } /** Gets the right operand of the binary expression. */ - override Expr getRightOperand() { toGenerated(result) = expr.getRight() } + override Expr getRightOperand() { toQL(result) = expr.getRight() } override FunctionSymbol getOperator() { result = operator } @@ -2022,24 +1993,24 @@ class ModExpr extends MulDivModExpr { * A range expression, such as `[1 .. 10]`. */ class Range extends TRange, Expr { - Generated::Range range; + QL::Range range; Range() { this = TRange(range) } /** * Gets the lower bound of the range. */ - Expr getLowEndpoint() { toGenerated(result) = range.getLower() } + Expr getLowEndpoint() { toQL(result) = range.getLower() } /** * Gets the upper bound of the range. */ - Expr getHighEndpoint() { toGenerated(result) = range.getUpper() } + Expr getHighEndpoint() { toQL(result) = range.getUpper() } /** * Gets the lower and upper bounds of the range. */ - Expr getAnEndpoint() { result = [getLowEndpoint(), getHighEndpoint()] } + Expr getAnEndpoint() { result = [this.getLowEndpoint(), this.getHighEndpoint()] } override PrimitiveType getType() { result.getName() = "int" } @@ -2058,24 +2029,24 @@ class Range extends TRange, Expr { * A set literal expression, such as `[1,3,5,7]`. */ class Set extends TSet, Expr { - Generated::SetLiteral set; + QL::SetLiteral set; Set() { this = TSet(set) } /** * Gets the `i`th element in this set literal expression. */ - Expr getElement(int i) { toGenerated(result) = set.getChild(i) } + Expr getElement(int i) { toQL(result) = set.getChild(i) } /** * Gets an element in this set literal expression, if any. */ - Expr getAnElement() { result = getElement(_) } + Expr getAnElement() { result = this.getElement(_) } /** * Gets the number of elements in this set literal expression. */ - int getNumberOfElements() { result = count(getAnElement()) } + int getNumberOfElements() { result = count(this.getAnElement()) } override Type getType() { result = this.getElement(0).getType() } @@ -2084,18 +2055,18 @@ class Set extends TSet, Expr { override AstNode getAChild(string pred) { result = super.getAChild(pred) or - exists(int i | pred = indexedMember("getElement", i) and result = getElement(i)) + exists(int i | pred = indexedMember("getElement", i) and result = this.getElement(i)) } } /** A unary operation expression, such as `-(x*y)` */ class UnaryExpr extends TUnaryExpr, Expr { - Generated::UnaryExpr unaryexpr; + QL::UnaryExpr unaryexpr; UnaryExpr() { this = TUnaryExpr(unaryexpr) } /** Gets the operand of the unary expression. */ - Expr getOperand() { toGenerated(result) = unaryexpr.getChild(1) } + Expr getOperand() { toQL(result) = unaryexpr.getChild(1) } /** Gets the operator of the unary expression as a string. */ FunctionSymbol getOperator() { result = unaryexpr.getChild(0).toString() } @@ -2113,7 +2084,7 @@ class UnaryExpr extends TUnaryExpr, Expr { /** A "don't care" expression, denoted by `_`. */ class DontCare extends TDontCare, Expr { - Generated::Underscore dontcare; + QL::Underscore dontcare; DontCare() { this = TDontCare(dontcare) } @@ -2124,7 +2095,7 @@ class DontCare extends TDontCare, Expr { /** A module expression. Such as `DataFlow` in `DataFlow::Node` */ class ModuleExpr extends TModuleExpr, ModuleRef { - Generated::ModuleExpr me; + QL::ModuleExpr me; ModuleExpr() { this = TModuleExpr(me) } @@ -2140,7 +2111,7 @@ class ModuleExpr extends TModuleExpr, ModuleRef { string getName() { result = me.getName().getValue() or - not exists(me.getName()) and result = me.getChild().(Generated::SimpleId).getValue() + not exists(me.getName()) and result = me.getChild().(QL::SimpleId).getValue() } /** @@ -2169,7 +2140,7 @@ class ModuleExpr extends TModuleExpr, ModuleRef { /** An argument to an annotation. */ private class AnnotationArg extends TAnnotationArg, AstNode { - Generated::AnnotArg arg; + QL::AnnotArg arg; AnnotationArg() { this = TAnnotationArg(arg) } @@ -2177,8 +2148,8 @@ private class AnnotationArg extends TAnnotationArg, AstNode { string getValue() { result = [ - arg.getChild().(Generated::SimpleId).getValue(), - arg.getChild().(Generated::Result).getValue(), arg.getChild().(Generated::This).getValue() + arg.getChild().(QL::SimpleId).getValue(), arg.getChild().(QL::Result).getValue(), + arg.getChild().(QL::This).getValue() ] } @@ -2207,7 +2178,7 @@ private class MonotonicAggregatesArg extends AnnotationArg { /** An annotation on an element. */ class Annotation extends TAnnotation, AstNode { - Generated::Annotation annot; + QL::Annotation annot; Annotation() { this = TAnnotation(annot) } @@ -2218,7 +2189,7 @@ class Annotation extends TAnnotation, AstNode { override Location getLocation() { result = annot.getLocation() } /** Gets the node corresponding to the field `args`. */ - AnnotationArg getArgs(int i) { toGenerated(result) = annot.getArgs(i) } + AnnotationArg getArgs(int i) { toQL(result) = annot.getArgs(i) } /** Gets the node corresponding to the field `name`. */ string getName() { result = annot.getName().getValue() } @@ -2267,10 +2238,10 @@ class BindingSet extends Annotation { string getBoundName(int index) { result = this.getArgs(index).getValue() } /** Gets a name bound by this bindingset, if any. */ - string getABoundName() { result = getBoundName(_) } + string getABoundName() { result = this.getBoundName(_) } /** Gets the number of names bound by this bindingset. */ - int getNumberOfBoundNames() { result = count(getABoundName()) } + int getNumberOfBoundNames() { result = count(this.getABoundName()) } } /** @@ -2280,12 +2251,12 @@ module YAML { /** A node in a YAML file */ class YAMLNode extends TYAMLNode, AstNode { /** Holds if the predicate is a root node (has no parent) */ - predicate isRoot() { not exists(getParent()) } + predicate isRoot() { not exists(this.getParent()) } } /** A YAML comment. */ class YAMLComment extends TYamlCommemt, YAMLNode { - Generated::YamlComment yamlcomment; + QL::YamlComment yamlcomment; YAMLComment() { this = TYamlCommemt(yamlcomment) } @@ -2294,13 +2265,13 @@ module YAML { /** A YAML entry. */ class YAMLEntry extends TYamlEntry, YAMLNode { - Generated::YamlEntry yamle; + QL::YamlEntry yamle; YAMLEntry() { this = TYamlEntry(yamle) } /** Gets the key of this YAML entry. */ YAMLKey getKey() { - exists(Generated::YamlKeyvaluepair pair | + exists(QL::YamlKeyvaluepair pair | pair.getParent() = yamle and result = TYamlKey(pair.getKey()) ) @@ -2308,7 +2279,7 @@ module YAML { /** Gets the value of this YAML entry. */ YAMLValue getValue() { - exists(Generated::YamlKeyvaluepair pair | + exists(QL::YamlKeyvaluepair pair | pair.getParent() = yamle and result = TYamlValue(pair.getValue()) ) @@ -2319,7 +2290,7 @@ module YAML { /** A YAML key. */ class YAMLKey extends TYamlKey, YAMLNode { - Generated::YamlKey yamlkey; + QL::YamlKey yamlkey; YAMLKey() { this = TYamlKey(yamlkey) } @@ -2327,7 +2298,7 @@ module YAML { * Gets the value of this YAML key. */ YAMLValue getValue() { - exists(Generated::YamlKeyvaluepair pair | + exists(QL::YamlKeyvaluepair pair | pair.getKey() = yamlkey and result = TYamlValue(pair.getValue()) ) } @@ -2336,7 +2307,7 @@ module YAML { /** Gets the value of this YAML value. */ string getNamePart(int i) { - i = 0 and result = yamlkey.getChild(0).(Generated::SimpleId).getValue() + i = 0 and result = yamlkey.getChild(0).(QL::SimpleId).getValue() or exists(YAMLKey child | child = TYamlKey(yamlkey.getChild(1)) and @@ -2349,13 +2320,13 @@ module YAML { * Dashes are replaced with `/` (because we don't have that information in the generated AST). */ string getQualifiedName() { - result = concat(string part, int i | part = getNamePart(i) | part, "/" order by i) + result = concat(string part, int i | part = this.getNamePart(i) | part, "/" order by i) } } /** A YAML list item. */ class YAMLListItem extends TYamlListitem, YAMLNode { - Generated::YamlListitem yamllistitem; + QL::YamlListitem yamllistitem; YAMLListItem() { this = TYamlListitem(yamllistitem) } @@ -2369,7 +2340,7 @@ module YAML { /** A YAML value. */ class YAMLValue extends TYamlValue, YAMLNode { - Generated::YamlValue yamlvalue; + QL::YamlValue yamlvalue; YAMLValue() { this = TYamlValue(yamlvalue) } @@ -2382,8 +2353,6 @@ module YAML { // to not expose the entire `File` API on `QlPack`. private newtype TQLPack = MKQlPack(File file) { file.getBaseName() = "qlpack.yml" } - YAMLEntry test() { not result.isRoot() } - /** * A `qlpack.yml` file. */ @@ -2402,15 +2371,15 @@ module YAML { } /** Gets the name of this qlpack */ - string getName() { result = getProperty("name") } + string getName() { result = this.getProperty("name") } /** Gets the version of this qlpack */ - string getVersion() { result = getProperty("version") } + string getVersion() { result = this.getProperty("version") } /** Gets the extractor of this qlpack */ - string getExtractor() { result = getProperty("extractor") } + string getExtractor() { result = this.getProperty("extractor") } - string toString() { result = getName() } + string toString() { result = this.getName() } /** Gets the file that this `QLPack` represents. */ File getFile() { result = file } @@ -2425,7 +2394,7 @@ module YAML { entry.getLocation().getStartColumn() > deps.getLocation().getStartColumn() ) or - exists(YAMLEntry prev | isADependency(prev) | + exists(YAMLEntry prev | this.isADependency(prev) | prev.getLocation().getFile() = file and entry.getLocation().getFile() = file and entry.getLocation().getStartLine() = 1 + prev.getLocation().getStartLine() and @@ -2434,7 +2403,7 @@ module YAML { } predicate hasDependency(string name, string version) { - exists(YAMLEntry entry | isADependency(entry) | + exists(YAMLEntry entry | this.isADependency(entry) | entry.getKey().getQualifiedName() = name and entry.getValue().getValue() = version ) @@ -2442,7 +2411,7 @@ module YAML { /** Gets the database scheme of this qlpack */ File getDBScheme() { - result.getBaseName() = getProperty("dbscheme") and + result.getBaseName() = this.getProperty("dbscheme") and result = file.getParentContainer().getFile(any(string s | s.matches("%.dbscheme"))) } @@ -2450,14 +2419,16 @@ module YAML { Container getAFileInPack() { result.getParentContainer() = file.getParentContainer() or - result = getAFileInPack().(Folder).getAChildContainer() + result = this.getAFileInPack().(Folder).getAChildContainer() } /** * Gets a QLPack that this QLPack depends on. */ QLPack getADependency() { - exists(string name | hasDependency(name, _) | result.getName().replaceAll("-", "/") = name) + exists(string name | this.hasDependency(name, _) | + result.getName().replaceAll("-", "/") = name + ) } Location getLocation() { diff --git a/ql/src/codeql_ql/ast/internal/AstNodes.qll b/ql/src/codeql_ql/ast/internal/AstNodes.qll index c7e73105b4c..1b0f92d014e 100644 --- a/ql/src/codeql_ql/ast/internal/AstNodes.qll +++ b/ql/src/codeql_ql/ast/internal/AstNodes.qll @@ -4,69 +4,65 @@ private import Builtins cached newtype TAstNode = - TTopLevel(Generated::Ql file) or - TQLDoc(Generated::Qldoc qldoc) or - TClasslessPredicate(Generated::ClasslessPredicate pred) or - TVarDecl(Generated::VarDecl decl) or - TClass(Generated::Dataclass dc) or - TCharPred(Generated::Charpred pred) or - TClassPredicate(Generated::MemberPredicate pred) or - TDBRelation(Generated::DbTable table) or - TSelect(Generated::Select sel) or - TModule(Generated::Module mod) or - TNewType(Generated::Datatype dt) or - TNewTypeBranch(Generated::DatatypeBranch branch) or - TImport(Generated::ImportDirective imp) or - TType(Generated::TypeExpr type) or - TDisjunction(Generated::Disjunction disj) or - TConjunction(Generated::Conjunction conj) or - TComparisonFormula(Generated::CompTerm comp) or - TComparisonOp(Generated::Compop op) or - TQuantifier(Generated::Quantified quant) or - TFullAggregate(Generated::Aggregate agg) { - agg.getChild(_) instanceof Generated::FullAggregateBody + TTopLevel(QL::Ql file) or + TQLDoc(QL::Qldoc qldoc) or + TClasslessPredicate(QL::ClasslessPredicate pred) or + TVarDecl(QL::VarDecl decl) or + TClass(QL::Dataclass dc) or + TCharPred(QL::Charpred pred) or + TClassPredicate(QL::MemberPredicate pred) or + TDBRelation(QL::DbTable table) or + TSelect(QL::Select sel) or + TModule(QL::Module mod) or + TNewType(QL::Datatype dt) or + TNewTypeBranch(QL::DatatypeBranch branch) or + TImport(QL::ImportDirective imp) or + TType(QL::TypeExpr type) or + TDisjunction(QL::Disjunction disj) or + TConjunction(QL::Conjunction conj) or + TComparisonFormula(QL::CompTerm comp) or + TComparisonOp(QL::Compop op) or + TQuantifier(QL::Quantified quant) or + TFullAggregate(QL::Aggregate agg) { agg.getChild(_) instanceof QL::FullAggregateBody } or + TExprAggregate(QL::Aggregate agg) { agg.getChild(_) instanceof QL::ExprAggregateBody } or + TSuper(QL::SuperRef sup) or + TIdentifier(QL::Variable var) or + TAsExpr(QL::AsExpr asExpr) { asExpr.getChild(1) instanceof QL::VarName } or + TPredicateCall(QL::CallOrUnqualAggExpr call) or + TMemberCall(QL::QualifiedExpr expr) { + not expr.getChild(_).(QL::QualifiedRhs).getChild(_) instanceof QL::TypeExpr } or - TExprAggregate(Generated::Aggregate agg) { - agg.getChild(_) instanceof Generated::ExprAggregateBody + TInlineCast(QL::QualifiedExpr expr) { + expr.getChild(_).(QL::QualifiedRhs).getChild(_) instanceof QL::TypeExpr } or - TSuper(Generated::SuperRef sup) or - TIdentifier(Generated::Variable var) or - TAsExpr(Generated::AsExpr asExpr) { asExpr.getChild(1) instanceof Generated::VarName } or - TPredicateCall(Generated::CallOrUnqualAggExpr call) or - TMemberCall(Generated::QualifiedExpr expr) { - not expr.getChild(_).(Generated::QualifiedRhs).getChild(_) instanceof Generated::TypeExpr + TNoneCall(QL::SpecialCall call) or + TAnyCall(QL::Aggregate agg) { + "any" = agg.getChild(0).(QL::AggId).getValue() and + not agg.getChild(_) instanceof QL::FullAggregateBody } or - TInlineCast(Generated::QualifiedExpr expr) { - expr.getChild(_).(Generated::QualifiedRhs).getChild(_) instanceof Generated::TypeExpr - } or - TNoneCall(Generated::SpecialCall call) or - TAnyCall(Generated::Aggregate agg) { - "any" = agg.getChild(0).(Generated::AggId).getValue() and - not agg.getChild(_) instanceof Generated::FullAggregateBody - } or - TNegation(Generated::Negation neg) or - TIfFormula(Generated::IfTerm ifterm) or - TImplication(Generated::Implication impl) or - TInstanceOf(Generated::InstanceOf inst) or - TInFormula(Generated::InExpr inexpr) or - THigherOrderFormula(Generated::HigherOrderTerm hop) or - TExprAnnotation(Generated::ExprAnnotation expr_anno) or - TAddSubExpr(Generated::AddExpr addexp) or - TMulDivModExpr(Generated::MulExpr mulexpr) or - TRange(Generated::Range range) or - TSet(Generated::SetLiteral set) or - TLiteral(Generated::Literal lit) or - TUnaryExpr(Generated::UnaryExpr unaryexpr) or - TDontCare(Generated::Underscore dontcare) or - TModuleExpr(Generated::ModuleExpr me) or - TPredicateExpr(Generated::PredicateExpr pe) or - TAnnotation(Generated::Annotation annot) or - TAnnotationArg(Generated::AnnotArg arg) or - TYamlCommemt(Generated::YamlComment yc) or - TYamlEntry(Generated::YamlEntry ye) or - TYamlKey(Generated::YamlKey yk) or - TYamlListitem(Generated::YamlListitem yli) or - TYamlValue(Generated::YamlValue yv) or + TNegation(QL::Negation neg) or + TIfFormula(QL::IfTerm ifterm) or + TImplication(QL::Implication impl) or + TInstanceOf(QL::InstanceOf inst) or + TInFormula(QL::InExpr inexpr) or + THigherOrderFormula(QL::HigherOrderTerm hop) or + TExprAnnotation(QL::ExprAnnotation expr_anno) or + TAddSubExpr(QL::AddExpr addexp) or + TMulDivModExpr(QL::MulExpr mulexpr) or + TRange(QL::Range range) or + TSet(QL::SetLiteral set) or + TLiteral(QL::Literal lit) or + TUnaryExpr(QL::UnaryExpr unaryexpr) or + TDontCare(QL::Underscore dontcare) or + TModuleExpr(QL::ModuleExpr me) or + TPredicateExpr(QL::PredicateExpr pe) or + TAnnotation(QL::Annotation annot) or + TAnnotationArg(QL::AnnotArg arg) or + TYamlCommemt(QL::YamlComment yc) or + TYamlEntry(QL::YamlEntry ye) or + TYamlKey(QL::YamlKey yk) or + TYamlListitem(QL::YamlListitem yli) or + TYamlValue(QL::YamlValue yv) or TBuiltinClassless(string ret, string name, string args) { isBuiltinClassless(ret, name, args) } or TBuiltinMember(string qual, string ret, string name, string args) { isBuiltinMember(qual, ret, name, args) @@ -90,7 +86,7 @@ class TModuleRef = TImport or TModuleExpr; class TYAMLNode = TYamlCommemt or TYamlEntry or TYamlKey or TYamlListitem or TYamlValue; -private Generated::AstNode toGeneratedFormula(AST::AstNode n) { +private QL::AstNode toQLFormula(AST::AstNode n) { n = TConjunction(result) or n = TDisjunction(result) or n = TComparisonFormula(result) or @@ -106,7 +102,7 @@ private Generated::AstNode toGeneratedFormula(AST::AstNode n) { n = TInFormula(result) } -private Generated::AstNode toGeneratedExpr(AST::AstNode n) { +private QL::AstNode toQLExpr(AST::AstNode n) { n = TAddSubExpr(result) or n = TMulDivModExpr(result) or n = TRange(result) or @@ -120,7 +116,7 @@ private Generated::AstNode toGeneratedExpr(AST::AstNode n) { n = TDontCare(result) } -private Generated::AstNode toGenerateYAML(AST::AstNode n) { +private QL::AstNode toGenerateYAML(AST::AstNode n) { n = TYamlCommemt(result) or n = TYamlEntry(result) or n = TYamlKey(result) or @@ -131,19 +127,19 @@ private Generated::AstNode toGenerateYAML(AST::AstNode n) { /** * Gets the underlying TreeSitter entity for a given AST node. */ -Generated::AstNode toGenerated(AST::AstNode n) { - result = toGeneratedExpr(n) +QL::AstNode toQL(AST::AstNode n) { + result = toQLExpr(n) or - result = toGeneratedFormula(n) + result = toQLFormula(n) or result = toGenerateYAML(n) or - result.(Generated::ParExpr).getChild() = toGenerated(n) + result.(QL::ParExpr).getChild() = toQL(n) or result = - any(Generated::AsExpr ae | - not ae.getChild(1) instanceof Generated::VarName and - toGenerated(n) = ae.getChild(0) + any(QL::AsExpr ae | + not ae.getChild(1) instanceof QL::VarName and + toQL(n) = ae.getChild(0) ) or n = TTopLevel(result) diff --git a/ql/src/codeql_ql/ast/internal/Builtins.qll b/ql/src/codeql_ql/ast/internal/Builtins.qll index 9e1d45d5242..78b40e56f30 100644 --- a/ql/src/codeql_ql/ast/internal/Builtins.qll +++ b/ql/src/codeql_ql/ast/internal/Builtins.qll @@ -35,8 +35,8 @@ predicate isBuiltinMember(string sig) { "string int.toString()", "string string.charAt(int)", "int string.indexOf(string)", "int string.indexOf(string, int, int)", "predicate string.isLowercase()", "predicate string.isUppercase()", "int string.length()", "predicate string.matches(string)", - "string string.prefix(int)", "string regexpCapture(string, int)", - "string regexpFind(string, int, int)", "predicate string.regexpMatch(string)", + "string string.prefix(int)", "string string.regexpCapture(string, int)", + "string string.regexpFind(string, int, int)", "predicate string.regexpMatch(string)", "string string.regexpReplaceAll(string, string)", "string string.replaceAll(string, string)", "string string.splitAt(string)", "string string.splitAt(string, int)", "string string.substring(int, int)", "string string.suffix(int)", "date string.toDate()", @@ -58,6 +58,18 @@ predicate isBuiltinMember(string qual, string ret, string name, string args) { ) } +module BuildinsConsistency { + query predicate noBuildinParse(string sig) { + isBuiltinMember(sig) and + not exists(sig.regexpCapture("(\\w+) (\\w+)\\.(\\w+)\\(([\\w, ]*)\\)", _)) + } + + query predicate noBuildinClasslessParse(string sig) { + isBuiltinClassless(sig) and + not exists(sig.regexpCapture("(\\w+) (\\w+)\\(([\\w, ]*)\\)", _)) + } +} + bindingset[args] string getArgType(string args, int i) { result = args.splitAt(",", i).trim() } diff --git a/ql/src/codeql_ql/ast/internal/Module.qll b/ql/src/codeql_ql/ast/internal/Module.qll index a64ccfd0f2d..faf18cf7954 100644 --- a/ql/src/codeql_ql/ast/internal/Module.qll +++ b/ql/src/codeql_ql/ast/internal/Module.qll @@ -19,7 +19,9 @@ private class ContainerOrModule extends TContainerOrModule { private class TFileOrModule = TFile or TModule; /** A file or a module. */ -class FileOrModule extends TFileOrModule, ContainerOrModule { } +class FileOrModule extends TFileOrModule, ContainerOrModule { + abstract File getFile(); +} private class File_ extends FileOrModule, TFile { File f; @@ -41,6 +43,8 @@ private class File_ extends FileOrModule, TFile { endline = 0 and endcolumn = 0 } + + override File getFile() { result = f } } private class Folder_ extends ContainerOrModule, TFolder { @@ -90,6 +94,8 @@ class Module_ extends FileOrModule, TModule { ) { m.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + + override File getFile() { result = m.getLocation().getFile() } } private predicate resolveQualifiedName(Import imp, ContainerOrModule m, int i) { @@ -148,14 +154,16 @@ private predicate resolveSelectionName(Import imp, ContainerOrModule m, int i) { cached private module Cached { - // TODO: Use `AstNode::getParent` once it is total - private Generated::AstNode parent(Generated::AstNode n) { - result = n.getParent() and - not n instanceof Generated::Module - } - private Module getEnclosingModule0(AstNode n) { - AstNodes::toGenerated(result) = parent*(AstNodes::toGenerated(n).getParent()) + not n instanceof Module and + ( + n = result.getAChild(_) + or + exists(AstNode prev | + result = getEnclosingModule0(prev) and + n = prev.getAChild(_) + ) + ) } cached diff --git a/ql/src/codeql_ql/ast/internal/Predicate.qll b/ql/src/codeql_ql/ast/internal/Predicate.qll index 31c91c7ae6d..393ecdf4266 100644 --- a/ql/src/codeql_ql/ast/internal/Predicate.qll +++ b/ql/src/codeql_ql/ast/internal/Predicate.qll @@ -79,10 +79,11 @@ private module Cached { ) or // super calls - exists(Super sup, ClassType type | + exists(Super sup, ClassType type, Type supertype | mc.getBase() = sup and sup.getEnclosingPredicate().(ClassPredicate).getParent().getType() = type and - p = type.getASuperType().getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments()) + supertype in [type.getASuperType(), type.getAnInstanceofType()] and + p = supertype.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments()) ) } @@ -152,7 +153,9 @@ module PredConsistency { strictcount(PredicateOrBuiltin p0 | resolveCall(call, p0) and // aliases are expected to resolve to multiple. - not exists(p0.(ClasslessPredicate).getAlias()) + not exists(p0.(ClasslessPredicate).getAlias()) and + // overridden predicates may have multiple targets + not p0.(ClassPredicate).isOverride() ) and c > 1 and resolveCall(call, p) diff --git a/ql/src/codeql_ql/ast/internal/TreeSitter.qll b/ql/src/codeql_ql/ast/internal/TreeSitter.qll index 15191b154f2..cfef117f269 100644 --- a/ql/src/codeql_ql/ast/internal/TreeSitter.qll +++ b/ql/src/codeql_ql/ast/internal/TreeSitter.qll @@ -3,12 +3,12 @@ * Automatically generated from the tree-sitter grammar; do not edit */ -module Generated { - private import codeql.files.FileSystem - private import codeql.Locations +private import codeql.files.FileSystem +private import codeql.Locations +module QL { /** The base class for all AST nodes */ - class AstNode extends @ast_node { + class AstNode extends @ql_ast_node { /** Gets a string representation of this element. */ string toString() { result = this.getAPrimaryQlClass() } @@ -16,1759 +16,1764 @@ module Generated { Location getLocation() { none() } /** Gets the parent of this element. */ - AstNode getParent() { ast_node_parent(this, result, _) } + AstNode getParent() { ql_ast_node_parent(this, result, _) } /** Gets the index of this node among the children of its parent. */ - int getParentIndex() { ast_node_parent(this, _, result) } + int getParentIndex() { ql_ast_node_parent(this, _, result) } /** Gets a field or child node of this node. */ AstNode getAFieldOrChild() { none() } /** Gets the name of the primary QL class for this element. */ string getAPrimaryQlClass() { result = "???" } + + /** Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs. */ + string getPrimaryQlClasses() { result = concat(this.getAPrimaryQlClass(), ",") } } /** A token. */ - class Token extends @token, AstNode { + class Token extends @ql_token, AstNode { /** Gets the value of this token. */ - string getValue() { tokeninfo(this, _, _, _, result, _) } + string getValue() { ql_tokeninfo(this, _, result, _) } /** Gets the location of this token. */ - override Location getLocation() { tokeninfo(this, _, _, _, _, result) } + override Location getLocation() { ql_tokeninfo(this, _, _, result) } /** Gets a string representation of this element. */ - override string toString() { result = getValue() } + override string toString() { result = this.getValue() } /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Token" } } /** A reserved word. */ - class ReservedWord extends @reserved_word, Token { + class ReservedWord extends @ql_reserved_word, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ReservedWord" } } /** A class representing `add_expr` nodes. */ - class AddExpr extends @add_expr, AstNode { + class AddExpr extends @ql_add_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AddExpr" } /** Gets the location of this element. */ - override Location getLocation() { add_expr_def(this, _, _, _, result) } + override Location getLocation() { ql_add_expr_def(this, _, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { add_expr_def(this, result, _, _, _) } + AstNode getLeft() { ql_add_expr_def(this, result, _, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { add_expr_def(this, _, result, _, _) } + AstNode getRight() { ql_add_expr_def(this, _, result, _, _) } /** Gets the child of this node. */ - Addop getChild() { add_expr_def(this, _, _, result, _) } + Addop getChild() { ql_add_expr_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - add_expr_def(this, result, _, _, _) or - add_expr_def(this, _, result, _, _) or - add_expr_def(this, _, _, result, _) + ql_add_expr_def(this, result, _, _, _) or + ql_add_expr_def(this, _, result, _, _) or + ql_add_expr_def(this, _, _, result, _) } } /** A class representing `addop` tokens. */ - class Addop extends @token_addop, Token { + class Addop extends @ql_token_addop, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Addop" } } /** A class representing `aggId` tokens. */ - class AggId extends @token_agg_id, Token { + class AggId extends @ql_token_agg_id, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AggId" } } /** A class representing `aggregate` nodes. */ - class Aggregate extends @aggregate, AstNode { + class Aggregate extends @ql_aggregate, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Aggregate" } /** Gets the location of this element. */ - override Location getLocation() { aggregate_def(this, result) } + override Location getLocation() { ql_aggregate_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { aggregate_child(this, i, result) } + AstNode getChild(int i) { ql_aggregate_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { aggregate_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_aggregate_child(this, _, result) } } /** A class representing `annotArg` nodes. */ - class AnnotArg extends @annot_arg, AstNode { + class AnnotArg extends @ql_annot_arg, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AnnotArg" } /** Gets the location of this element. */ - override Location getLocation() { annot_arg_def(this, _, result) } + override Location getLocation() { ql_annot_arg_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { annot_arg_def(this, result, _) } + AstNode getChild() { ql_annot_arg_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { annot_arg_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_annot_arg_def(this, result, _) } } /** A class representing `annotName` tokens. */ - class AnnotName extends @token_annot_name, Token { + class AnnotName extends @ql_token_annot_name, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AnnotName" } } /** A class representing `annotation` nodes. */ - class Annotation extends @annotation, AstNode { + class Annotation extends @ql_annotation, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Annotation" } /** Gets the location of this element. */ - override Location getLocation() { annotation_def(this, _, result) } + override Location getLocation() { ql_annotation_def(this, _, result) } /** Gets the node corresponding to the field `args`. */ - AstNode getArgs(int i) { annotation_args(this, i, result) } + AstNode getArgs(int i) { ql_annotation_args(this, i, result) } /** Gets the node corresponding to the field `name`. */ - AnnotName getName() { annotation_def(this, result, _) } + AnnotName getName() { ql_annotation_def(this, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - annotation_args(this, _, result) or annotation_def(this, result, _) + ql_annotation_args(this, _, result) or ql_annotation_def(this, result, _) } } /** A class representing `aritylessPredicateExpr` nodes. */ - class AritylessPredicateExpr extends @arityless_predicate_expr, AstNode { + class AritylessPredicateExpr extends @ql_arityless_predicate_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AritylessPredicateExpr" } /** Gets the location of this element. */ - override Location getLocation() { arityless_predicate_expr_def(this, _, result) } + override Location getLocation() { ql_arityless_predicate_expr_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - LiteralId getName() { arityless_predicate_expr_def(this, result, _) } + LiteralId getName() { ql_arityless_predicate_expr_def(this, result, _) } /** Gets the child of this node. */ - ModuleExpr getChild() { arityless_predicate_expr_child(this, result) } + ModuleExpr getChild() { ql_arityless_predicate_expr_child(this, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - arityless_predicate_expr_def(this, result, _) or arityless_predicate_expr_child(this, result) + ql_arityless_predicate_expr_def(this, result, _) or + ql_arityless_predicate_expr_child(this, result) } } /** A class representing `asExpr` nodes. */ - class AsExpr extends @as_expr, AstNode { + class AsExpr extends @ql_as_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AsExpr" } /** Gets the location of this element. */ - override Location getLocation() { as_expr_def(this, result) } + override Location getLocation() { ql_as_expr_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { as_expr_child(this, i, result) } + AstNode getChild(int i) { ql_as_expr_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { as_expr_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_as_expr_child(this, _, result) } } /** A class representing `asExprs` nodes. */ - class AsExprs extends @as_exprs, AstNode { + class AsExprs extends @ql_as_exprs, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "AsExprs" } /** Gets the location of this element. */ - override Location getLocation() { as_exprs_def(this, result) } + override Location getLocation() { ql_as_exprs_def(this, result) } /** Gets the `i`th child of this node. */ - AsExpr getChild(int i) { as_exprs_child(this, i, result) } + AsExpr getChild(int i) { ql_as_exprs_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { as_exprs_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_as_exprs_child(this, _, result) } } /** A class representing `block_comment` tokens. */ - class BlockComment extends @token_block_comment, Token { + class BlockComment extends @ql_token_block_comment, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "BlockComment" } } /** A class representing `body` nodes. */ - class Body extends @body, AstNode { + class Body extends @ql_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Body" } /** Gets the location of this element. */ - override Location getLocation() { body_def(this, _, result) } + override Location getLocation() { ql_body_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { body_def(this, result, _) } + AstNode getChild() { ql_body_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { body_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_body_def(this, result, _) } } /** A class representing `bool` nodes. */ - class Bool extends @bool, AstNode { + class Bool extends @ql_bool, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Bool" } /** Gets the location of this element. */ - override Location getLocation() { bool_def(this, _, result) } + override Location getLocation() { ql_bool_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { bool_def(this, result, _) } + AstNode getChild() { ql_bool_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { bool_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_bool_def(this, result, _) } } /** A class representing `call_body` nodes. */ - class CallBody extends @call_body, AstNode { + class CallBody extends @ql_call_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "CallBody" } /** Gets the location of this element. */ - override Location getLocation() { call_body_def(this, result) } + override Location getLocation() { ql_call_body_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { call_body_child(this, i, result) } + AstNode getChild(int i) { ql_call_body_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { call_body_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_call_body_child(this, _, result) } } /** A class representing `call_or_unqual_agg_expr` nodes. */ - class CallOrUnqualAggExpr extends @call_or_unqual_agg_expr, AstNode { + class CallOrUnqualAggExpr extends @ql_call_or_unqual_agg_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "CallOrUnqualAggExpr" } /** Gets the location of this element. */ - override Location getLocation() { call_or_unqual_agg_expr_def(this, result) } + override Location getLocation() { ql_call_or_unqual_agg_expr_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { call_or_unqual_agg_expr_child(this, i, result) } + AstNode getChild(int i) { ql_call_or_unqual_agg_expr_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { call_or_unqual_agg_expr_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_call_or_unqual_agg_expr_child(this, _, result) } } /** A class representing `charpred` nodes. */ - class Charpred extends @charpred, AstNode { + class Charpred extends @ql_charpred, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Charpred" } /** Gets the location of this element. */ - override Location getLocation() { charpred_def(this, _, _, result) } + override Location getLocation() { ql_charpred_def(this, _, _, result) } /** Gets the node corresponding to the field `body`. */ - AstNode getBody() { charpred_def(this, result, _, _) } + AstNode getBody() { ql_charpred_def(this, result, _, _) } /** Gets the child of this node. */ - ClassName getChild() { charpred_def(this, _, result, _) } + ClassName getChild() { ql_charpred_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - charpred_def(this, result, _, _) or charpred_def(this, _, result, _) + ql_charpred_def(this, result, _, _) or ql_charpred_def(this, _, result, _) } } /** A class representing `classMember` nodes. */ - class ClassMember extends @class_member, AstNode { + class ClassMember extends @ql_class_member, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ClassMember" } /** Gets the location of this element. */ - override Location getLocation() { class_member_def(this, result) } + override Location getLocation() { ql_class_member_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { class_member_child(this, i, result) } + AstNode getChild(int i) { ql_class_member_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { class_member_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_class_member_child(this, _, result) } } /** A class representing `className` tokens. */ - class ClassName extends @token_class_name, Token { + class ClassName extends @ql_token_class_name, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ClassName" } } /** A class representing `classlessPredicate` nodes. */ - class ClasslessPredicate extends @classless_predicate, AstNode { + class ClasslessPredicate extends @ql_classless_predicate, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ClasslessPredicate" } /** Gets the location of this element. */ - override Location getLocation() { classless_predicate_def(this, _, _, result) } + override Location getLocation() { ql_classless_predicate_def(this, _, _, result) } /** Gets the node corresponding to the field `name`. */ - PredicateName getName() { classless_predicate_def(this, result, _, _) } + PredicateName getName() { ql_classless_predicate_def(this, result, _, _) } /** Gets the node corresponding to the field `returnType`. */ - AstNode getReturnType() { classless_predicate_def(this, _, result, _) } + AstNode getReturnType() { ql_classless_predicate_def(this, _, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { classless_predicate_child(this, i, result) } + AstNode getChild(int i) { ql_classless_predicate_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - classless_predicate_def(this, result, _, _) or - classless_predicate_def(this, _, result, _) or - classless_predicate_child(this, _, result) + ql_classless_predicate_def(this, result, _, _) or + ql_classless_predicate_def(this, _, result, _) or + ql_classless_predicate_child(this, _, result) } } /** A class representing `closure` tokens. */ - class Closure extends @token_closure, Token { + class Closure extends @ql_token_closure, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Closure" } } /** A class representing `comp_term` nodes. */ - class CompTerm extends @comp_term, AstNode { + class CompTerm extends @ql_comp_term, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "CompTerm" } /** Gets the location of this element. */ - override Location getLocation() { comp_term_def(this, _, _, _, result) } + override Location getLocation() { ql_comp_term_def(this, _, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { comp_term_def(this, result, _, _, _) } + AstNode getLeft() { ql_comp_term_def(this, result, _, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { comp_term_def(this, _, result, _, _) } + AstNode getRight() { ql_comp_term_def(this, _, result, _, _) } /** Gets the child of this node. */ - Compop getChild() { comp_term_def(this, _, _, result, _) } + Compop getChild() { ql_comp_term_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - comp_term_def(this, result, _, _, _) or - comp_term_def(this, _, result, _, _) or - comp_term_def(this, _, _, result, _) + ql_comp_term_def(this, result, _, _, _) or + ql_comp_term_def(this, _, result, _, _) or + ql_comp_term_def(this, _, _, result, _) } } /** A class representing `compop` tokens. */ - class Compop extends @token_compop, Token { + class Compop extends @ql_token_compop, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Compop" } } /** A class representing `conjunction` nodes. */ - class Conjunction extends @conjunction, AstNode { + class Conjunction extends @ql_conjunction, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Conjunction" } /** Gets the location of this element. */ - override Location getLocation() { conjunction_def(this, _, _, result) } + override Location getLocation() { ql_conjunction_def(this, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { conjunction_def(this, result, _, _) } + AstNode getLeft() { ql_conjunction_def(this, result, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { conjunction_def(this, _, result, _) } + AstNode getRight() { ql_conjunction_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - conjunction_def(this, result, _, _) or conjunction_def(this, _, result, _) + ql_conjunction_def(this, result, _, _) or ql_conjunction_def(this, _, result, _) } } /** A class representing `dataclass` nodes. */ - class Dataclass extends @dataclass, AstNode { + class Dataclass extends @ql_dataclass, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Dataclass" } /** Gets the location of this element. */ - override Location getLocation() { dataclass_def(this, _, result) } + override Location getLocation() { ql_dataclass_def(this, _, result) } /** Gets the node corresponding to the field `extends`. */ - AstNode getExtends(int i) { dataclass_extends(this, i, result) } + AstNode getExtends(int i) { ql_dataclass_extends(this, i, result) } /** Gets the node corresponding to the field `instanceof`. */ - AstNode getInstanceof(int i) { dataclass_instanceof(this, i, result) } + AstNode getInstanceof(int i) { ql_dataclass_instanceof(this, i, result) } /** Gets the node corresponding to the field `name`. */ - ClassName getName() { dataclass_def(this, result, _) } + ClassName getName() { ql_dataclass_def(this, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { dataclass_child(this, i, result) } + AstNode getChild(int i) { ql_dataclass_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - dataclass_extends(this, _, result) or - dataclass_instanceof(this, _, result) or - dataclass_def(this, result, _) or - dataclass_child(this, _, result) + ql_dataclass_extends(this, _, result) or + ql_dataclass_instanceof(this, _, result) or + ql_dataclass_def(this, result, _) or + ql_dataclass_child(this, _, result) } } /** A class representing `datatype` nodes. */ - class Datatype extends @datatype, AstNode { + class Datatype extends @ql_datatype, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Datatype" } /** Gets the location of this element. */ - override Location getLocation() { datatype_def(this, _, _, result) } + override Location getLocation() { ql_datatype_def(this, _, _, result) } /** Gets the node corresponding to the field `name`. */ - ClassName getName() { datatype_def(this, result, _, _) } + ClassName getName() { ql_datatype_def(this, result, _, _) } /** Gets the child of this node. */ - DatatypeBranches getChild() { datatype_def(this, _, result, _) } + DatatypeBranches getChild() { ql_datatype_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - datatype_def(this, result, _, _) or datatype_def(this, _, result, _) + ql_datatype_def(this, result, _, _) or ql_datatype_def(this, _, result, _) } } /** A class representing `datatypeBranch` nodes. */ - class DatatypeBranch extends @datatype_branch, AstNode { + class DatatypeBranch extends @ql_datatype_branch, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DatatypeBranch" } /** Gets the location of this element. */ - override Location getLocation() { datatype_branch_def(this, _, result) } + override Location getLocation() { ql_datatype_branch_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - ClassName getName() { datatype_branch_def(this, result, _) } + ClassName getName() { ql_datatype_branch_def(this, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { datatype_branch_child(this, i, result) } + AstNode getChild(int i) { ql_datatype_branch_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - datatype_branch_def(this, result, _) or datatype_branch_child(this, _, result) + ql_datatype_branch_def(this, result, _) or ql_datatype_branch_child(this, _, result) } } /** A class representing `datatypeBranches` nodes. */ - class DatatypeBranches extends @datatype_branches, AstNode { + class DatatypeBranches extends @ql_datatype_branches, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DatatypeBranches" } /** Gets the location of this element. */ - override Location getLocation() { datatype_branches_def(this, result) } + override Location getLocation() { ql_datatype_branches_def(this, result) } /** Gets the `i`th child of this node. */ - DatatypeBranch getChild(int i) { datatype_branches_child(this, i, result) } + DatatypeBranch getChild(int i) { ql_datatype_branches_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { datatype_branches_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_datatype_branches_child(this, _, result) } } /** A class representing `db_annotation` nodes. */ - class DbAnnotation extends @db_annotation, AstNode { + class DbAnnotation extends @ql_db_annotation, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbAnnotation" } /** Gets the location of this element. */ - override Location getLocation() { db_annotation_def(this, result) } + override Location getLocation() { ql_db_annotation_def(this, result) } /** Gets the node corresponding to the field `argsAnnotation`. */ - DbArgsAnnotation getArgsAnnotation() { db_annotation_args_annotation(this, result) } + DbArgsAnnotation getArgsAnnotation() { ql_db_annotation_args_annotation(this, result) } /** Gets the node corresponding to the field `simpleAnnotation`. */ - AnnotName getSimpleAnnotation() { db_annotation_simple_annotation(this, result) } + AnnotName getSimpleAnnotation() { ql_db_annotation_simple_annotation(this, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_annotation_args_annotation(this, result) or db_annotation_simple_annotation(this, result) + ql_db_annotation_args_annotation(this, result) or + ql_db_annotation_simple_annotation(this, result) } } /** A class representing `db_argsAnnotation` nodes. */ - class DbArgsAnnotation extends @db_args_annotation, AstNode { + class DbArgsAnnotation extends @ql_db_args_annotation, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbArgsAnnotation" } /** Gets the location of this element. */ - override Location getLocation() { db_args_annotation_def(this, _, result) } + override Location getLocation() { ql_db_args_annotation_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - AnnotName getName() { db_args_annotation_def(this, result, _) } + AnnotName getName() { ql_db_args_annotation_def(this, result, _) } /** Gets the `i`th child of this node. */ - SimpleId getChild(int i) { db_args_annotation_child(this, i, result) } + SimpleId getChild(int i) { ql_db_args_annotation_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_args_annotation_def(this, result, _) or db_args_annotation_child(this, _, result) + ql_db_args_annotation_def(this, result, _) or ql_db_args_annotation_child(this, _, result) } } /** A class representing `db_boolean` tokens. */ - class DbBoolean extends @token_db_boolean, Token { + class DbBoolean extends @ql_token_db_boolean, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbBoolean" } } /** A class representing `db_branch` nodes. */ - class DbBranch extends @db_branch, AstNode { + class DbBranch extends @ql_db_branch, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbBranch" } /** Gets the location of this element. */ - override Location getLocation() { db_branch_def(this, result) } + override Location getLocation() { ql_db_branch_def(this, result) } /** Gets the node corresponding to the field `qldoc`. */ - Qldoc getQldoc() { db_branch_qldoc(this, result) } + Qldoc getQldoc() { ql_db_branch_qldoc(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { db_branch_child(this, i, result) } + AstNode getChild(int i) { ql_db_branch_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_branch_qldoc(this, result) or db_branch_child(this, _, result) + ql_db_branch_qldoc(this, result) or ql_db_branch_child(this, _, result) } } /** A class representing `db_case` tokens. */ - class DbCase extends @token_db_case, Token { + class DbCase extends @ql_token_db_case, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbCase" } } /** A class representing `db_caseDecl` nodes. */ - class DbCaseDecl extends @db_case_decl, AstNode { + class DbCaseDecl extends @ql_db_case_decl, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbCaseDecl" } /** Gets the location of this element. */ - override Location getLocation() { db_case_decl_def(this, _, _, result) } + override Location getLocation() { ql_db_case_decl_def(this, _, _, result) } /** Gets the node corresponding to the field `base`. */ - Dbtype getBase() { db_case_decl_def(this, result, _, _) } + Dbtype getBase() { ql_db_case_decl_def(this, result, _, _) } /** Gets the node corresponding to the field `discriminator`. */ - SimpleId getDiscriminator() { db_case_decl_def(this, _, result, _) } + SimpleId getDiscriminator() { ql_db_case_decl_def(this, _, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { db_case_decl_child(this, i, result) } + AstNode getChild(int i) { ql_db_case_decl_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_case_decl_def(this, result, _, _) or - db_case_decl_def(this, _, result, _) or - db_case_decl_child(this, _, result) + ql_db_case_decl_def(this, result, _, _) or + ql_db_case_decl_def(this, _, result, _) or + ql_db_case_decl_child(this, _, result) } } /** A class representing `db_colType` nodes. */ - class DbColType extends @db_col_type, AstNode { + class DbColType extends @ql_db_col_type, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbColType" } /** Gets the location of this element. */ - override Location getLocation() { db_col_type_def(this, _, result) } + override Location getLocation() { ql_db_col_type_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { db_col_type_def(this, result, _) } + AstNode getChild() { ql_db_col_type_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { db_col_type_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_db_col_type_def(this, result, _) } } /** A class representing `db_column` nodes. */ - class DbColumn extends @db_column, AstNode { + class DbColumn extends @ql_db_column, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbColumn" } /** Gets the location of this element. */ - override Location getLocation() { db_column_def(this, _, _, _, result) } + override Location getLocation() { ql_db_column_def(this, _, _, _, result) } /** Gets the node corresponding to the field `colName`. */ - SimpleId getColName() { db_column_def(this, result, _, _, _) } + SimpleId getColName() { ql_db_column_def(this, result, _, _, _) } /** Gets the node corresponding to the field `colType`. */ - DbColType getColType() { db_column_def(this, _, result, _, _) } + DbColType getColType() { ql_db_column_def(this, _, result, _, _) } /** Gets the node corresponding to the field `isRef`. */ - DbRef getIsRef() { db_column_is_ref(this, result) } + DbRef getIsRef() { ql_db_column_is_ref(this, result) } /** Gets the node corresponding to the field `isUnique`. */ - DbUnique getIsUnique() { db_column_is_unique(this, result) } + DbUnique getIsUnique() { ql_db_column_is_unique(this, result) } /** Gets the node corresponding to the field `qldoc`. */ - Qldoc getQldoc() { db_column_qldoc(this, result) } + Qldoc getQldoc() { ql_db_column_qldoc(this, result) } /** Gets the node corresponding to the field `reprType`. */ - DbReprType getReprType() { db_column_def(this, _, _, result, _) } + DbReprType getReprType() { ql_db_column_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_column_def(this, result, _, _, _) or - db_column_def(this, _, result, _, _) or - db_column_is_ref(this, result) or - db_column_is_unique(this, result) or - db_column_qldoc(this, result) or - db_column_def(this, _, _, result, _) + ql_db_column_def(this, result, _, _, _) or + ql_db_column_def(this, _, result, _, _) or + ql_db_column_is_ref(this, result) or + ql_db_column_is_unique(this, result) or + ql_db_column_qldoc(this, result) or + ql_db_column_def(this, _, _, result, _) } } /** A class representing `db_date` tokens. */ - class DbDate extends @token_db_date, Token { + class DbDate extends @ql_token_db_date, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbDate" } } /** A class representing `db_entry` nodes. */ - class DbEntry extends @db_entry, AstNode { + class DbEntry extends @ql_db_entry, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbEntry" } /** Gets the location of this element. */ - override Location getLocation() { db_entry_def(this, _, result) } + override Location getLocation() { ql_db_entry_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { db_entry_def(this, result, _) } + AstNode getChild() { ql_db_entry_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { db_entry_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_db_entry_def(this, result, _) } } /** A class representing `db_float` tokens. */ - class DbFloat extends @token_db_float, Token { + class DbFloat extends @ql_token_db_float, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbFloat" } } /** A class representing `db_int` tokens. */ - class DbInt extends @token_db_int, Token { + class DbInt extends @ql_token_db_int, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbInt" } } /** A class representing `db_ref` tokens. */ - class DbRef extends @token_db_ref, Token { + class DbRef extends @ql_token_db_ref, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbRef" } } /** A class representing `db_reprType` nodes. */ - class DbReprType extends @db_repr_type, AstNode { + class DbReprType extends @ql_db_repr_type, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbReprType" } /** Gets the location of this element. */ - override Location getLocation() { db_repr_type_def(this, result) } + override Location getLocation() { ql_db_repr_type_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { db_repr_type_child(this, i, result) } + AstNode getChild(int i) { ql_db_repr_type_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { db_repr_type_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_db_repr_type_child(this, _, result) } } /** A class representing `db_string` tokens. */ - class DbString extends @token_db_string, Token { + class DbString extends @ql_token_db_string, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbString" } } /** A class representing `db_table` nodes. */ - class DbTable extends @db_table, AstNode { + class DbTable extends @ql_db_table, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbTable" } /** Gets the location of this element. */ - override Location getLocation() { db_table_def(this, _, result) } + override Location getLocation() { ql_db_table_def(this, _, result) } /** Gets the node corresponding to the field `tableName`. */ - DbTableName getTableName() { db_table_def(this, result, _) } + DbTableName getTableName() { ql_db_table_def(this, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { db_table_child(this, i, result) } + AstNode getChild(int i) { ql_db_table_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_table_def(this, result, _) or db_table_child(this, _, result) + ql_db_table_def(this, result, _) or ql_db_table_child(this, _, result) } } /** A class representing `db_tableName` nodes. */ - class DbTableName extends @db_table_name, AstNode { + class DbTableName extends @ql_db_table_name, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbTableName" } /** Gets the location of this element. */ - override Location getLocation() { db_table_name_def(this, _, result) } + override Location getLocation() { ql_db_table_name_def(this, _, result) } /** Gets the child of this node. */ - SimpleId getChild() { db_table_name_def(this, result, _) } + SimpleId getChild() { ql_db_table_name_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { db_table_name_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_db_table_name_def(this, result, _) } } /** A class representing `db_unionDecl` nodes. */ - class DbUnionDecl extends @db_union_decl, AstNode { + class DbUnionDecl extends @ql_db_union_decl, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbUnionDecl" } /** Gets the location of this element. */ - override Location getLocation() { db_union_decl_def(this, _, result) } + override Location getLocation() { ql_db_union_decl_def(this, _, result) } /** Gets the node corresponding to the field `base`. */ - Dbtype getBase() { db_union_decl_def(this, result, _) } + Dbtype getBase() { ql_db_union_decl_def(this, result, _) } /** Gets the `i`th child of this node. */ - Dbtype getChild(int i) { db_union_decl_child(this, i, result) } + Dbtype getChild(int i) { ql_db_union_decl_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - db_union_decl_def(this, result, _) or db_union_decl_child(this, _, result) + ql_db_union_decl_def(this, result, _) or ql_db_union_decl_child(this, _, result) } } /** A class representing `db_unique` tokens. */ - class DbUnique extends @token_db_unique, Token { + class DbUnique extends @ql_token_db_unique, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbUnique" } } /** A class representing `db_varchar` tokens. */ - class DbVarchar extends @token_db_varchar, Token { + class DbVarchar extends @ql_token_db_varchar, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "DbVarchar" } } /** A class representing `dbtype` tokens. */ - class Dbtype extends @token_dbtype, Token { + class Dbtype extends @ql_token_dbtype, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Dbtype" } } /** A class representing `direction` tokens. */ - class Direction extends @token_direction, Token { + class Direction extends @ql_token_direction, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Direction" } } /** A class representing `disjunction` nodes. */ - class Disjunction extends @disjunction, AstNode { + class Disjunction extends @ql_disjunction, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Disjunction" } /** Gets the location of this element. */ - override Location getLocation() { disjunction_def(this, _, _, result) } + override Location getLocation() { ql_disjunction_def(this, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { disjunction_def(this, result, _, _) } + AstNode getLeft() { ql_disjunction_def(this, result, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { disjunction_def(this, _, result, _) } + AstNode getRight() { ql_disjunction_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - disjunction_def(this, result, _, _) or disjunction_def(this, _, result, _) + ql_disjunction_def(this, result, _, _) or ql_disjunction_def(this, _, result, _) } } /** A class representing `empty` tokens. */ - class Empty extends @token_empty, Token { + class Empty extends @ql_token_empty, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Empty" } } /** A class representing `expr_aggregate_body` nodes. */ - class ExprAggregateBody extends @expr_aggregate_body, AstNode { + class ExprAggregateBody extends @ql_expr_aggregate_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ExprAggregateBody" } /** Gets the location of this element. */ - override Location getLocation() { expr_aggregate_body_def(this, _, result) } + override Location getLocation() { ql_expr_aggregate_body_def(this, _, result) } /** Gets the node corresponding to the field `asExprs`. */ - AsExprs getAsExprs() { expr_aggregate_body_def(this, result, _) } + AsExprs getAsExprs() { ql_expr_aggregate_body_def(this, result, _) } /** Gets the node corresponding to the field `orderBys`. */ - OrderBys getOrderBys() { expr_aggregate_body_order_bys(this, result) } + OrderBys getOrderBys() { ql_expr_aggregate_body_order_bys(this, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - expr_aggregate_body_def(this, result, _) or expr_aggregate_body_order_bys(this, result) + ql_expr_aggregate_body_def(this, result, _) or ql_expr_aggregate_body_order_bys(this, result) } } /** A class representing `expr_annotation` nodes. */ - class ExprAnnotation extends @expr_annotation, AstNode { + class ExprAnnotation extends @ql_expr_annotation, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ExprAnnotation" } /** Gets the location of this element. */ - override Location getLocation() { expr_annotation_def(this, _, _, _, result) } + override Location getLocation() { ql_expr_annotation_def(this, _, _, _, result) } /** Gets the node corresponding to the field `annot_arg`. */ - AnnotName getAnnotArg() { expr_annotation_def(this, result, _, _, _) } + AnnotName getAnnotArg() { ql_expr_annotation_def(this, result, _, _, _) } /** Gets the node corresponding to the field `name`. */ - AnnotName getName() { expr_annotation_def(this, _, result, _, _) } + AnnotName getName() { ql_expr_annotation_def(this, _, result, _, _) } /** Gets the child of this node. */ - AstNode getChild() { expr_annotation_def(this, _, _, result, _) } + AstNode getChild() { ql_expr_annotation_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - expr_annotation_def(this, result, _, _, _) or - expr_annotation_def(this, _, result, _, _) or - expr_annotation_def(this, _, _, result, _) + ql_expr_annotation_def(this, result, _, _, _) or + ql_expr_annotation_def(this, _, result, _, _) or + ql_expr_annotation_def(this, _, _, result, _) } } /** A class representing `false` tokens. */ - class False extends @token_false, Token { + class False extends @ql_token_false, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "False" } } /** A class representing `field` nodes. */ - class Field extends @field, AstNode { + class Field extends @ql_field, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Field" } /** Gets the location of this element. */ - override Location getLocation() { field_def(this, _, result) } + override Location getLocation() { ql_field_def(this, _, result) } /** Gets the child of this node. */ - VarDecl getChild() { field_def(this, result, _) } + VarDecl getChild() { ql_field_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { field_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_field_def(this, result, _) } } /** A class representing `float` tokens. */ - class Float extends @token_float, Token { + class Float extends @ql_token_float, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Float" } } /** A class representing `full_aggregate_body` nodes. */ - class FullAggregateBody extends @full_aggregate_body, AstNode { + class FullAggregateBody extends @ql_full_aggregate_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "FullAggregateBody" } /** Gets the location of this element. */ - override Location getLocation() { full_aggregate_body_def(this, result) } + override Location getLocation() { ql_full_aggregate_body_def(this, result) } /** Gets the node corresponding to the field `asExprs`. */ - AsExprs getAsExprs() { full_aggregate_body_as_exprs(this, result) } + AsExprs getAsExprs() { ql_full_aggregate_body_as_exprs(this, result) } /** Gets the node corresponding to the field `guard`. */ - AstNode getGuard() { full_aggregate_body_guard(this, result) } + AstNode getGuard() { ql_full_aggregate_body_guard(this, result) } /** Gets the node corresponding to the field `orderBys`. */ - OrderBys getOrderBys() { full_aggregate_body_order_bys(this, result) } + OrderBys getOrderBys() { ql_full_aggregate_body_order_bys(this, result) } /** Gets the `i`th child of this node. */ - VarDecl getChild(int i) { full_aggregate_body_child(this, i, result) } + VarDecl getChild(int i) { ql_full_aggregate_body_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - full_aggregate_body_as_exprs(this, result) or - full_aggregate_body_guard(this, result) or - full_aggregate_body_order_bys(this, result) or - full_aggregate_body_child(this, _, result) + ql_full_aggregate_body_as_exprs(this, result) or + ql_full_aggregate_body_guard(this, result) or + ql_full_aggregate_body_order_bys(this, result) or + ql_full_aggregate_body_child(this, _, result) } } /** A class representing `higherOrderTerm` nodes. */ - class HigherOrderTerm extends @higher_order_term, AstNode { + class HigherOrderTerm extends @ql_higher_order_term, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "HigherOrderTerm" } /** Gets the location of this element. */ - override Location getLocation() { higher_order_term_def(this, _, result) } + override Location getLocation() { ql_higher_order_term_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - LiteralId getName() { higher_order_term_def(this, result, _) } + LiteralId getName() { ql_higher_order_term_def(this, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { higher_order_term_child(this, i, result) } + AstNode getChild(int i) { ql_higher_order_term_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - higher_order_term_def(this, result, _) or higher_order_term_child(this, _, result) + ql_higher_order_term_def(this, result, _) or ql_higher_order_term_child(this, _, result) } } /** A class representing `if_term` nodes. */ - class IfTerm extends @if_term, AstNode { + class IfTerm extends @ql_if_term, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "IfTerm" } /** Gets the location of this element. */ - override Location getLocation() { if_term_def(this, _, _, _, result) } + override Location getLocation() { ql_if_term_def(this, _, _, _, result) } /** Gets the node corresponding to the field `cond`. */ - AstNode getCond() { if_term_def(this, result, _, _, _) } + AstNode getCond() { ql_if_term_def(this, result, _, _, _) } /** Gets the node corresponding to the field `first`. */ - AstNode getFirst() { if_term_def(this, _, result, _, _) } + AstNode getFirst() { ql_if_term_def(this, _, result, _, _) } /** Gets the node corresponding to the field `second`. */ - AstNode getSecond() { if_term_def(this, _, _, result, _) } + AstNode getSecond() { ql_if_term_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - if_term_def(this, result, _, _, _) or - if_term_def(this, _, result, _, _) or - if_term_def(this, _, _, result, _) + ql_if_term_def(this, result, _, _, _) or + ql_if_term_def(this, _, result, _, _) or + ql_if_term_def(this, _, _, result, _) } } /** A class representing `implication` nodes. */ - class Implication extends @implication, AstNode { + class Implication extends @ql_implication, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Implication" } /** Gets the location of this element. */ - override Location getLocation() { implication_def(this, _, _, result) } + override Location getLocation() { ql_implication_def(this, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { implication_def(this, result, _, _) } + AstNode getLeft() { ql_implication_def(this, result, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { implication_def(this, _, result, _) } + AstNode getRight() { ql_implication_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - implication_def(this, result, _, _) or implication_def(this, _, result, _) + ql_implication_def(this, result, _, _) or ql_implication_def(this, _, result, _) } } /** A class representing `importDirective` nodes. */ - class ImportDirective extends @import_directive, AstNode { + class ImportDirective extends @ql_import_directive, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ImportDirective" } /** Gets the location of this element. */ - override Location getLocation() { import_directive_def(this, result) } + override Location getLocation() { ql_import_directive_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { import_directive_child(this, i, result) } + AstNode getChild(int i) { ql_import_directive_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { import_directive_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_import_directive_child(this, _, result) } } /** A class representing `importModuleExpr` nodes. */ - class ImportModuleExpr extends @import_module_expr, AstNode { + class ImportModuleExpr extends @ql_import_module_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ImportModuleExpr" } /** Gets the location of this element. */ - override Location getLocation() { import_module_expr_def(this, _, result) } + override Location getLocation() { ql_import_module_expr_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - SimpleId getName(int i) { import_module_expr_name(this, i, result) } + SimpleId getName(int i) { ql_import_module_expr_name(this, i, result) } /** Gets the child of this node. */ - QualModuleExpr getChild() { import_module_expr_def(this, result, _) } + QualModuleExpr getChild() { ql_import_module_expr_def(this, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - import_module_expr_name(this, _, result) or import_module_expr_def(this, result, _) + ql_import_module_expr_name(this, _, result) or ql_import_module_expr_def(this, result, _) } } /** A class representing `in_expr` nodes. */ - class InExpr extends @in_expr, AstNode { + class InExpr extends @ql_in_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "InExpr" } /** Gets the location of this element. */ - override Location getLocation() { in_expr_def(this, _, _, result) } + override Location getLocation() { ql_in_expr_def(this, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { in_expr_def(this, result, _, _) } + AstNode getLeft() { ql_in_expr_def(this, result, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { in_expr_def(this, _, result, _) } + AstNode getRight() { ql_in_expr_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - in_expr_def(this, result, _, _) or in_expr_def(this, _, result, _) + ql_in_expr_def(this, result, _, _) or ql_in_expr_def(this, _, result, _) } } /** A class representing `instance_of` nodes. */ - class InstanceOf extends @instance_of, AstNode { + class InstanceOf extends @ql_instance_of, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "InstanceOf" } /** Gets the location of this element. */ - override Location getLocation() { instance_of_def(this, result) } + override Location getLocation() { ql_instance_of_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { instance_of_child(this, i, result) } + AstNode getChild(int i) { ql_instance_of_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { instance_of_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_instance_of_child(this, _, result) } } /** A class representing `integer` tokens. */ - class Integer extends @token_integer, Token { + class Integer extends @ql_token_integer, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Integer" } } /** A class representing `line_comment` tokens. */ - class LineComment extends @token_line_comment, Token { + class LineComment extends @ql_token_line_comment, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "LineComment" } } /** A class representing `literal` nodes. */ - class Literal extends @literal, AstNode { + class Literal extends @ql_literal, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Literal" } /** Gets the location of this element. */ - override Location getLocation() { literal_def(this, _, result) } + override Location getLocation() { ql_literal_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { literal_def(this, result, _) } + AstNode getChild() { ql_literal_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { literal_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_literal_def(this, result, _) } } /** A class representing `literalId` tokens. */ - class LiteralId extends @token_literal_id, Token { + class LiteralId extends @ql_token_literal_id, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "LiteralId" } } /** A class representing `memberPredicate` nodes. */ - class MemberPredicate extends @member_predicate, AstNode { + class MemberPredicate extends @ql_member_predicate, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "MemberPredicate" } /** Gets the location of this element. */ - override Location getLocation() { member_predicate_def(this, _, _, result) } + override Location getLocation() { ql_member_predicate_def(this, _, _, result) } /** Gets the node corresponding to the field `name`. */ - PredicateName getName() { member_predicate_def(this, result, _, _) } + PredicateName getName() { ql_member_predicate_def(this, result, _, _) } /** Gets the node corresponding to the field `returnType`. */ - AstNode getReturnType() { member_predicate_def(this, _, result, _) } + AstNode getReturnType() { ql_member_predicate_def(this, _, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { member_predicate_child(this, i, result) } + AstNode getChild(int i) { ql_member_predicate_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - member_predicate_def(this, result, _, _) or - member_predicate_def(this, _, result, _) or - member_predicate_child(this, _, result) + ql_member_predicate_def(this, result, _, _) or + ql_member_predicate_def(this, _, result, _) or + ql_member_predicate_child(this, _, result) } } /** A class representing `module` nodes. */ - class Module extends @module, AstNode { + class Module extends @ql_module, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Module" } /** Gets the location of this element. */ - override Location getLocation() { module_def(this, _, result) } + override Location getLocation() { ql_module_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - ModuleName getName() { module_def(this, result, _) } + ModuleName getName() { ql_module_def(this, result, _) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { module_child(this, i, result) } + AstNode getChild(int i) { ql_module_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - module_def(this, result, _) or module_child(this, _, result) + ql_module_def(this, result, _) or ql_module_child(this, _, result) } } /** A class representing `moduleAliasBody` nodes. */ - class ModuleAliasBody extends @module_alias_body, AstNode { + class ModuleAliasBody extends @ql_module_alias_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ModuleAliasBody" } /** Gets the location of this element. */ - override Location getLocation() { module_alias_body_def(this, _, result) } + override Location getLocation() { ql_module_alias_body_def(this, _, result) } /** Gets the child of this node. */ - ModuleExpr getChild() { module_alias_body_def(this, result, _) } + ModuleExpr getChild() { ql_module_alias_body_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { module_alias_body_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_module_alias_body_def(this, result, _) } } /** A class representing `moduleExpr` nodes. */ - class ModuleExpr extends @module_expr, AstNode { + class ModuleExpr extends @ql_module_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ModuleExpr" } /** Gets the location of this element. */ - override Location getLocation() { module_expr_def(this, _, result) } + override Location getLocation() { ql_module_expr_def(this, _, result) } /** Gets the node corresponding to the field `name`. */ - SimpleId getName() { module_expr_name(this, result) } + SimpleId getName() { ql_module_expr_name(this, result) } /** Gets the child of this node. */ - AstNode getChild() { module_expr_def(this, result, _) } + AstNode getChild() { ql_module_expr_def(this, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - module_expr_name(this, result) or module_expr_def(this, result, _) + ql_module_expr_name(this, result) or ql_module_expr_def(this, result, _) } } /** A class representing `moduleMember` nodes. */ - class ModuleMember extends @module_member, AstNode { + class ModuleMember extends @ql_module_member, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ModuleMember" } /** Gets the location of this element. */ - override Location getLocation() { module_member_def(this, result) } + override Location getLocation() { ql_module_member_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { module_member_child(this, i, result) } + AstNode getChild(int i) { ql_module_member_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { module_member_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_module_member_child(this, _, result) } } /** A class representing `moduleName` nodes. */ - class ModuleName extends @module_name, AstNode { + class ModuleName extends @ql_module_name, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ModuleName" } /** Gets the location of this element. */ - override Location getLocation() { module_name_def(this, _, result) } + override Location getLocation() { ql_module_name_def(this, _, result) } /** Gets the child of this node. */ - SimpleId getChild() { module_name_def(this, result, _) } + SimpleId getChild() { ql_module_name_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { module_name_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_module_name_def(this, result, _) } } /** A class representing `mul_expr` nodes. */ - class MulExpr extends @mul_expr, AstNode { + class MulExpr extends @ql_mul_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "MulExpr" } /** Gets the location of this element. */ - override Location getLocation() { mul_expr_def(this, _, _, _, result) } + override Location getLocation() { ql_mul_expr_def(this, _, _, _, result) } /** Gets the node corresponding to the field `left`. */ - AstNode getLeft() { mul_expr_def(this, result, _, _, _) } + AstNode getLeft() { ql_mul_expr_def(this, result, _, _, _) } /** Gets the node corresponding to the field `right`. */ - AstNode getRight() { mul_expr_def(this, _, result, _, _) } + AstNode getRight() { ql_mul_expr_def(this, _, result, _, _) } /** Gets the child of this node. */ - Mulop getChild() { mul_expr_def(this, _, _, result, _) } + Mulop getChild() { ql_mul_expr_def(this, _, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - mul_expr_def(this, result, _, _, _) or - mul_expr_def(this, _, result, _, _) or - mul_expr_def(this, _, _, result, _) + ql_mul_expr_def(this, result, _, _, _) or + ql_mul_expr_def(this, _, result, _, _) or + ql_mul_expr_def(this, _, _, result, _) } } /** A class representing `mulop` tokens. */ - class Mulop extends @token_mulop, Token { + class Mulop extends @ql_token_mulop, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Mulop" } } /** A class representing `negation` nodes. */ - class Negation extends @negation, AstNode { + class Negation extends @ql_negation, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Negation" } /** Gets the location of this element. */ - override Location getLocation() { negation_def(this, _, result) } + override Location getLocation() { ql_negation_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { negation_def(this, result, _) } + AstNode getChild() { ql_negation_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { negation_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_negation_def(this, result, _) } } /** A class representing `orderBy` nodes. */ - class OrderBy extends @order_by, AstNode { + class OrderBy extends @ql_order_by, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "OrderBy" } /** Gets the location of this element. */ - override Location getLocation() { order_by_def(this, result) } + override Location getLocation() { ql_order_by_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { order_by_child(this, i, result) } + AstNode getChild(int i) { ql_order_by_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { order_by_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_order_by_child(this, _, result) } } /** A class representing `orderBys` nodes. */ - class OrderBys extends @order_bys, AstNode { + class OrderBys extends @ql_order_bys, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "OrderBys" } /** Gets the location of this element. */ - override Location getLocation() { order_bys_def(this, result) } + override Location getLocation() { ql_order_bys_def(this, result) } /** Gets the `i`th child of this node. */ - OrderBy getChild(int i) { order_bys_child(this, i, result) } + OrderBy getChild(int i) { ql_order_bys_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { order_bys_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_order_bys_child(this, _, result) } } /** A class representing `par_expr` nodes. */ - class ParExpr extends @par_expr, AstNode { + class ParExpr extends @ql_par_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "ParExpr" } /** Gets the location of this element. */ - override Location getLocation() { par_expr_def(this, _, result) } + override Location getLocation() { ql_par_expr_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { par_expr_def(this, result, _) } + AstNode getChild() { ql_par_expr_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { par_expr_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_par_expr_def(this, result, _) } } /** A class representing `predicate` tokens. */ - class Predicate extends @token_predicate, Token { + class Predicate extends @ql_token_predicate, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Predicate" } } /** A class representing `predicateAliasBody` nodes. */ - class PredicateAliasBody extends @predicate_alias_body, AstNode { + class PredicateAliasBody extends @ql_predicate_alias_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "PredicateAliasBody" } /** Gets the location of this element. */ - override Location getLocation() { predicate_alias_body_def(this, _, result) } + override Location getLocation() { ql_predicate_alias_body_def(this, _, result) } /** Gets the child of this node. */ - PredicateExpr getChild() { predicate_alias_body_def(this, result, _) } + PredicateExpr getChild() { ql_predicate_alias_body_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { predicate_alias_body_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_predicate_alias_body_def(this, result, _) } } /** A class representing `predicateExpr` nodes. */ - class PredicateExpr extends @predicate_expr, AstNode { + class PredicateExpr extends @ql_predicate_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "PredicateExpr" } /** Gets the location of this element. */ - override Location getLocation() { predicate_expr_def(this, result) } + override Location getLocation() { ql_predicate_expr_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { predicate_expr_child(this, i, result) } + AstNode getChild(int i) { ql_predicate_expr_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { predicate_expr_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_predicate_expr_child(this, _, result) } } /** A class representing `predicateName` tokens. */ - class PredicateName extends @token_predicate_name, Token { + class PredicateName extends @ql_token_predicate_name, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "PredicateName" } } /** A class representing `prefix_cast` nodes. */ - class PrefixCast extends @prefix_cast, AstNode { + class PrefixCast extends @ql_prefix_cast, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "PrefixCast" } /** Gets the location of this element. */ - override Location getLocation() { prefix_cast_def(this, result) } + override Location getLocation() { ql_prefix_cast_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { prefix_cast_child(this, i, result) } + AstNode getChild(int i) { ql_prefix_cast_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { prefix_cast_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_prefix_cast_child(this, _, result) } } /** A class representing `primitiveType` tokens. */ - class PrimitiveType extends @token_primitive_type, Token { + class PrimitiveType extends @ql_token_primitive_type, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "PrimitiveType" } } /** A class representing `ql` nodes. */ - class Ql extends @ql, AstNode { + class Ql extends @ql_ql, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Ql" } /** Gets the location of this element. */ - override Location getLocation() { ql_def(this, result) } + override Location getLocation() { ql_ql_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { ql_child(this, i, result) } + AstNode getChild(int i) { ql_ql_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { ql_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_ql_child(this, _, result) } } /** A class representing `qldoc` tokens. */ - class Qldoc extends @token_qldoc, Token { + class Qldoc extends @ql_token_qldoc, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Qldoc" } } /** A class representing `qualModuleExpr` nodes. */ - class QualModuleExpr extends @qual_module_expr, AstNode { + class QualModuleExpr extends @ql_qual_module_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "QualModuleExpr" } /** Gets the location of this element. */ - override Location getLocation() { qual_module_expr_def(this, result) } + override Location getLocation() { ql_qual_module_expr_def(this, result) } /** Gets the node corresponding to the field `name`. */ - SimpleId getName(int i) { qual_module_expr_name(this, i, result) } + SimpleId getName(int i) { ql_qual_module_expr_name(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { qual_module_expr_name(this, _, result) } + override AstNode getAFieldOrChild() { ql_qual_module_expr_name(this, _, result) } } /** A class representing `qualifiedRhs` nodes. */ - class QualifiedRhs extends @qualified_rhs, AstNode { + class QualifiedRhs extends @ql_qualified_rhs, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "QualifiedRhs" } /** Gets the location of this element. */ - override Location getLocation() { qualified_rhs_def(this, result) } + override Location getLocation() { ql_qualified_rhs_def(this, result) } /** Gets the node corresponding to the field `name`. */ - PredicateName getName() { qualified_rhs_name(this, result) } + PredicateName getName() { ql_qualified_rhs_name(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { qualified_rhs_child(this, i, result) } + AstNode getChild(int i) { ql_qualified_rhs_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - qualified_rhs_name(this, result) or qualified_rhs_child(this, _, result) + ql_qualified_rhs_name(this, result) or ql_qualified_rhs_child(this, _, result) } } /** A class representing `qualified_expr` nodes. */ - class QualifiedExpr extends @qualified_expr, AstNode { + class QualifiedExpr extends @ql_qualified_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "QualifiedExpr" } /** Gets the location of this element. */ - override Location getLocation() { qualified_expr_def(this, result) } + override Location getLocation() { ql_qualified_expr_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { qualified_expr_child(this, i, result) } + AstNode getChild(int i) { ql_qualified_expr_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { qualified_expr_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_qualified_expr_child(this, _, result) } } /** A class representing `quantified` nodes. */ - class Quantified extends @quantified, AstNode { + class Quantified extends @ql_quantified, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Quantified" } /** Gets the location of this element. */ - override Location getLocation() { quantified_def(this, result) } + override Location getLocation() { ql_quantified_def(this, result) } /** Gets the node corresponding to the field `expr`. */ - AstNode getExpr() { quantified_expr(this, result) } + AstNode getExpr() { ql_quantified_expr(this, result) } /** Gets the node corresponding to the field `formula`. */ - AstNode getFormula() { quantified_formula(this, result) } + AstNode getFormula() { ql_quantified_formula(this, result) } /** Gets the node corresponding to the field `range`. */ - AstNode getRange() { quantified_range(this, result) } + AstNode getRange() { ql_quantified_range(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { quantified_child(this, i, result) } + AstNode getChild(int i) { ql_quantified_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - quantified_expr(this, result) or - quantified_formula(this, result) or - quantified_range(this, result) or - quantified_child(this, _, result) + ql_quantified_expr(this, result) or + ql_quantified_formula(this, result) or + ql_quantified_range(this, result) or + ql_quantified_child(this, _, result) } } /** A class representing `quantifier` tokens. */ - class Quantifier extends @token_quantifier, Token { + class Quantifier extends @ql_token_quantifier, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Quantifier" } } /** A class representing `range` nodes. */ - class Range extends @range, AstNode { + class Range extends @ql_range, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Range" } /** Gets the location of this element. */ - override Location getLocation() { range_def(this, _, _, result) } + override Location getLocation() { ql_range_def(this, _, _, result) } /** Gets the node corresponding to the field `lower`. */ - AstNode getLower() { range_def(this, result, _, _) } + AstNode getLower() { ql_range_def(this, result, _, _) } /** Gets the node corresponding to the field `upper`. */ - AstNode getUpper() { range_def(this, _, result, _) } + AstNode getUpper() { ql_range_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - range_def(this, result, _, _) or range_def(this, _, result, _) + ql_range_def(this, result, _, _) or ql_range_def(this, _, result, _) } } /** A class representing `result` tokens. */ - class Result extends @token_result, Token { + class Result extends @ql_token_result, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Result" } } /** A class representing `select` nodes. */ - class Select extends @select, AstNode { + class Select extends @ql_select, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Select" } /** Gets the location of this element. */ - override Location getLocation() { select_def(this, result) } + override Location getLocation() { ql_select_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { select_child(this, i, result) } + AstNode getChild(int i) { ql_select_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { select_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_select_child(this, _, result) } } /** A class representing `set_literal` nodes. */ - class SetLiteral extends @set_literal, AstNode { + class SetLiteral extends @ql_set_literal, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "SetLiteral" } /** Gets the location of this element. */ - override Location getLocation() { set_literal_def(this, result) } + override Location getLocation() { ql_set_literal_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { set_literal_child(this, i, result) } + AstNode getChild(int i) { ql_set_literal_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { set_literal_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_set_literal_child(this, _, result) } } /** A class representing `simpleId` tokens. */ - class SimpleId extends @token_simple_id, Token { + class SimpleId extends @ql_token_simple_id, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "SimpleId" } } /** A class representing `specialId` tokens. */ - class SpecialId extends @token_special_id, Token { + class SpecialId extends @ql_token_special_id, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "SpecialId" } } /** A class representing `special_call` nodes. */ - class SpecialCall extends @special_call, AstNode { + class SpecialCall extends @ql_special_call, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "SpecialCall" } /** Gets the location of this element. */ - override Location getLocation() { special_call_def(this, _, result) } + override Location getLocation() { ql_special_call_def(this, _, result) } /** Gets the child of this node. */ - SpecialId getChild() { special_call_def(this, result, _) } + SpecialId getChild() { ql_special_call_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { special_call_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_special_call_def(this, result, _) } } /** A class representing `string` tokens. */ - class String extends @token_string, Token { + class String extends @ql_token_string, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "String" } } /** A class representing `super` tokens. */ - class Super extends @token_super, Token { + class Super extends @ql_token_super, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Super" } } /** A class representing `super_ref` nodes. */ - class SuperRef extends @super_ref, AstNode { + class SuperRef extends @ql_super_ref, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "SuperRef" } /** Gets the location of this element. */ - override Location getLocation() { super_ref_def(this, result) } + override Location getLocation() { ql_super_ref_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { super_ref_child(this, i, result) } + AstNode getChild(int i) { ql_super_ref_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { super_ref_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_super_ref_child(this, _, result) } } /** A class representing `this` tokens. */ - class This extends @token_this, Token { + class This extends @ql_token_this, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "This" } } /** A class representing `true` tokens. */ - class True extends @token_true, Token { + class True extends @ql_token_true, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "True" } } /** A class representing `typeAliasBody` nodes. */ - class TypeAliasBody extends @type_alias_body, AstNode { + class TypeAliasBody extends @ql_type_alias_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "TypeAliasBody" } /** Gets the location of this element. */ - override Location getLocation() { type_alias_body_def(this, _, result) } + override Location getLocation() { ql_type_alias_body_def(this, _, result) } /** Gets the child of this node. */ - TypeExpr getChild() { type_alias_body_def(this, result, _) } + TypeExpr getChild() { ql_type_alias_body_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { type_alias_body_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_type_alias_body_def(this, result, _) } } /** A class representing `typeExpr` nodes. */ - class TypeExpr extends @type_expr, AstNode { + class TypeExpr extends @ql_type_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "TypeExpr" } /** Gets the location of this element. */ - override Location getLocation() { type_expr_def(this, result) } + override Location getLocation() { ql_type_expr_def(this, result) } /** Gets the node corresponding to the field `name`. */ - ClassName getName() { type_expr_name(this, result) } + ClassName getName() { ql_type_expr_name(this, result) } /** Gets the child of this node. */ - AstNode getChild() { type_expr_child(this, result) } + AstNode getChild() { ql_type_expr_child(this, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - type_expr_name(this, result) or type_expr_child(this, result) + ql_type_expr_name(this, result) or ql_type_expr_child(this, result) } } /** A class representing `typeUnionBody` nodes. */ - class TypeUnionBody extends @type_union_body, AstNode { + class TypeUnionBody extends @ql_type_union_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "TypeUnionBody" } /** Gets the location of this element. */ - override Location getLocation() { type_union_body_def(this, result) } + override Location getLocation() { ql_type_union_body_def(this, result) } /** Gets the `i`th child of this node. */ - TypeExpr getChild(int i) { type_union_body_child(this, i, result) } + TypeExpr getChild(int i) { ql_type_union_body_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { type_union_body_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_type_union_body_child(this, _, result) } } /** A class representing `unary_expr` nodes. */ - class UnaryExpr extends @unary_expr, AstNode { + class UnaryExpr extends @ql_unary_expr, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "UnaryExpr" } /** Gets the location of this element. */ - override Location getLocation() { unary_expr_def(this, result) } + override Location getLocation() { ql_unary_expr_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { unary_expr_child(this, i, result) } + AstNode getChild(int i) { ql_unary_expr_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { unary_expr_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_unary_expr_child(this, _, result) } } /** A class representing `underscore` tokens. */ - class Underscore extends @token_underscore, Token { + class Underscore extends @ql_token_underscore, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Underscore" } } /** A class representing `unop` tokens. */ - class Unop extends @token_unop, Token { + class Unop extends @ql_token_unop, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Unop" } } /** A class representing `unqual_agg_body` nodes. */ - class UnqualAggBody extends @unqual_agg_body, AstNode { + class UnqualAggBody extends @ql_unqual_agg_body, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "UnqualAggBody" } /** Gets the location of this element. */ - override Location getLocation() { unqual_agg_body_def(this, result) } + override Location getLocation() { ql_unqual_agg_body_def(this, result) } /** Gets the node corresponding to the field `asExprs`. */ - AstNode getAsExprs(int i) { unqual_agg_body_as_exprs(this, i, result) } + AstNode getAsExprs(int i) { ql_unqual_agg_body_as_exprs(this, i, result) } /** Gets the node corresponding to the field `guard`. */ - AstNode getGuard() { unqual_agg_body_guard(this, result) } + AstNode getGuard() { ql_unqual_agg_body_guard(this, result) } /** Gets the `i`th child of this node. */ - VarDecl getChild(int i) { unqual_agg_body_child(this, i, result) } + VarDecl getChild(int i) { ql_unqual_agg_body_child(this, i, result) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - unqual_agg_body_as_exprs(this, _, result) or - unqual_agg_body_guard(this, result) or - unqual_agg_body_child(this, _, result) + ql_unqual_agg_body_as_exprs(this, _, result) or + ql_unqual_agg_body_guard(this, result) or + ql_unqual_agg_body_child(this, _, result) } } /** A class representing `varDecl` nodes. */ - class VarDecl extends @var_decl, AstNode { + class VarDecl extends @ql_var_decl, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "VarDecl" } /** Gets the location of this element. */ - override Location getLocation() { var_decl_def(this, result) } + override Location getLocation() { ql_var_decl_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { var_decl_child(this, i, result) } + AstNode getChild(int i) { ql_var_decl_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { var_decl_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_var_decl_child(this, _, result) } } /** A class representing `varName` nodes. */ - class VarName extends @var_name, AstNode { + class VarName extends @ql_var_name, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "VarName" } /** Gets the location of this element. */ - override Location getLocation() { var_name_def(this, _, result) } + override Location getLocation() { ql_var_name_def(this, _, result) } /** Gets the child of this node. */ - SimpleId getChild() { var_name_def(this, result, _) } + SimpleId getChild() { ql_var_name_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { var_name_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_var_name_def(this, result, _) } } /** A class representing `variable` nodes. */ - class Variable extends @variable, AstNode { + class Variable extends @ql_variable, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "Variable" } /** Gets the location of this element. */ - override Location getLocation() { variable_def(this, _, result) } + override Location getLocation() { ql_variable_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { variable_def(this, result, _) } + AstNode getChild() { ql_variable_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { variable_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_variable_def(this, result, _) } } /** A class representing `yaml_comment` nodes. */ - class YamlComment extends @yaml_comment, AstNode { + class YamlComment extends @ql_yaml_comment, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlComment" } /** Gets the location of this element. */ - override Location getLocation() { yaml_comment_def(this, _, result) } + override Location getLocation() { ql_yaml_comment_def(this, _, result) } /** Gets the child of this node. */ - YamlValue getChild() { yaml_comment_def(this, result, _) } + YamlValue getChild() { ql_yaml_comment_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { yaml_comment_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_yaml_comment_def(this, result, _) } } /** A class representing `yaml_entry` nodes. */ - class YamlEntry extends @yaml_entry, AstNode { + class YamlEntry extends @ql_yaml_entry, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlEntry" } /** Gets the location of this element. */ - override Location getLocation() { yaml_entry_def(this, _, result) } + override Location getLocation() { ql_yaml_entry_def(this, _, result) } /** Gets the child of this node. */ - AstNode getChild() { yaml_entry_def(this, result, _) } + AstNode getChild() { ql_yaml_entry_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { yaml_entry_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_yaml_entry_def(this, result, _) } } /** A class representing `yaml_key` nodes. */ - class YamlKey extends @yaml_key, AstNode { + class YamlKey extends @ql_yaml_key, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlKey" } /** Gets the location of this element. */ - override Location getLocation() { yaml_key_def(this, result) } + override Location getLocation() { ql_yaml_key_def(this, result) } /** Gets the `i`th child of this node. */ - AstNode getChild(int i) { yaml_key_child(this, i, result) } + AstNode getChild(int i) { ql_yaml_key_child(this, i, result) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { yaml_key_child(this, _, result) } + override AstNode getAFieldOrChild() { ql_yaml_key_child(this, _, result) } } /** A class representing `yaml_keyvaluepair` nodes. */ - class YamlKeyvaluepair extends @yaml_keyvaluepair, AstNode { + class YamlKeyvaluepair extends @ql_yaml_keyvaluepair, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlKeyvaluepair" } /** Gets the location of this element. */ - override Location getLocation() { yaml_keyvaluepair_def(this, _, _, result) } + override Location getLocation() { ql_yaml_keyvaluepair_def(this, _, _, result) } /** Gets the node corresponding to the field `key`. */ - YamlKey getKey() { yaml_keyvaluepair_def(this, result, _, _) } + YamlKey getKey() { ql_yaml_keyvaluepair_def(this, result, _, _) } /** Gets the node corresponding to the field `value`. */ - YamlValue getValue() { yaml_keyvaluepair_def(this, _, result, _) } + YamlValue getValue() { ql_yaml_keyvaluepair_def(this, _, result, _) } /** Gets a field or child node of this node. */ override AstNode getAFieldOrChild() { - yaml_keyvaluepair_def(this, result, _, _) or yaml_keyvaluepair_def(this, _, result, _) + ql_yaml_keyvaluepair_def(this, result, _, _) or ql_yaml_keyvaluepair_def(this, _, result, _) } } /** A class representing `yaml_listitem` nodes. */ - class YamlListitem extends @yaml_listitem, AstNode { + class YamlListitem extends @ql_yaml_listitem, AstNode { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlListitem" } /** Gets the location of this element. */ - override Location getLocation() { yaml_listitem_def(this, _, result) } + override Location getLocation() { ql_yaml_listitem_def(this, _, result) } /** Gets the child of this node. */ - YamlValue getChild() { yaml_listitem_def(this, result, _) } + YamlValue getChild() { ql_yaml_listitem_def(this, result, _) } /** Gets a field or child node of this node. */ - override AstNode getAFieldOrChild() { yaml_listitem_def(this, result, _) } + override AstNode getAFieldOrChild() { ql_yaml_listitem_def(this, result, _) } } /** A class representing `yaml_value` tokens. */ - class YamlValue extends @token_yaml_value, Token { + class YamlValue extends @ql_token_yaml_value, Token { /** Gets the name of the primary QL class for this element. */ override string getAPrimaryQlClass() { result = "YamlValue" } } diff --git a/ql/src/codeql_ql/ast/internal/Type.qll b/ql/src/codeql_ql/ast/internal/Type.qll index ee4c5dc8400..bfd84ea9208 100644 --- a/ql/src/codeql_ql/ast/internal/Type.qll +++ b/ql/src/codeql_ql/ast/internal/Type.qll @@ -27,7 +27,7 @@ private predicate isActualClass(Class c) { * A type, such as `int` or `Node`. */ class Type extends TType { - string toString() { result = getName() } + string toString() { result = this.getName() } string getName() { result = "???" } @@ -48,9 +48,9 @@ class Type extends TType { predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - if exists(getDeclaration()) + if exists(this.getDeclaration()) then - getDeclaration() + this.getDeclaration() .getLocation() .hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) else ( @@ -72,14 +72,14 @@ class Type extends TType { private predicate getClassPredicate1( string name, int arity, PredicateOrBuiltin p1, PredicateOrBuiltin p2 ) { - getClassPredicate0(name, arity, p1, p2.getDeclaringType()) and + this.getClassPredicate0(name, arity, p1, p2.getDeclaringType()) and p2 = classPredCandidate(this, name, arity) } cached PredicateOrBuiltin getClassPredicate(string name, int arity) { result = classPredCandidate(this, name, arity) and - not getClassPredicate1(name, arity, _, result) + not this.getClassPredicate1(name, arity, _, result) } } @@ -94,6 +94,8 @@ class ClassType extends Type, TClass { override Type getASuperType() { result = decl.getASuperType().getResolvedType() } + Type getAnInstanceofType() { result = decl.getAnInstanceofType().getResolvedType() } + override Type getAnInternalSuperType() { result.(ClassCharType).getClassType() = this or @@ -179,7 +181,7 @@ class ClassDomainType extends Type, TClassDomain { ClassType getClassType() { result = TClass(decl) } - override Type getAnInternalSuperType() { result = getClassType().getASuperType() } + override Type getAnInternalSuperType() { result = this.getClassType().getASuperType() } } class PrimitiveType extends Type, TPrimitive { @@ -192,7 +194,7 @@ class PrimitiveType extends Type, TPrimitive { override Type getASuperType() { name = "int" and result.(PrimitiveType).getName() = "float" } override Type getAnInternalSuperType() { - result = getASuperType() + result = this.getASuperType() or result = super.getAnInternalSuperType() } @@ -232,7 +234,7 @@ class NewTypeBranchType extends Type, TNewTypeBranch { } override Type getAnInternalSuperType() { - result = getASuperType() + result = this.getASuperType() or result = super.getAnInternalSuperType() } diff --git a/ql/src/codeql_ql/ast/internal/Variable.qll b/ql/src/codeql_ql/ast/internal/Variable.qll index 349bad6a7ca..634c4b1a3e8 100644 --- a/ql/src/codeql_ql/ast/internal/Variable.qll +++ b/ql/src/codeql_ql/ast/internal/Variable.qll @@ -60,9 +60,9 @@ pragma[nomagic] VariableScope scopeOf(AstNode n) { result = parent*(n.getParent()) } private string getName(Identifier i) { - exists(Generated::Variable v | + exists(QL::Variable v | i = TIdentifier(v) and - result = v.getChild().(Generated::VarName).getChild().getValue() + result = v.getChild().(QL::VarName).getChild().getValue() ) } diff --git a/ql/src/ql.dbscheme b/ql/src/ql.dbscheme index 36e57f03df4..dbdd64930a3 100644 --- a/ql/src/ql.dbscheme +++ b/ql/src/ql.dbscheme @@ -12,27 +12,14 @@ locations_default( int end_column: int ref ); -@sourceline = @file - -numlines( - int element_id: @sourceline ref, - int num_lines: int ref, - int num_code: int ref, - int num_comment: int ref -); - files( unique int id: @file, - string name: string ref, - string simple: string ref, - string ext: string ref, - int fromSource: int ref + string name: string ref ); folders( unique int id: @folder, - string name: string ref, - string simple: string ref + string name: string ref ); @container = @file | @folder @@ -46,1097 +33,6 @@ sourceLocationPrefix( string prefix: string ref ); -@add_expr_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@add_expr_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -add_expr_def( - unique int id: @add_expr, - int left: @add_expr_left_type ref, - int right: @add_expr_right_type ref, - int child: @token_addop ref, - int loc: @location ref -); - -@aggregate_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_aggregate_body | @expr_annotation | @full_aggregate_body | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_agg_id | @unary_expr | @variable - -#keyset[aggregate, index] -aggregate_child( - int aggregate: @aggregate ref, - int index: int ref, - unique int child: @aggregate_child_type ref -); - -aggregate_def( - unique int id: @aggregate, - int loc: @location ref -); - -@annotArg_child_type = @token_result | @token_simple_id | @token_this - -annot_arg_def( - unique int id: @annot_arg, - int child: @annotArg_child_type ref, - int loc: @location ref -); - -@annotation_args_type = @annot_arg | @reserved_word - -#keyset[annotation, index] -annotation_args( - int annotation: @annotation ref, - int index: int ref, - unique int args: @annotation_args_type ref -); - -annotation_def( - unique int id: @annotation, - int name: @token_annot_name ref, - int loc: @location ref -); - -arityless_predicate_expr_child( - unique int arityless_predicate_expr: @arityless_predicate_expr ref, - unique int child: @module_expr ref -); - -arityless_predicate_expr_def( - unique int id: @arityless_predicate_expr, - int name: @token_literal_id ref, - int loc: @location ref -); - -@asExpr_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @var_name | @variable - -#keyset[as_expr, index] -as_expr_child( - int as_expr: @as_expr ref, - int index: int ref, - unique int child: @asExpr_child_type ref -); - -as_expr_def( - unique int id: @as_expr, - int loc: @location ref -); - -#keyset[as_exprs, index] -as_exprs_child( - int as_exprs: @as_exprs ref, - int index: int ref, - unique int child: @as_expr ref -); - -as_exprs_def( - unique int id: @as_exprs, - int loc: @location ref -); - -@body_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -body_def( - unique int id: @body, - int child: @body_child_type ref, - int loc: @location ref -); - -@bool_child_type = @token_false | @token_true - -bool_def( - unique int id: @bool, - int child: @bool_child_type ref, - int loc: @location ref -); - -@call_body_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_underscore | @unary_expr | @variable - -#keyset[call_body, index] -call_body_child( - int call_body: @call_body ref, - int index: int ref, - unique int child: @call_body_child_type ref -); - -call_body_def( - unique int id: @call_body, - int loc: @location ref -); - -@call_or_unqual_agg_expr_child_type = @arityless_predicate_expr | @call_body | @token_closure | @unqual_agg_body - -#keyset[call_or_unqual_agg_expr, index] -call_or_unqual_agg_expr_child( - int call_or_unqual_agg_expr: @call_or_unqual_agg_expr ref, - int index: int ref, - unique int child: @call_or_unqual_agg_expr_child_type ref -); - -call_or_unqual_agg_expr_def( - unique int id: @call_or_unqual_agg_expr, - int loc: @location ref -); - -@charpred_body_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -charpred_def( - unique int id: @charpred, - int body: @charpred_body_type ref, - int child: @token_class_name ref, - int loc: @location ref -); - -@classMember_child_type = @annotation | @charpred | @field | @member_predicate | @token_qldoc - -#keyset[class_member, index] -class_member_child( - int class_member: @class_member ref, - int index: int ref, - unique int child: @classMember_child_type ref -); - -class_member_def( - unique int id: @class_member, - int loc: @location ref -); - -@classlessPredicate_returnType_type = @token_predicate | @type_expr - -@classlessPredicate_child_type = @body | @higher_order_term | @predicate_alias_body | @token_empty | @var_decl - -#keyset[classless_predicate, index] -classless_predicate_child( - int classless_predicate: @classless_predicate ref, - int index: int ref, - unique int child: @classlessPredicate_child_type ref -); - -classless_predicate_def( - unique int id: @classless_predicate, - int name: @token_predicate_name ref, - int return_type: @classlessPredicate_returnType_type ref, - int loc: @location ref -); - -@comp_term_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@comp_term_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -comp_term_def( - unique int id: @comp_term, - int left: @comp_term_left_type ref, - int right: @comp_term_right_type ref, - int child: @token_compop ref, - int loc: @location ref -); - -@conjunction_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@conjunction_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -conjunction_def( - unique int id: @conjunction, - int left: @conjunction_left_type ref, - int right: @conjunction_right_type ref, - int loc: @location ref -); - -@dataclass_extends_type = @reserved_word | @type_expr - -#keyset[dataclass, index] -dataclass_extends( - int dataclass: @dataclass ref, - int index: int ref, - unique int extends: @dataclass_extends_type ref -); - -@dataclass_instanceof_type = @reserved_word | @type_expr - -#keyset[dataclass, index] -dataclass_instanceof( - int dataclass: @dataclass ref, - int index: int ref, - unique int instanceof: @dataclass_instanceof_type ref -); - -@dataclass_child_type = @class_member | @type_alias_body | @type_union_body - -#keyset[dataclass, index] -dataclass_child( - int dataclass: @dataclass ref, - int index: int ref, - unique int child: @dataclass_child_type ref -); - -dataclass_def( - unique int id: @dataclass, - int name: @token_class_name ref, - int loc: @location ref -); - -datatype_def( - unique int id: @datatype, - int name: @token_class_name ref, - int child: @datatype_branches ref, - int loc: @location ref -); - -@datatypeBranch_child_type = @annotation | @body | @token_qldoc | @var_decl - -#keyset[datatype_branch, index] -datatype_branch_child( - int datatype_branch: @datatype_branch ref, - int index: int ref, - unique int child: @datatypeBranch_child_type ref -); - -datatype_branch_def( - unique int id: @datatype_branch, - int name: @token_class_name ref, - int loc: @location ref -); - -#keyset[datatype_branches, index] -datatype_branches_child( - int datatype_branches: @datatype_branches ref, - int index: int ref, - unique int child: @datatype_branch ref -); - -datatype_branches_def( - unique int id: @datatype_branches, - int loc: @location ref -); - -db_annotation_args_annotation( - unique int db_annotation: @db_annotation ref, - unique int args_annotation: @db_args_annotation ref -); - -db_annotation_simple_annotation( - unique int db_annotation: @db_annotation ref, - unique int simple_annotation: @token_annot_name ref -); - -db_annotation_def( - unique int id: @db_annotation, - int loc: @location ref -); - -#keyset[db_args_annotation, index] -db_args_annotation_child( - int db_args_annotation: @db_args_annotation ref, - int index: int ref, - unique int child: @token_simple_id ref -); - -db_args_annotation_def( - unique int id: @db_args_annotation, - int name: @token_annot_name ref, - int loc: @location ref -); - -db_branch_qldoc( - unique int db_branch: @db_branch ref, - unique int qldoc: @token_qldoc ref -); - -@db_branch_child_type = @token_dbtype | @token_integer - -#keyset[db_branch, index] -db_branch_child( - int db_branch: @db_branch ref, - int index: int ref, - unique int child: @db_branch_child_type ref -); - -db_branch_def( - unique int id: @db_branch, - int loc: @location ref -); - -@db_caseDecl_child_type = @db_branch | @token_db_case - -#keyset[db_case_decl, index] -db_case_decl_child( - int db_case_decl: @db_case_decl ref, - int index: int ref, - unique int child: @db_caseDecl_child_type ref -); - -db_case_decl_def( - unique int id: @db_case_decl, - int base: @token_dbtype ref, - int discriminator: @token_simple_id ref, - int loc: @location ref -); - -@db_colType_child_type = @token_db_boolean | @token_db_date | @token_db_float | @token_db_int | @token_db_string | @token_dbtype - -db_col_type_def( - unique int id: @db_col_type, - int child: @db_colType_child_type ref, - int loc: @location ref -); - -db_column_is_ref( - unique int db_column: @db_column ref, - unique int is_ref: @token_db_ref ref -); - -db_column_is_unique( - unique int db_column: @db_column ref, - unique int is_unique: @token_db_unique ref -); - -db_column_qldoc( - unique int db_column: @db_column ref, - unique int qldoc: @token_qldoc ref -); - -db_column_def( - unique int id: @db_column, - int col_name: @token_simple_id ref, - int col_type: @db_col_type ref, - int repr_type: @db_repr_type ref, - int loc: @location ref -); - -@db_entry_child_type = @db_case_decl | @db_table | @db_union_decl | @token_qldoc - -db_entry_def( - unique int id: @db_entry, - int child: @db_entry_child_type ref, - int loc: @location ref -); - -@db_reprType_child_type = @token_db_boolean | @token_db_date | @token_db_float | @token_db_int | @token_db_string | @token_db_varchar | @token_integer - -#keyset[db_repr_type, index] -db_repr_type_child( - int db_repr_type: @db_repr_type ref, - int index: int ref, - unique int child: @db_reprType_child_type ref -); - -db_repr_type_def( - unique int id: @db_repr_type, - int loc: @location ref -); - -@db_table_child_type = @db_annotation | @db_column - -#keyset[db_table, index] -db_table_child( - int db_table: @db_table ref, - int index: int ref, - unique int child: @db_table_child_type ref -); - -db_table_def( - unique int id: @db_table, - int table_name: @db_table_name ref, - int loc: @location ref -); - -db_table_name_def( - unique int id: @db_table_name, - int child: @token_simple_id ref, - int loc: @location ref -); - -#keyset[db_union_decl, index] -db_union_decl_child( - int db_union_decl: @db_union_decl ref, - int index: int ref, - unique int child: @token_dbtype ref -); - -db_union_decl_def( - unique int id: @db_union_decl, - int base: @token_dbtype ref, - int loc: @location ref -); - -@disjunction_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@disjunction_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -disjunction_def( - unique int id: @disjunction, - int left: @disjunction_left_type ref, - int right: @disjunction_right_type ref, - int loc: @location ref -); - -expr_aggregate_body_order_bys( - unique int expr_aggregate_body: @expr_aggregate_body ref, - unique int order_bys: @order_bys ref -); - -expr_aggregate_body_def( - unique int id: @expr_aggregate_body, - int as_exprs: @as_exprs ref, - int loc: @location ref -); - -@expr_annotation_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -expr_annotation_def( - unique int id: @expr_annotation, - int annot_arg: @token_annot_name ref, - int name: @token_annot_name ref, - int child: @expr_annotation_child_type ref, - int loc: @location ref -); - -field_def( - unique int id: @field, - int child: @var_decl ref, - int loc: @location ref -); - -full_aggregate_body_as_exprs( - unique int full_aggregate_body: @full_aggregate_body ref, - unique int as_exprs: @as_exprs ref -); - -@full_aggregate_body_guard_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -full_aggregate_body_guard( - unique int full_aggregate_body: @full_aggregate_body ref, - unique int guard: @full_aggregate_body_guard_type ref -); - -full_aggregate_body_order_bys( - unique int full_aggregate_body: @full_aggregate_body ref, - unique int order_bys: @order_bys ref -); - -#keyset[full_aggregate_body, index] -full_aggregate_body_child( - int full_aggregate_body: @full_aggregate_body ref, - int index: int ref, - unique int child: @var_decl ref -); - -full_aggregate_body_def( - unique int id: @full_aggregate_body, - int loc: @location ref -); - -@higherOrderTerm_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @predicate_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_underscore | @unary_expr | @variable - -#keyset[higher_order_term, index] -higher_order_term_child( - int higher_order_term: @higher_order_term ref, - int index: int ref, - unique int child: @higherOrderTerm_child_type ref -); - -higher_order_term_def( - unique int id: @higher_order_term, - int name: @token_literal_id ref, - int loc: @location ref -); - -@if_term_cond_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@if_term_first_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@if_term_second_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -if_term_def( - unique int id: @if_term, - int cond: @if_term_cond_type ref, - int first: @if_term_first_type ref, - int second: @if_term_second_type ref, - int loc: @location ref -); - -@implication_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@implication_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -implication_def( - unique int id: @implication, - int left: @implication_left_type ref, - int right: @implication_right_type ref, - int loc: @location ref -); - -@importDirective_child_type = @import_module_expr | @module_name - -#keyset[import_directive, index] -import_directive_child( - int import_directive: @import_directive ref, - int index: int ref, - unique int child: @importDirective_child_type ref -); - -import_directive_def( - unique int id: @import_directive, - int loc: @location ref -); - -#keyset[import_module_expr, index] -import_module_expr_name( - int import_module_expr: @import_module_expr ref, - int index: int ref, - unique int name: @token_simple_id ref -); - -import_module_expr_def( - unique int id: @import_module_expr, - int child: @qual_module_expr ref, - int loc: @location ref -); - -@in_expr_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@in_expr_right_type = @aggregate | @call_or_unqual_agg_expr | @expr_annotation | @literal | @par_expr | @qualified_expr | @range | @set_literal | @super_ref | @variable - -in_expr_def( - unique int id: @in_expr, - int left: @in_expr_left_type ref, - int right: @in_expr_right_type ref, - int loc: @location ref -); - -@instance_of_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @type_expr | @unary_expr | @variable - -#keyset[instance_of, index] -instance_of_child( - int instance_of: @instance_of ref, - int index: int ref, - unique int child: @instance_of_child_type ref -); - -instance_of_def( - unique int id: @instance_of, - int loc: @location ref -); - -@literal_child_type = @bool | @token_float | @token_integer | @token_string - -literal_def( - unique int id: @literal, - int child: @literal_child_type ref, - int loc: @location ref -); - -@memberPredicate_returnType_type = @token_predicate | @type_expr - -@memberPredicate_child_type = @body | @higher_order_term | @token_empty | @var_decl - -#keyset[member_predicate, index] -member_predicate_child( - int member_predicate: @member_predicate ref, - int index: int ref, - unique int child: @memberPredicate_child_type ref -); - -member_predicate_def( - unique int id: @member_predicate, - int name: @token_predicate_name ref, - int return_type: @memberPredicate_returnType_type ref, - int loc: @location ref -); - -@module_child_type = @module_alias_body | @module_member - -#keyset[module, index] -module_child( - int module: @module ref, - int index: int ref, - unique int child: @module_child_type ref -); - -module_def( - unique int id: @module, - int name: @module_name ref, - int loc: @location ref -); - -module_alias_body_def( - unique int id: @module_alias_body, - int child: @module_expr ref, - int loc: @location ref -); - -module_expr_name( - unique int module_expr: @module_expr ref, - unique int name: @token_simple_id ref -); - -@moduleExpr_child_type = @module_expr | @token_simple_id - -module_expr_def( - unique int id: @module_expr, - int child: @moduleExpr_child_type ref, - int loc: @location ref -); - -@moduleMember_child_type = @annotation | @classless_predicate | @dataclass | @datatype | @import_directive | @module | @select | @token_qldoc - -#keyset[module_member, index] -module_member_child( - int module_member: @module_member ref, - int index: int ref, - unique int child: @moduleMember_child_type ref -); - -module_member_def( - unique int id: @module_member, - int loc: @location ref -); - -module_name_def( - unique int id: @module_name, - int child: @token_simple_id ref, - int loc: @location ref -); - -@mul_expr_left_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@mul_expr_right_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -mul_expr_def( - unique int id: @mul_expr, - int left: @mul_expr_left_type ref, - int right: @mul_expr_right_type ref, - int child: @token_mulop ref, - int loc: @location ref -); - -@negation_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -negation_def( - unique int id: @negation, - int child: @negation_child_type ref, - int loc: @location ref -); - -@orderBy_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_direction | @unary_expr | @variable - -#keyset[order_by, index] -order_by_child( - int order_by: @order_by ref, - int index: int ref, - unique int child: @orderBy_child_type ref -); - -order_by_def( - unique int id: @order_by, - int loc: @location ref -); - -#keyset[order_bys, index] -order_bys_child( - int order_bys: @order_bys ref, - int index: int ref, - unique int child: @order_by ref -); - -order_bys_def( - unique int id: @order_bys, - int loc: @location ref -); - -@par_expr_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -par_expr_def( - unique int id: @par_expr, - int child: @par_expr_child_type ref, - int loc: @location ref -); - -predicate_alias_body_def( - unique int id: @predicate_alias_body, - int child: @predicate_expr ref, - int loc: @location ref -); - -@predicateExpr_child_type = @arityless_predicate_expr | @token_integer - -#keyset[predicate_expr, index] -predicate_expr_child( - int predicate_expr: @predicate_expr ref, - int index: int ref, - unique int child: @predicateExpr_child_type ref -); - -predicate_expr_def( - unique int id: @predicate_expr, - int loc: @location ref -); - -@prefix_cast_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @type_expr | @unary_expr | @variable - -#keyset[prefix_cast, index] -prefix_cast_child( - int prefix_cast: @prefix_cast ref, - int index: int ref, - unique int child: @prefix_cast_child_type ref -); - -prefix_cast_def( - unique int id: @prefix_cast, - int loc: @location ref -); - -@ql_child_type = @db_entry | @module_member | @yaml_entry - -#keyset[ql, index] -ql_child( - int ql: @ql ref, - int index: int ref, - unique int child: @ql_child_type ref -); - -ql_def( - unique int id: @ql, - int loc: @location ref -); - -#keyset[qual_module_expr, index] -qual_module_expr_name( - int qual_module_expr: @qual_module_expr ref, - int index: int ref, - unique int name: @token_simple_id ref -); - -qual_module_expr_def( - unique int id: @qual_module_expr, - int loc: @location ref -); - -qualified_rhs_name( - unique int qualified_rhs: @qualified_rhs ref, - unique int name: @token_predicate_name ref -); - -@qualifiedRhs_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_closure | @token_underscore | @type_expr | @unary_expr | @variable - -#keyset[qualified_rhs, index] -qualified_rhs_child( - int qualified_rhs: @qualified_rhs ref, - int index: int ref, - unique int child: @qualifiedRhs_child_type ref -); - -qualified_rhs_def( - unique int id: @qualified_rhs, - int loc: @location ref -); - -@qualified_expr_child_type = @aggregate | @call_or_unqual_agg_expr | @expr_annotation | @literal | @par_expr | @qualified_expr | @qualified_rhs | @range | @set_literal | @super_ref | @variable - -#keyset[qualified_expr, index] -qualified_expr_child( - int qualified_expr: @qualified_expr ref, - int index: int ref, - unique int child: @qualified_expr_child_type ref -); - -qualified_expr_def( - unique int id: @qualified_expr, - int loc: @location ref -); - -@quantified_expr_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -quantified_expr( - unique int quantified: @quantified ref, - unique int expr: @quantified_expr_type ref -); - -@quantified_formula_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -quantified_formula( - unique int quantified: @quantified ref, - unique int formula: @quantified_formula_type ref -); - -@quantified_range_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -quantified_range( - unique int quantified: @quantified ref, - unique int range: @quantified_range_type ref -); - -@quantified_child_type = @token_quantifier | @var_decl - -#keyset[quantified, index] -quantified_child( - int quantified: @quantified ref, - int index: int ref, - unique int child: @quantified_child_type ref -); - -quantified_def( - unique int id: @quantified, - int loc: @location ref -); - -@range_lower_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -@range_upper_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -range_def( - unique int id: @range, - int lower: @range_lower_type ref, - int upper: @range_upper_type ref, - int loc: @location ref -); - -@select_child_type = @add_expr | @aggregate | @as_exprs | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @order_bys | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @var_decl | @variable - -#keyset[select, index] -select_child( - int select: @select ref, - int index: int ref, - unique int child: @select_child_type ref -); - -select_def( - unique int id: @select, - int loc: @location ref -); - -@set_literal_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -#keyset[set_literal, index] -set_literal_child( - int set_literal: @set_literal ref, - int index: int ref, - unique int child: @set_literal_child_type ref -); - -set_literal_def( - unique int id: @set_literal, - int loc: @location ref -); - -special_call_def( - unique int id: @special_call, - int child: @token_special_id ref, - int loc: @location ref -); - -@super_ref_child_type = @token_super | @type_expr - -#keyset[super_ref, index] -super_ref_child( - int super_ref: @super_ref ref, - int index: int ref, - unique int child: @super_ref_child_type ref -); - -super_ref_def( - unique int id: @super_ref, - int loc: @location ref -); - -type_alias_body_def( - unique int id: @type_alias_body, - int child: @type_expr ref, - int loc: @location ref -); - -type_expr_name( - unique int type_expr: @type_expr ref, - unique int name: @token_class_name ref -); - -@typeExpr_child_type = @module_expr | @token_dbtype | @token_primitive_type - -type_expr_child( - unique int type_expr: @type_expr ref, - unique int child: @typeExpr_child_type ref -); - -type_expr_def( - unique int id: @type_expr, - int loc: @location ref -); - -#keyset[type_union_body, index] -type_union_body_child( - int type_union_body: @type_union_body ref, - int index: int ref, - unique int child: @type_expr ref -); - -type_union_body_def( - unique int id: @type_union_body, - int loc: @location ref -); - -@unary_expr_child_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @token_unop | @unary_expr | @variable - -#keyset[unary_expr, index] -unary_expr_child( - int unary_expr: @unary_expr ref, - int index: int ref, - unique int child: @unary_expr_child_type ref -); - -unary_expr_def( - unique int id: @unary_expr, - int loc: @location ref -); - -@unqual_agg_body_asExprs_type = @as_exprs | @reserved_word - -#keyset[unqual_agg_body, index] -unqual_agg_body_as_exprs( - int unqual_agg_body: @unqual_agg_body ref, - int index: int ref, - unique int as_exprs: @unqual_agg_body_asExprs_type ref -); - -@unqual_agg_body_guard_type = @add_expr | @aggregate | @call_or_unqual_agg_expr | @comp_term | @conjunction | @disjunction | @expr_annotation | @if_term | @implication | @in_expr | @instance_of | @literal | @mul_expr | @negation | @par_expr | @prefix_cast | @qualified_expr | @quantified | @range | @set_literal | @special_call | @super_ref | @unary_expr | @variable - -unqual_agg_body_guard( - unique int unqual_agg_body: @unqual_agg_body ref, - unique int guard: @unqual_agg_body_guard_type ref -); - -#keyset[unqual_agg_body, index] -unqual_agg_body_child( - int unqual_agg_body: @unqual_agg_body ref, - int index: int ref, - unique int child: @var_decl ref -); - -unqual_agg_body_def( - unique int id: @unqual_agg_body, - int loc: @location ref -); - -@varDecl_child_type = @type_expr | @var_name - -#keyset[var_decl, index] -var_decl_child( - int var_decl: @var_decl ref, - int index: int ref, - unique int child: @varDecl_child_type ref -); - -var_decl_def( - unique int id: @var_decl, - int loc: @location ref -); - -var_name_def( - unique int id: @var_name, - int child: @token_simple_id ref, - int loc: @location ref -); - -@variable_child_type = @token_result | @token_this | @var_name - -variable_def( - unique int id: @variable, - int child: @variable_child_type ref, - int loc: @location ref -); - -yaml_comment_def( - unique int id: @yaml_comment, - int child: @token_yaml_value ref, - int loc: @location ref -); - -@yaml_entry_child_type = @yaml_comment | @yaml_keyvaluepair | @yaml_listitem - -yaml_entry_def( - unique int id: @yaml_entry, - int child: @yaml_entry_child_type ref, - int loc: @location ref -); - -@yaml_key_child_type = @token_simple_id | @yaml_key - -#keyset[yaml_key, index] -yaml_key_child( - int yaml_key: @yaml_key ref, - int index: int ref, - unique int child: @yaml_key_child_type ref -); - -yaml_key_def( - unique int id: @yaml_key, - int loc: @location ref -); - -yaml_keyvaluepair_def( - unique int id: @yaml_keyvaluepair, - int key__: @yaml_key ref, - int value: @token_yaml_value ref, - int loc: @location ref -); - -yaml_listitem_def( - unique int id: @yaml_listitem, - int child: @token_yaml_value ref, - int loc: @location ref -); - -tokeninfo( - unique int id: @token, - int kind: int ref, - int file: @file ref, - int idx: int ref, - string value: string ref, - int loc: @location ref -); - -case @token.kind of - 0 = @reserved_word -| 1 = @token_addop -| 2 = @token_agg_id -| 3 = @token_annot_name -| 4 = @token_block_comment -| 5 = @token_class_name -| 6 = @token_closure -| 7 = @token_compop -| 8 = @token_db_boolean -| 9 = @token_db_case -| 10 = @token_db_date -| 11 = @token_db_float -| 12 = @token_db_int -| 13 = @token_db_ref -| 14 = @token_db_string -| 15 = @token_db_unique -| 16 = @token_db_varchar -| 17 = @token_dbtype -| 18 = @token_direction -| 19 = @token_empty -| 20 = @token_false -| 21 = @token_float -| 22 = @token_integer -| 23 = @token_line_comment -| 24 = @token_literal_id -| 25 = @token_mulop -| 26 = @token_predicate -| 27 = @token_predicate_name -| 28 = @token_primitive_type -| 29 = @token_qldoc -| 30 = @token_quantifier -| 31 = @token_result -| 32 = @token_simple_id -| 33 = @token_special_id -| 34 = @token_string -| 35 = @token_super -| 36 = @token_this -| 37 = @token_true -| 38 = @token_underscore -| 39 = @token_unop -| 40 = @token_yaml_value -; - - diagnostics( unique int id: @diagnostic, int severity: int ref, @@ -1154,14 +50,1103 @@ case @diagnostic.severity of ; -@ast_node = @add_expr | @aggregate | @annot_arg | @annotation | @arityless_predicate_expr | @as_expr | @as_exprs | @body | @bool | @call_body | @call_or_unqual_agg_expr | @charpred | @class_member | @classless_predicate | @comp_term | @conjunction | @dataclass | @datatype | @datatype_branch | @datatype_branches | @db_annotation | @db_args_annotation | @db_branch | @db_case_decl | @db_col_type | @db_column | @db_entry | @db_repr_type | @db_table | @db_table_name | @db_union_decl | @disjunction | @expr_aggregate_body | @expr_annotation | @field | @full_aggregate_body | @higher_order_term | @if_term | @implication | @import_directive | @import_module_expr | @in_expr | @instance_of | @literal | @member_predicate | @module | @module_alias_body | @module_expr | @module_member | @module_name | @mul_expr | @negation | @order_by | @order_bys | @par_expr | @predicate_alias_body | @predicate_expr | @prefix_cast | @ql | @qual_module_expr | @qualified_expr | @qualified_rhs | @quantified | @range | @select | @set_literal | @special_call | @super_ref | @token | @type_alias_body | @type_expr | @type_union_body | @unary_expr | @unqual_agg_body | @var_decl | @var_name | @variable | @yaml_comment | @yaml_entry | @yaml_key | @yaml_keyvaluepair | @yaml_listitem +@ql_add_expr_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable -@ast_node_parent = @ast_node | @file +@ql_add_expr_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_add_expr_def( + unique int id: @ql_add_expr, + int left: @ql_add_expr_left_type ref, + int right: @ql_add_expr_right_type ref, + int child: @ql_token_addop ref, + int loc: @location ref +); + +@ql_aggregate_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_aggregate_body | @ql_expr_annotation | @ql_full_aggregate_body | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_agg_id | @ql_unary_expr | @ql_variable + +#keyset[ql_aggregate, index] +ql_aggregate_child( + int ql_aggregate: @ql_aggregate ref, + int index: int ref, + unique int child: @ql_aggregate_child_type ref +); + +ql_aggregate_def( + unique int id: @ql_aggregate, + int loc: @location ref +); + +@ql_annotArg_child_type = @ql_token_result | @ql_token_simple_id | @ql_token_this + +ql_annot_arg_def( + unique int id: @ql_annot_arg, + int child: @ql_annotArg_child_type ref, + int loc: @location ref +); + +@ql_annotation_args_type = @ql_annot_arg | @ql_reserved_word + +#keyset[ql_annotation, index] +ql_annotation_args( + int ql_annotation: @ql_annotation ref, + int index: int ref, + unique int args: @ql_annotation_args_type ref +); + +ql_annotation_def( + unique int id: @ql_annotation, + int name: @ql_token_annot_name ref, + int loc: @location ref +); + +ql_arityless_predicate_expr_child( + unique int ql_arityless_predicate_expr: @ql_arityless_predicate_expr ref, + unique int child: @ql_module_expr ref +); + +ql_arityless_predicate_expr_def( + unique int id: @ql_arityless_predicate_expr, + int name: @ql_token_literal_id ref, + int loc: @location ref +); + +@ql_asExpr_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_var_name | @ql_variable + +#keyset[ql_as_expr, index] +ql_as_expr_child( + int ql_as_expr: @ql_as_expr ref, + int index: int ref, + unique int child: @ql_asExpr_child_type ref +); + +ql_as_expr_def( + unique int id: @ql_as_expr, + int loc: @location ref +); + +#keyset[ql_as_exprs, index] +ql_as_exprs_child( + int ql_as_exprs: @ql_as_exprs ref, + int index: int ref, + unique int child: @ql_as_expr ref +); + +ql_as_exprs_def( + unique int id: @ql_as_exprs, + int loc: @location ref +); + +@ql_body_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_body_def( + unique int id: @ql_body, + int child: @ql_body_child_type ref, + int loc: @location ref +); + +@ql_bool_child_type = @ql_token_false | @ql_token_true + +ql_bool_def( + unique int id: @ql_bool, + int child: @ql_bool_child_type ref, + int loc: @location ref +); + +@ql_call_body_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_underscore | @ql_unary_expr | @ql_variable + +#keyset[ql_call_body, index] +ql_call_body_child( + int ql_call_body: @ql_call_body ref, + int index: int ref, + unique int child: @ql_call_body_child_type ref +); + +ql_call_body_def( + unique int id: @ql_call_body, + int loc: @location ref +); + +@ql_call_or_unqual_agg_expr_child_type = @ql_arityless_predicate_expr | @ql_call_body | @ql_token_closure | @ql_unqual_agg_body + +#keyset[ql_call_or_unqual_agg_expr, index] +ql_call_or_unqual_agg_expr_child( + int ql_call_or_unqual_agg_expr: @ql_call_or_unqual_agg_expr ref, + int index: int ref, + unique int child: @ql_call_or_unqual_agg_expr_child_type ref +); + +ql_call_or_unqual_agg_expr_def( + unique int id: @ql_call_or_unqual_agg_expr, + int loc: @location ref +); + +@ql_charpred_body_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_charpred_def( + unique int id: @ql_charpred, + int body: @ql_charpred_body_type ref, + int child: @ql_token_class_name ref, + int loc: @location ref +); + +@ql_classMember_child_type = @ql_annotation | @ql_charpred | @ql_field | @ql_member_predicate | @ql_token_qldoc + +#keyset[ql_class_member, index] +ql_class_member_child( + int ql_class_member: @ql_class_member ref, + int index: int ref, + unique int child: @ql_classMember_child_type ref +); + +ql_class_member_def( + unique int id: @ql_class_member, + int loc: @location ref +); + +@ql_classlessPredicate_returnType_type = @ql_token_predicate | @ql_type_expr + +@ql_classlessPredicate_child_type = @ql_body | @ql_higher_order_term | @ql_predicate_alias_body | @ql_token_empty | @ql_var_decl + +#keyset[ql_classless_predicate, index] +ql_classless_predicate_child( + int ql_classless_predicate: @ql_classless_predicate ref, + int index: int ref, + unique int child: @ql_classlessPredicate_child_type ref +); + +ql_classless_predicate_def( + unique int id: @ql_classless_predicate, + int name: @ql_token_predicate_name ref, + int return_type: @ql_classlessPredicate_returnType_type ref, + int loc: @location ref +); + +@ql_comp_term_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_comp_term_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_comp_term_def( + unique int id: @ql_comp_term, + int left: @ql_comp_term_left_type ref, + int right: @ql_comp_term_right_type ref, + int child: @ql_token_compop ref, + int loc: @location ref +); + +@ql_conjunction_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_conjunction_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_conjunction_def( + unique int id: @ql_conjunction, + int left: @ql_conjunction_left_type ref, + int right: @ql_conjunction_right_type ref, + int loc: @location ref +); + +@ql_dataclass_extends_type = @ql_reserved_word | @ql_type_expr + +#keyset[ql_dataclass, index] +ql_dataclass_extends( + int ql_dataclass: @ql_dataclass ref, + int index: int ref, + unique int extends: @ql_dataclass_extends_type ref +); + +@ql_dataclass_instanceof_type = @ql_reserved_word | @ql_type_expr + +#keyset[ql_dataclass, index] +ql_dataclass_instanceof( + int ql_dataclass: @ql_dataclass ref, + int index: int ref, + unique int instanceof: @ql_dataclass_instanceof_type ref +); + +@ql_dataclass_child_type = @ql_class_member | @ql_type_alias_body | @ql_type_union_body + +#keyset[ql_dataclass, index] +ql_dataclass_child( + int ql_dataclass: @ql_dataclass ref, + int index: int ref, + unique int child: @ql_dataclass_child_type ref +); + +ql_dataclass_def( + unique int id: @ql_dataclass, + int name: @ql_token_class_name ref, + int loc: @location ref +); + +ql_datatype_def( + unique int id: @ql_datatype, + int name: @ql_token_class_name ref, + int child: @ql_datatype_branches ref, + int loc: @location ref +); + +@ql_datatypeBranch_child_type = @ql_annotation | @ql_body | @ql_token_qldoc | @ql_var_decl + +#keyset[ql_datatype_branch, index] +ql_datatype_branch_child( + int ql_datatype_branch: @ql_datatype_branch ref, + int index: int ref, + unique int child: @ql_datatypeBranch_child_type ref +); + +ql_datatype_branch_def( + unique int id: @ql_datatype_branch, + int name: @ql_token_class_name ref, + int loc: @location ref +); + +#keyset[ql_datatype_branches, index] +ql_datatype_branches_child( + int ql_datatype_branches: @ql_datatype_branches ref, + int index: int ref, + unique int child: @ql_datatype_branch ref +); + +ql_datatype_branches_def( + unique int id: @ql_datatype_branches, + int loc: @location ref +); + +ql_db_annotation_args_annotation( + unique int ql_db_annotation: @ql_db_annotation ref, + unique int args_annotation: @ql_db_args_annotation ref +); + +ql_db_annotation_simple_annotation( + unique int ql_db_annotation: @ql_db_annotation ref, + unique int simple_annotation: @ql_token_annot_name ref +); + +ql_db_annotation_def( + unique int id: @ql_db_annotation, + int loc: @location ref +); + +#keyset[ql_db_args_annotation, index] +ql_db_args_annotation_child( + int ql_db_args_annotation: @ql_db_args_annotation ref, + int index: int ref, + unique int child: @ql_token_simple_id ref +); + +ql_db_args_annotation_def( + unique int id: @ql_db_args_annotation, + int name: @ql_token_annot_name ref, + int loc: @location ref +); + +ql_db_branch_qldoc( + unique int ql_db_branch: @ql_db_branch ref, + unique int qldoc: @ql_token_qldoc ref +); + +@ql_db_branch_child_type = @ql_token_dbtype | @ql_token_integer + +#keyset[ql_db_branch, index] +ql_db_branch_child( + int ql_db_branch: @ql_db_branch ref, + int index: int ref, + unique int child: @ql_db_branch_child_type ref +); + +ql_db_branch_def( + unique int id: @ql_db_branch, + int loc: @location ref +); + +@ql_db_caseDecl_child_type = @ql_db_branch | @ql_token_db_case + +#keyset[ql_db_case_decl, index] +ql_db_case_decl_child( + int ql_db_case_decl: @ql_db_case_decl ref, + int index: int ref, + unique int child: @ql_db_caseDecl_child_type ref +); + +ql_db_case_decl_def( + unique int id: @ql_db_case_decl, + int base: @ql_token_dbtype ref, + int discriminator: @ql_token_simple_id ref, + int loc: @location ref +); + +@ql_db_colType_child_type = @ql_token_db_boolean | @ql_token_db_date | @ql_token_db_float | @ql_token_db_int | @ql_token_db_string | @ql_token_dbtype + +ql_db_col_type_def( + unique int id: @ql_db_col_type, + int child: @ql_db_colType_child_type ref, + int loc: @location ref +); + +ql_db_column_is_ref( + unique int ql_db_column: @ql_db_column ref, + unique int is_ref: @ql_token_db_ref ref +); + +ql_db_column_is_unique( + unique int ql_db_column: @ql_db_column ref, + unique int is_unique: @ql_token_db_unique ref +); + +ql_db_column_qldoc( + unique int ql_db_column: @ql_db_column ref, + unique int qldoc: @ql_token_qldoc ref +); + +ql_db_column_def( + unique int id: @ql_db_column, + int col_name: @ql_token_simple_id ref, + int col_type: @ql_db_col_type ref, + int repr_type: @ql_db_repr_type ref, + int loc: @location ref +); + +@ql_db_entry_child_type = @ql_db_case_decl | @ql_db_table | @ql_db_union_decl | @ql_token_qldoc + +ql_db_entry_def( + unique int id: @ql_db_entry, + int child: @ql_db_entry_child_type ref, + int loc: @location ref +); + +@ql_db_reprType_child_type = @ql_token_db_boolean | @ql_token_db_date | @ql_token_db_float | @ql_token_db_int | @ql_token_db_string | @ql_token_db_varchar | @ql_token_integer + +#keyset[ql_db_repr_type, index] +ql_db_repr_type_child( + int ql_db_repr_type: @ql_db_repr_type ref, + int index: int ref, + unique int child: @ql_db_reprType_child_type ref +); + +ql_db_repr_type_def( + unique int id: @ql_db_repr_type, + int loc: @location ref +); + +@ql_db_table_child_type = @ql_db_annotation | @ql_db_column + +#keyset[ql_db_table, index] +ql_db_table_child( + int ql_db_table: @ql_db_table ref, + int index: int ref, + unique int child: @ql_db_table_child_type ref +); + +ql_db_table_def( + unique int id: @ql_db_table, + int table_name: @ql_db_table_name ref, + int loc: @location ref +); + +ql_db_table_name_def( + unique int id: @ql_db_table_name, + int child: @ql_token_simple_id ref, + int loc: @location ref +); + +#keyset[ql_db_union_decl, index] +ql_db_union_decl_child( + int ql_db_union_decl: @ql_db_union_decl ref, + int index: int ref, + unique int child: @ql_token_dbtype ref +); + +ql_db_union_decl_def( + unique int id: @ql_db_union_decl, + int base: @ql_token_dbtype ref, + int loc: @location ref +); + +@ql_disjunction_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_disjunction_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_disjunction_def( + unique int id: @ql_disjunction, + int left: @ql_disjunction_left_type ref, + int right: @ql_disjunction_right_type ref, + int loc: @location ref +); + +ql_expr_aggregate_body_order_bys( + unique int ql_expr_aggregate_body: @ql_expr_aggregate_body ref, + unique int order_bys: @ql_order_bys ref +); + +ql_expr_aggregate_body_def( + unique int id: @ql_expr_aggregate_body, + int as_exprs: @ql_as_exprs ref, + int loc: @location ref +); + +@ql_expr_annotation_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_expr_annotation_def( + unique int id: @ql_expr_annotation, + int annot_arg: @ql_token_annot_name ref, + int name: @ql_token_annot_name ref, + int child: @ql_expr_annotation_child_type ref, + int loc: @location ref +); + +ql_field_def( + unique int id: @ql_field, + int child: @ql_var_decl ref, + int loc: @location ref +); + +ql_full_aggregate_body_as_exprs( + unique int ql_full_aggregate_body: @ql_full_aggregate_body ref, + unique int as_exprs: @ql_as_exprs ref +); + +@ql_full_aggregate_body_guard_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_full_aggregate_body_guard( + unique int ql_full_aggregate_body: @ql_full_aggregate_body ref, + unique int guard: @ql_full_aggregate_body_guard_type ref +); + +ql_full_aggregate_body_order_bys( + unique int ql_full_aggregate_body: @ql_full_aggregate_body ref, + unique int order_bys: @ql_order_bys ref +); + +#keyset[ql_full_aggregate_body, index] +ql_full_aggregate_body_child( + int ql_full_aggregate_body: @ql_full_aggregate_body ref, + int index: int ref, + unique int child: @ql_var_decl ref +); + +ql_full_aggregate_body_def( + unique int id: @ql_full_aggregate_body, + int loc: @location ref +); + +@ql_higherOrderTerm_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_predicate_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_underscore | @ql_unary_expr | @ql_variable + +#keyset[ql_higher_order_term, index] +ql_higher_order_term_child( + int ql_higher_order_term: @ql_higher_order_term ref, + int index: int ref, + unique int child: @ql_higherOrderTerm_child_type ref +); + +ql_higher_order_term_def( + unique int id: @ql_higher_order_term, + int name: @ql_token_literal_id ref, + int loc: @location ref +); + +@ql_if_term_cond_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_if_term_first_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_if_term_second_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_if_term_def( + unique int id: @ql_if_term, + int cond: @ql_if_term_cond_type ref, + int first: @ql_if_term_first_type ref, + int second: @ql_if_term_second_type ref, + int loc: @location ref +); + +@ql_implication_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_implication_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_implication_def( + unique int id: @ql_implication, + int left: @ql_implication_left_type ref, + int right: @ql_implication_right_type ref, + int loc: @location ref +); + +@ql_importDirective_child_type = @ql_import_module_expr | @ql_module_name + +#keyset[ql_import_directive, index] +ql_import_directive_child( + int ql_import_directive: @ql_import_directive ref, + int index: int ref, + unique int child: @ql_importDirective_child_type ref +); + +ql_import_directive_def( + unique int id: @ql_import_directive, + int loc: @location ref +); + +#keyset[ql_import_module_expr, index] +ql_import_module_expr_name( + int ql_import_module_expr: @ql_import_module_expr ref, + int index: int ref, + unique int name: @ql_token_simple_id ref +); + +ql_import_module_expr_def( + unique int id: @ql_import_module_expr, + int child: @ql_qual_module_expr ref, + int loc: @location ref +); + +@ql_in_expr_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_in_expr_right_type = @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_expr_annotation | @ql_literal | @ql_par_expr | @ql_qualified_expr | @ql_range | @ql_set_literal | @ql_super_ref | @ql_variable + +ql_in_expr_def( + unique int id: @ql_in_expr, + int left: @ql_in_expr_left_type ref, + int right: @ql_in_expr_right_type ref, + int loc: @location ref +); + +@ql_instance_of_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_type_expr | @ql_unary_expr | @ql_variable + +#keyset[ql_instance_of, index] +ql_instance_of_child( + int ql_instance_of: @ql_instance_of ref, + int index: int ref, + unique int child: @ql_instance_of_child_type ref +); + +ql_instance_of_def( + unique int id: @ql_instance_of, + int loc: @location ref +); + +@ql_literal_child_type = @ql_bool | @ql_token_float | @ql_token_integer | @ql_token_string + +ql_literal_def( + unique int id: @ql_literal, + int child: @ql_literal_child_type ref, + int loc: @location ref +); + +@ql_memberPredicate_returnType_type = @ql_token_predicate | @ql_type_expr + +@ql_memberPredicate_child_type = @ql_body | @ql_higher_order_term | @ql_token_empty | @ql_var_decl + +#keyset[ql_member_predicate, index] +ql_member_predicate_child( + int ql_member_predicate: @ql_member_predicate ref, + int index: int ref, + unique int child: @ql_memberPredicate_child_type ref +); + +ql_member_predicate_def( + unique int id: @ql_member_predicate, + int name: @ql_token_predicate_name ref, + int return_type: @ql_memberPredicate_returnType_type ref, + int loc: @location ref +); + +@ql_module_child_type = @ql_module_alias_body | @ql_module_member + +#keyset[ql_module, index] +ql_module_child( + int ql_module: @ql_module ref, + int index: int ref, + unique int child: @ql_module_child_type ref +); + +ql_module_def( + unique int id: @ql_module, + int name: @ql_module_name ref, + int loc: @location ref +); + +ql_module_alias_body_def( + unique int id: @ql_module_alias_body, + int child: @ql_module_expr ref, + int loc: @location ref +); + +ql_module_expr_name( + unique int ql_module_expr: @ql_module_expr ref, + unique int name: @ql_token_simple_id ref +); + +@ql_moduleExpr_child_type = @ql_module_expr | @ql_token_simple_id + +ql_module_expr_def( + unique int id: @ql_module_expr, + int child: @ql_moduleExpr_child_type ref, + int loc: @location ref +); + +@ql_moduleMember_child_type = @ql_annotation | @ql_classless_predicate | @ql_dataclass | @ql_datatype | @ql_import_directive | @ql_module | @ql_select | @ql_token_qldoc + +#keyset[ql_module_member, index] +ql_module_member_child( + int ql_module_member: @ql_module_member ref, + int index: int ref, + unique int child: @ql_moduleMember_child_type ref +); + +ql_module_member_def( + unique int id: @ql_module_member, + int loc: @location ref +); + +ql_module_name_def( + unique int id: @ql_module_name, + int child: @ql_token_simple_id ref, + int loc: @location ref +); + +@ql_mul_expr_left_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_mul_expr_right_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_mul_expr_def( + unique int id: @ql_mul_expr, + int left: @ql_mul_expr_left_type ref, + int right: @ql_mul_expr_right_type ref, + int child: @ql_token_mulop ref, + int loc: @location ref +); + +@ql_negation_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_negation_def( + unique int id: @ql_negation, + int child: @ql_negation_child_type ref, + int loc: @location ref +); + +@ql_orderBy_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_direction | @ql_unary_expr | @ql_variable + +#keyset[ql_order_by, index] +ql_order_by_child( + int ql_order_by: @ql_order_by ref, + int index: int ref, + unique int child: @ql_orderBy_child_type ref +); + +ql_order_by_def( + unique int id: @ql_order_by, + int loc: @location ref +); + +#keyset[ql_order_bys, index] +ql_order_bys_child( + int ql_order_bys: @ql_order_bys ref, + int index: int ref, + unique int child: @ql_order_by ref +); + +ql_order_bys_def( + unique int id: @ql_order_bys, + int loc: @location ref +); + +@ql_par_expr_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_par_expr_def( + unique int id: @ql_par_expr, + int child: @ql_par_expr_child_type ref, + int loc: @location ref +); + +ql_predicate_alias_body_def( + unique int id: @ql_predicate_alias_body, + int child: @ql_predicate_expr ref, + int loc: @location ref +); + +@ql_predicateExpr_child_type = @ql_arityless_predicate_expr | @ql_token_integer + +#keyset[ql_predicate_expr, index] +ql_predicate_expr_child( + int ql_predicate_expr: @ql_predicate_expr ref, + int index: int ref, + unique int child: @ql_predicateExpr_child_type ref +); + +ql_predicate_expr_def( + unique int id: @ql_predicate_expr, + int loc: @location ref +); + +@ql_prefix_cast_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_type_expr | @ql_unary_expr | @ql_variable + +#keyset[ql_prefix_cast, index] +ql_prefix_cast_child( + int ql_prefix_cast: @ql_prefix_cast ref, + int index: int ref, + unique int child: @ql_prefix_cast_child_type ref +); + +ql_prefix_cast_def( + unique int id: @ql_prefix_cast, + int loc: @location ref +); + +@ql_ql_child_type = @ql_db_entry | @ql_module_member | @ql_yaml_entry + +#keyset[ql_ql, index] +ql_ql_child( + int ql_ql: @ql_ql ref, + int index: int ref, + unique int child: @ql_ql_child_type ref +); + +ql_ql_def( + unique int id: @ql_ql, + int loc: @location ref +); + +#keyset[ql_qual_module_expr, index] +ql_qual_module_expr_name( + int ql_qual_module_expr: @ql_qual_module_expr ref, + int index: int ref, + unique int name: @ql_token_simple_id ref +); + +ql_qual_module_expr_def( + unique int id: @ql_qual_module_expr, + int loc: @location ref +); + +ql_qualified_rhs_name( + unique int ql_qualified_rhs: @ql_qualified_rhs ref, + unique int name: @ql_token_predicate_name ref +); + +@ql_qualifiedRhs_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_closure | @ql_token_underscore | @ql_type_expr | @ql_unary_expr | @ql_variable + +#keyset[ql_qualified_rhs, index] +ql_qualified_rhs_child( + int ql_qualified_rhs: @ql_qualified_rhs ref, + int index: int ref, + unique int child: @ql_qualifiedRhs_child_type ref +); + +ql_qualified_rhs_def( + unique int id: @ql_qualified_rhs, + int loc: @location ref +); + +@ql_qualified_expr_child_type = @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_expr_annotation | @ql_literal | @ql_par_expr | @ql_qualified_expr | @ql_qualified_rhs | @ql_range | @ql_set_literal | @ql_super_ref | @ql_variable + +#keyset[ql_qualified_expr, index] +ql_qualified_expr_child( + int ql_qualified_expr: @ql_qualified_expr ref, + int index: int ref, + unique int child: @ql_qualified_expr_child_type ref +); + +ql_qualified_expr_def( + unique int id: @ql_qualified_expr, + int loc: @location ref +); + +@ql_quantified_expr_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_quantified_expr( + unique int ql_quantified: @ql_quantified ref, + unique int expr: @ql_quantified_expr_type ref +); + +@ql_quantified_formula_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_quantified_formula( + unique int ql_quantified: @ql_quantified ref, + unique int formula: @ql_quantified_formula_type ref +); + +@ql_quantified_range_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_quantified_range( + unique int ql_quantified: @ql_quantified ref, + unique int range: @ql_quantified_range_type ref +); + +@ql_quantified_child_type = @ql_token_quantifier | @ql_var_decl + +#keyset[ql_quantified, index] +ql_quantified_child( + int ql_quantified: @ql_quantified ref, + int index: int ref, + unique int child: @ql_quantified_child_type ref +); + +ql_quantified_def( + unique int id: @ql_quantified, + int loc: @location ref +); + +@ql_range_lower_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +@ql_range_upper_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_range_def( + unique int id: @ql_range, + int lower: @ql_range_lower_type ref, + int upper: @ql_range_upper_type ref, + int loc: @location ref +); + +@ql_select_child_type = @ql_add_expr | @ql_aggregate | @ql_as_exprs | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_order_bys | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_var_decl | @ql_variable + +#keyset[ql_select, index] +ql_select_child( + int ql_select: @ql_select ref, + int index: int ref, + unique int child: @ql_select_child_type ref +); + +ql_select_def( + unique int id: @ql_select, + int loc: @location ref +); + +@ql_set_literal_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +#keyset[ql_set_literal, index] +ql_set_literal_child( + int ql_set_literal: @ql_set_literal ref, + int index: int ref, + unique int child: @ql_set_literal_child_type ref +); + +ql_set_literal_def( + unique int id: @ql_set_literal, + int loc: @location ref +); + +ql_special_call_def( + unique int id: @ql_special_call, + int child: @ql_token_special_id ref, + int loc: @location ref +); + +@ql_super_ref_child_type = @ql_token_super | @ql_type_expr + +#keyset[ql_super_ref, index] +ql_super_ref_child( + int ql_super_ref: @ql_super_ref ref, + int index: int ref, + unique int child: @ql_super_ref_child_type ref +); + +ql_super_ref_def( + unique int id: @ql_super_ref, + int loc: @location ref +); + +ql_type_alias_body_def( + unique int id: @ql_type_alias_body, + int child: @ql_type_expr ref, + int loc: @location ref +); + +ql_type_expr_name( + unique int ql_type_expr: @ql_type_expr ref, + unique int name: @ql_token_class_name ref +); + +@ql_typeExpr_child_type = @ql_module_expr | @ql_token_dbtype | @ql_token_primitive_type + +ql_type_expr_child( + unique int ql_type_expr: @ql_type_expr ref, + unique int child: @ql_typeExpr_child_type ref +); + +ql_type_expr_def( + unique int id: @ql_type_expr, + int loc: @location ref +); + +#keyset[ql_type_union_body, index] +ql_type_union_body_child( + int ql_type_union_body: @ql_type_union_body ref, + int index: int ref, + unique int child: @ql_type_expr ref +); + +ql_type_union_body_def( + unique int id: @ql_type_union_body, + int loc: @location ref +); + +@ql_unary_expr_child_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token_unop | @ql_unary_expr | @ql_variable + +#keyset[ql_unary_expr, index] +ql_unary_expr_child( + int ql_unary_expr: @ql_unary_expr ref, + int index: int ref, + unique int child: @ql_unary_expr_child_type ref +); + +ql_unary_expr_def( + unique int id: @ql_unary_expr, + int loc: @location ref +); + +@ql_unqual_agg_body_asExprs_type = @ql_as_exprs | @ql_reserved_word + +#keyset[ql_unqual_agg_body, index] +ql_unqual_agg_body_as_exprs( + int ql_unqual_agg_body: @ql_unqual_agg_body ref, + int index: int ref, + unique int as_exprs: @ql_unqual_agg_body_asExprs_type ref +); + +@ql_unqual_agg_body_guard_type = @ql_add_expr | @ql_aggregate | @ql_call_or_unqual_agg_expr | @ql_comp_term | @ql_conjunction | @ql_disjunction | @ql_expr_annotation | @ql_if_term | @ql_implication | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_mul_expr | @ql_negation | @ql_par_expr | @ql_prefix_cast | @ql_qualified_expr | @ql_quantified | @ql_range | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_unary_expr | @ql_variable + +ql_unqual_agg_body_guard( + unique int ql_unqual_agg_body: @ql_unqual_agg_body ref, + unique int guard: @ql_unqual_agg_body_guard_type ref +); + +#keyset[ql_unqual_agg_body, index] +ql_unqual_agg_body_child( + int ql_unqual_agg_body: @ql_unqual_agg_body ref, + int index: int ref, + unique int child: @ql_var_decl ref +); + +ql_unqual_agg_body_def( + unique int id: @ql_unqual_agg_body, + int loc: @location ref +); + +@ql_varDecl_child_type = @ql_type_expr | @ql_var_name + +#keyset[ql_var_decl, index] +ql_var_decl_child( + int ql_var_decl: @ql_var_decl ref, + int index: int ref, + unique int child: @ql_varDecl_child_type ref +); + +ql_var_decl_def( + unique int id: @ql_var_decl, + int loc: @location ref +); + +ql_var_name_def( + unique int id: @ql_var_name, + int child: @ql_token_simple_id ref, + int loc: @location ref +); + +@ql_variable_child_type = @ql_token_result | @ql_token_this | @ql_var_name + +ql_variable_def( + unique int id: @ql_variable, + int child: @ql_variable_child_type ref, + int loc: @location ref +); + +ql_yaml_comment_def( + unique int id: @ql_yaml_comment, + int child: @ql_token_yaml_value ref, + int loc: @location ref +); + +@ql_yaml_entry_child_type = @ql_yaml_comment | @ql_yaml_keyvaluepair | @ql_yaml_listitem + +ql_yaml_entry_def( + unique int id: @ql_yaml_entry, + int child: @ql_yaml_entry_child_type ref, + int loc: @location ref +); + +@ql_yaml_key_child_type = @ql_token_simple_id | @ql_yaml_key + +#keyset[ql_yaml_key, index] +ql_yaml_key_child( + int ql_yaml_key: @ql_yaml_key ref, + int index: int ref, + unique int child: @ql_yaml_key_child_type ref +); + +ql_yaml_key_def( + unique int id: @ql_yaml_key, + int loc: @location ref +); + +ql_yaml_keyvaluepair_def( + unique int id: @ql_yaml_keyvaluepair, + int key__: @ql_yaml_key ref, + int value: @ql_token_yaml_value ref, + int loc: @location ref +); + +ql_yaml_listitem_def( + unique int id: @ql_yaml_listitem, + int child: @ql_token_yaml_value ref, + int loc: @location ref +); + +ql_tokeninfo( + unique int id: @ql_token, + int kind: int ref, + string value: string ref, + int loc: @location ref +); + +case @ql_token.kind of + 0 = @ql_reserved_word +| 1 = @ql_token_addop +| 2 = @ql_token_agg_id +| 3 = @ql_token_annot_name +| 4 = @ql_token_block_comment +| 5 = @ql_token_class_name +| 6 = @ql_token_closure +| 7 = @ql_token_compop +| 8 = @ql_token_db_boolean +| 9 = @ql_token_db_case +| 10 = @ql_token_db_date +| 11 = @ql_token_db_float +| 12 = @ql_token_db_int +| 13 = @ql_token_db_ref +| 14 = @ql_token_db_string +| 15 = @ql_token_db_unique +| 16 = @ql_token_db_varchar +| 17 = @ql_token_dbtype +| 18 = @ql_token_direction +| 19 = @ql_token_empty +| 20 = @ql_token_false +| 21 = @ql_token_float +| 22 = @ql_token_integer +| 23 = @ql_token_line_comment +| 24 = @ql_token_literal_id +| 25 = @ql_token_mulop +| 26 = @ql_token_predicate +| 27 = @ql_token_predicate_name +| 28 = @ql_token_primitive_type +| 29 = @ql_token_qldoc +| 30 = @ql_token_quantifier +| 31 = @ql_token_result +| 32 = @ql_token_simple_id +| 33 = @ql_token_special_id +| 34 = @ql_token_string +| 35 = @ql_token_super +| 36 = @ql_token_this +| 37 = @ql_token_true +| 38 = @ql_token_underscore +| 39 = @ql_token_unop +| 40 = @ql_token_yaml_value +; + + +@ql_ast_node = @ql_add_expr | @ql_aggregate | @ql_annot_arg | @ql_annotation | @ql_arityless_predicate_expr | @ql_as_expr | @ql_as_exprs | @ql_body | @ql_bool | @ql_call_body | @ql_call_or_unqual_agg_expr | @ql_charpred | @ql_class_member | @ql_classless_predicate | @ql_comp_term | @ql_conjunction | @ql_dataclass | @ql_datatype | @ql_datatype_branch | @ql_datatype_branches | @ql_db_annotation | @ql_db_args_annotation | @ql_db_branch | @ql_db_case_decl | @ql_db_col_type | @ql_db_column | @ql_db_entry | @ql_db_repr_type | @ql_db_table | @ql_db_table_name | @ql_db_union_decl | @ql_disjunction | @ql_expr_aggregate_body | @ql_expr_annotation | @ql_field | @ql_full_aggregate_body | @ql_higher_order_term | @ql_if_term | @ql_implication | @ql_import_directive | @ql_import_module_expr | @ql_in_expr | @ql_instance_of | @ql_literal | @ql_member_predicate | @ql_module | @ql_module_alias_body | @ql_module_expr | @ql_module_member | @ql_module_name | @ql_mul_expr | @ql_negation | @ql_order_by | @ql_order_bys | @ql_par_expr | @ql_predicate_alias_body | @ql_predicate_expr | @ql_prefix_cast | @ql_ql | @ql_qual_module_expr | @ql_qualified_expr | @ql_qualified_rhs | @ql_quantified | @ql_range | @ql_select | @ql_set_literal | @ql_special_call | @ql_super_ref | @ql_token | @ql_type_alias_body | @ql_type_expr | @ql_type_union_body | @ql_unary_expr | @ql_unqual_agg_body | @ql_var_decl | @ql_var_name | @ql_variable | @ql_yaml_comment | @ql_yaml_entry | @ql_yaml_key | @ql_yaml_keyvaluepair | @ql_yaml_listitem + +@ql_ast_node_parent = @file | @ql_ast_node #keyset[parent, parent_index] -ast_node_parent( - int child: @ast_node ref, - int parent: @ast_node_parent ref, +ql_ast_node_parent( + int child: @ql_ast_node ref, + int parent: @ql_ast_node_parent ref, int parent_index: int ref ); diff --git a/ql/src/queries/performance/AbstractClassImport.ql b/ql/src/queries/performance/AbstractClassImport.ql new file mode 100644 index 00000000000..b3dfceebed1 --- /dev/null +++ b/ql/src/queries/performance/AbstractClassImport.ql @@ -0,0 +1,105 @@ +/** + * @name Bidirectional imports for abstract classes + * @description An abstract class should import each of its subclasses, unless + * it is meant as a configuration-style class, in which case it + * should import none of them. + * @kind problem + * @problem.severity error + * @id ql/abstract-class-import + * @tags correctness + * performance + * @precision high + */ + +import ql +import codeql_ql.ast.internal.Module + +File imports(File file) { + exists(Import imp | + imp.getLocation().getFile() = file and + result = imp.getResolvedModule().getFile() + ) +} + +predicate testFile(File f) { f.getRelativePath().matches("%/ql/test/%") } + +predicate nonTestQuery(File f) { f.getBaseName().matches("%.ql") and not testFile(f) } + +predicate liveNonTestFile(File f) { + exists(File query | nonTestQuery(query) and f = imports*(query)) +} + +predicate experimentalFile(File f) { f.getRelativePath().matches("%/experimental/%") } + +Class getASubclassOfAbstract(Class ab) { + ab.isAbstract() and + result.getType().getASuperType() = ab.getType() +} + +/** Gets a non-abstract subclass of `ab` that contributes to the extent of `ab`. */ +Class concreteExternalSubclass(Class ab) { + ab.isAbstract() and + not result.isAbstract() and + result = getASubclassOfAbstract+(ab) and + // Heuristic: An abstract class with subclasses in the same file and no other + // imported subclasses is likely intentional. + result.getLocation().getFile() != ab.getLocation().getFile() and + // Exclude subclasses in tests and libraries that are only used in tests. + liveNonTestFile(result.getLocation().getFile()) +} + +/** Holds if there is a bidirectional import between the abstract class `ab` and its subclass `sub` */ +predicate bidirectionalImport(Class ab, Class sub) { + sub = concreteExternalSubclass(ab) and + sub.getLocation().getFile() = imports*(ab.getLocation().getFile()) +} + +predicate stats(Class ab, int imports, int nonImports) { + ab.isAbstract() and + imports = + strictcount(Class sub | sub = concreteExternalSubclass(ab) and bidirectionalImport(ab, sub)) and + nonImports = + strictcount(Class sub | sub = concreteExternalSubclass(ab) and not bidirectionalImport(ab, sub)) +} + +predicate alert(Class ab, string msg, Class sub, Class sub2) { + sub = concreteExternalSubclass(ab) and + sub2 = concreteExternalSubclass(ab) and + exists(int imports, int nonImports | stats(ab, imports, nonImports) | + (imports < 10 or nonImports < 10) and // if this is not the case, it's likely intended + ( + // report whichever of imports or nonimports there are more of; both if equal + imports >= nonImports and + not bidirectionalImport(ab, sub) and + sub2 = + min(Class other | + other = concreteExternalSubclass(ab) and + bidirectionalImport(ab, other) + | + other order by other.getLocation().toString() + ) and + msg = + "This abstract class doesn't import its subclass $@ but imports " + imports + + " other subclasses, such as $@." + or + nonImports >= imports and + bidirectionalImport(ab, sub) and + sub2 = + min(Class other | + other = concreteExternalSubclass(ab) and + not bidirectionalImport(ab, other) + | + other order by other.getLocation().toString() + ) and + msg = + "This abstract class imports its subclass $@ but doesn't import " + nonImports + + " other subclasses, such as $@." + ) + ) and + // exclude results in experimental + not experimentalFile(sub.getLocation().getFile()) +} + +from Class ab, string msg, Class sub, Class sub2 +where alert(ab, msg, sub, sub2) +select ab, msg, sub, sub.getName(), sub2, sub2.getName() diff --git a/ql/src/queries/performance/NonInitialStdLibImport.ql b/ql/src/queries/performance/NonInitialStdLibImport.ql new file mode 100644 index 00000000000..88296d895fc --- /dev/null +++ b/ql/src/queries/performance/NonInitialStdLibImport.ql @@ -0,0 +1,30 @@ +/** + * @name Standard library is not the first import + * @description Importing other libraries before the standard library can cause a change in + * evaluation order and may lead to performance errors. + * @kind problem + * @problem.severity error + * @id ql/noninitial-stdlib-import + * @tags performance + * @precision high + */ + +import ql + +predicate isStdLibImport(Import i, string name) { + name = i.getQualifiedName(0) and + i.getLocation().getFile().getRelativePath().matches(name + "%") and + not exists(i.getQualifiedName(1)) +} + +Import importBefore(Import i) { + exists(Module m, int bi, int ii | + result = m.getMember(bi) and + i = m.getMember(ii) and + bi < ii + ) +} + +from Import i +where isStdLibImport(i, _) and exists(importBefore(i)) +select i, "This import may cause reevaluation to occur, as there are other imports preceding it" diff --git a/ql/src/queries/performance/TransitiveStep.ql b/ql/src/queries/performance/TransitiveStep.ql new file mode 100644 index 00000000000..045424256db --- /dev/null +++ b/ql/src/queries/performance/TransitiveStep.ql @@ -0,0 +1,165 @@ +/** + * @name Transitively closed recursive delta + * @description Using a transitively closed relation as the step in a recursive + * delta can perform poorly as it is inherently quadratic and may + * force materialization of a fastTC. The transitively closed delta + * can usually just be replaced by the underlying step relation as + * the recursive context will provide transitive closure. + * @kind problem + * @problem.severity error + * @id ql/transitive-step + * @tags performance + * @precision high + */ + +import ql + +Expr getArg(Call c, int i) { + result = c.getArgument(i) + or + result = c.(MemberCall).getBase() and i = -1 + or + exists(c.getType()) and result = c and i = -2 +} + +newtype TParameter = + TThisParam(ClassPredicate p) or + TResultParam(Predicate p) { exists(p.getReturnType()) } or + TVarParam(VarDecl v) { any(Predicate p).getParameter(_) = v } + +class Parameter extends TParameter { + string toString() { + this instanceof TThisParam and result = "this" + or + this instanceof TResultParam and result = "result" + or + exists(VarDecl v | this = TVarParam(v) and result = v.toString()) + } + + Expr getAnAccess() { + result instanceof ThisAccess and this = TThisParam(result.getEnclosingPredicate()) + or + result instanceof ResultAccess and this = TResultParam(result.getEnclosingPredicate()) + or + this = TVarParam(result.(VarAccess).getDeclaration()) + } + + predicate isParameterOf(Predicate p, int i) { + this = TThisParam(p) and i = -1 + or + this = TResultParam(p) and i = -2 + or + this = TVarParam(p.getParameter(i)) + } +} + +predicate hasTwoArgs(Call c, Expr arg1, Expr arg2) { + exists(int i1, int i2 | + arg1 = getArg(c, i1) and + arg2 = getArg(c, i2) and + i1 != i2 and + strictcount(getArg(c, _)) = 2 + ) +} + +predicate transitivePred(Predicate p, AstNode tc) { + exists(PredicateExpr pe | + p.(ClasslessPredicate).getAlias() = pe and + transitivePred(pe.getResolvedPredicate(), tc) + ) + or + p.(ClasslessPredicate).getAlias().(HigherOrderFormula).getName() = "fastTC" and + tc = p + or + strictcount(Parameter par | par.isParameterOf(p, _)) = 2 and + exists(Formula body | p.getBody() = body | + transitiveCall(body, tc) and + hasTwoArgs(body, any(Identifier i1), any(Identifier i2)) + or + exists(ComparisonFormula eq, Call c | + body = eq and + eq.getSymbol() = "=" and + transitiveCall(c, tc) and + getArg(c, _) instanceof Identifier and + eq.getAnOperand() = c and + eq.getAnOperand() instanceof Identifier + ) + ) +} + +predicate transitiveCall(Call c, AstNode tc) { + c.isClosure(_) and tc = c + or + transitivePred(c.getTarget(), tc) +} + +class TransitivelyClosedCall extends Call { + TransitivelyClosedCall() { transitiveCall(this, _) } + + predicate hasArgs(Expr arg1, Expr arg2) { hasTwoArgs(this, arg1, arg2) } + + AstNode getReason() { transitiveCall(this, result) } +} + +AstNode getParentOfExpr(Expr e) { result = e.getParent() } + +Formula getEnclosing(Expr e) { result = getParentOfExpr+(e) } + +Formula enlargeScopeStep(Formula f) { result.(Conjunction).getAnOperand() = f } + +Formula enlargeScope(Formula f) { + result = enlargeScopeStep*(f) and not exists(enlargeScopeStep(result)) +} + +predicate varaccesValue(VarAccess va, VarDecl v, Formula scope) { + va.getDeclaration() = v and + scope = enlargeScope(getEnclosing(va)) +} + +predicate thisValue(ThisAccess ta, Formula scope) { scope = enlargeScope(getEnclosing(ta)) } + +predicate resultValue(ResultAccess ra, Formula scope) { scope = enlargeScope(getEnclosing(ra)) } + +predicate valueStep(Expr e1, Expr e2) { + exists(VarDecl v, Formula scope | + varaccesValue(e1, v, scope) and + varaccesValue(e2, v, scope) + ) + or + exists(Formula scope | + thisValue(e1, scope) and + thisValue(e2, scope) + or + resultValue(e1, scope) and + resultValue(e2, scope) + ) + or + exists(InlineCast c | + e1 = c and e2 = c.getBase() + or + e2 = c and e1 = c.getBase() + ) + or + exists(ComparisonFormula eq | + eq.getSymbol() = "=" and + eq.getAnOperand() = e1 and + eq.getAnOperand() = e2 and + e1 != e2 + ) +} + +predicate transitiveDelta(Call rec, TransitivelyClosedCall tc) { + exists(Expr recarg, int i, Expr tcarg, Predicate pred, Parameter p | + rec.getTarget() = pred and + pred = rec.getEnclosingPredicate() and + recarg = getArg(rec, i) and + valueStep*(recarg, tcarg) and + tc.hasArgs(tcarg, p.getAnAccess()) and + p.isParameterOf(pred, i) + ) +} + +from Call rec, TransitivelyClosedCall tc, AstNode reason +where transitiveDelta(rec, tc) and reason = tc.getReason() +select tc, "This recursive delta is transively closed $@, which may be a performance problem.", + reason, "here" diff --git a/ql/src/queries/style/LibraryAnnotation.ql b/ql/src/queries/style/LibraryAnnotation.ql new file mode 100644 index 00000000000..cf4a4bc8232 --- /dev/null +++ b/ql/src/queries/style/LibraryAnnotation.ql @@ -0,0 +1,15 @@ +/** + * @name Use of deprecated annotation + * @description The library annotation is deprecated + * @kind problem + * @problem.severity warning + * @id ql/deprecated-annotation + * @tags maintainability + * @precision very-high + */ + +import ql + +from AstNode n +where n.hasAnnotation("library") and not n.hasAnnotation("deprecated") +select n, "Don't use the library annotation." diff --git a/ql/src/queries/style/ToStringInQueryLogic.ql b/ql/src/queries/style/ToStringInQueryLogic.ql new file mode 100644 index 00000000000..93a4b816475 --- /dev/null +++ b/ql/src/queries/style/ToStringInQueryLogic.ql @@ -0,0 +1,344 @@ +/** + * @name Using 'toString' in query logic + * @description A query should not depend on the output of 'toString'. + * @kind problem + * @problem.severity error + * @id ql/to-string-in-logic + * @precision medium + * @tags maintainability + */ + +import ql +import codeql_ql.ast.internal.Builtins + +class ToString extends Predicate { + ToString() { this.getName() = "toString" } +} + +class ToStringCall extends Call { + ToStringCall() { this.getTarget() instanceof ToString } +} + +class NodesPredicate extends Predicate { + NodesPredicate() { this.getName() = "nodes" } +} + +class EdgesPredicate extends Predicate { + EdgesPredicate() { this.getName() = "edges" } +} + +class RegexpReplaceAll extends BuiltinPredicate { + RegexpReplaceAll() { this.getName() = "regexpReplaceAll" } +} + +class RegexpReplaceAllCall extends MemberCall { + RegexpReplaceAllCall() { this.getTarget() instanceof RegexpReplaceAll } +} + +module DataFlow { + private newtype TNode = + TExprNode(Expr e) or + TOutParameterNode(Parameter p) or + TArgumentOutNode(VarAccess acc, Call call, int pos) { + acc.(Argument).getCall() = call and acc.(Argument).getPosition() = pos + } or + TParameterNode(Parameter p) + + /** An argument to a call. */ + class Argument extends Expr { + Call call; + int pos; + + Argument() { call.getArgument(pos) = this } + + /** Gets the call that has this argument. */ + Call getCall() { result = call } + + /** Gets the position of this argument. */ + int getPosition() { result = pos } + } + + private newtype TParameter = + TThisParameter(ClassPredicate p) or + TResultParameter(Predicate p) { exists(p.getReturnType()) } or + TVariableParameter(VarDecl v, int i, Predicate pred) { pred.getParameter(i) = v } + + abstract class Parameter extends TParameter { + string toString() { this.hasName(result) } + + abstract predicate hasName(string name); + + abstract int getIndex(); + + abstract Predicate getPredicate(); + } + + class ThisParameter extends Parameter, TThisParameter { + ClassPredicate p; + + ThisParameter() { this = TThisParameter(p) } + + override predicate hasName(string name) { name = "this" } + + override int getIndex() { result = -1 } + + override Predicate getPredicate() { result = p } + } + + class ResultParameter extends Parameter, TResultParameter { + Predicate p; + + ResultParameter() { this = TResultParameter(p) } + + override predicate hasName(string name) { name = "result" } + + override int getIndex() { result = -2 } + + override Predicate getPredicate() { result = p } + } + + class VariableParameter extends Parameter, TVariableParameter { + VarDecl v; + int i; + Predicate p; + + VariableParameter() { this = TVariableParameter(v, i, p) } + + override predicate hasName(string name) { name = v.getName() } + + override int getIndex() { result = i } + + override Predicate getPredicate() { result = p } + } + + class Node extends TNode { + /** Gets the predicate to which this node belongs. */ + Predicate getPredicate() { none() } // overridden in subclasses + + Expr asExpr() { result = this.(ExprNode).getExpr() } + + /** Gets a textual representation of this element. */ + string toString() { none() } // overridden by subclasses + } + + /** + * An expression, viewed as a node in a data flow graph. + */ + class ExprNode extends Node, TExprNode { + Expr expr; + + ExprNode() { this = TExprNode(expr) } + + override string toString() { result = expr.toString() } + + /** Gets the expression corresponding to this node. */ + Expr getExpr() { result = expr } + } + + class ParameterNode extends Node, TParameterNode { + Parameter p; + + ParameterNode() { this = TParameterNode(p) } + + override string toString() { result = p.toString() } + } + + newtype TReturnKind = + TNormalReturnKind() or + TParameterOutKind(int i) { any(Parameter p).getIndex() = i } + + /** A data flow node that represents the output of a call at the call site. */ + abstract class OutNode extends Node { + /** Gets the underlying call. */ + abstract Call getCall(); + } + + class ArgumentOutNode extends Node, TArgumentOutNode, OutNode { + VarAccess acc; + Call call; + int pos; + + ArgumentOutNode() { this = TArgumentOutNode(acc, call, pos) } + + VarAccess getVarAccess() { result = acc } + + override string toString() { result = acc.toString() + " [out]" } + + override Call getCall() { result = call } + + int getIndex() { result = pos } + } + + class OutParameterNode extends Node, TOutParameterNode { + Parameter p; + + OutParameterNode() { this = TOutParameterNode(p) } + + Parameter getParameter() { result = p } + + override string toString() { result = p.toString() } + } + + AstNode getParentOfExpr(Expr e) { result = e.getParent() } + + Formula getEnclosing(Expr e) { result = getParentOfExpr+(e) } + + Formula enlargeScopeStep(Formula f) { result.(Conjunction).getAnOperand() = f } + + Formula enlargeScope(Formula f) { + result = enlargeScopeStep*(f) and not exists(enlargeScopeStep(result)) + } + + predicate varaccesValue(VarAccess va, VarDecl v, Formula scope) { + va.getDeclaration() = v and + scope = enlargeScope(getEnclosing(va)) + } + + predicate thisValue(ThisAccess ta, Formula scope) { scope = enlargeScope(getEnclosing(ta)) } + + predicate resultValue(ResultAccess ra, Formula scope) { scope = enlargeScope(getEnclosing(ra)) } + + Formula getParentFormula(Formula f) { f.getParent() = result } + + predicate valueStep(Expr e1, Expr e2) { + exists(VarDecl v, Formula scope | + varaccesValue(e1, v, scope) and + varaccesValue(e2, v, scope) + ) + or + exists(VarDecl v, Formula f, Select sel | + getParentFormula*(f) = sel.getWhere() and + varaccesValue(e1, v, f) and + sel.getExpr(_) = e2 + ) + or + exists(Formula scope | + thisValue(e1, scope) and + thisValue(e2, scope) + or + resultValue(e1, scope) and + resultValue(e2, scope) + ) + or + exists(InlineCast c | + e1 = c and e2 = c.getBase() + or + e2 = c and e1 = c.getBase() + ) + or + exists(ComparisonFormula eq | + eq.getSymbol() = "=" and + eq.getAnOperand() = e1 and + eq.getAnOperand() = e2 and + e1 != e2 + ) + } + + predicate paramStep(Expr e1, Parameter p2) { + exists(VarDecl v | + p2 = TVariableParameter(v, _, _) and + varaccesValue(e1, v, _) + ) + or + exists(Formula scope | + p2 = TThisParameter(scope.getEnclosingPredicate()) and + thisValue(e1, scope) + or + p2 = TResultParameter(scope.getEnclosingPredicate()) and + resultValue(e1, scope) + ) + } + + predicate additionalLocalStep(Node nodeFrom, Node nodeTo) { + nodeFrom.asExpr().getType() instanceof StringClass and + nodeFrom.asExpr().getType() instanceof StringClass and + exists(BinOpExpr binop | + nodeFrom.asExpr() = binop.getAnOperand() and + nodeTo.asExpr() = binop + ) + or + nodeTo.asExpr().(RegexpReplaceAllCall).getBase() = nodeFrom.asExpr() + } + + predicate localStep(Node nodeFrom, Node nodeTo) { + valueStep(nodeFrom.asExpr(), nodeTo.asExpr()) + or + paramStep(nodeFrom.asExpr(), nodeTo.(OutParameterNode).getParameter()) + or + valueStep(nodeFrom.(ArgumentOutNode).getVarAccess(), nodeTo.asExpr()) + or + additionalLocalStep(nodeFrom, nodeTo) + } + + predicate step(Node nodeFrom, Node nodeTo) { + // Local flow + localStep(nodeFrom, nodeTo) + or + // Flow out of functions + exists(Call call, Parameter p, OutParameterNode outParam, ArgumentOutNode outArg | + outParam = nodeFrom and + outArg = nodeTo + | + p = outParam.getParameter() and + p.getPredicate() = call.getTarget() and + outArg.getCall() = call and + outArg.getIndex() = p.getIndex() + ) + } + + predicate flowsFromSource(Node node) { + isSource(node.asExpr()) + or + exists(Node mid | flowsFromSource(mid) | step(mid, node)) + } + + predicate flowsToSink(Node node) { + flowsFromSource(node) and isSink(node) + or + exists(Node mid | flowsToSink(mid) | step(node, mid)) + } + + predicate isSink(Node sink) { + sink.asExpr() = any(Select s).getExpr(_) + or + sink.getPredicate() instanceof NodesPredicate + or + sink.getPredicate() instanceof EdgesPredicate + } + + predicate isSource(ToStringCall toString) { + not toString.getEnclosingPredicate() instanceof ToString and + not toString.getEnclosingPredicate() instanceof NodesPredicate and + not toString.getEnclosingPredicate() instanceof EdgesPredicate + } +} + +predicate flowsToSelect(Expr e) { + exists(DataFlow::Node source | + source.asExpr() = e and + DataFlow::flowsToSink(source) + ) +} + +from ToStringCall call +where + // It's not part of a toString call + DataFlow::isSource(call) and + // The call doesn't flow to a select + not flowsToSelect(call) and + // It's in a query + call.getLocation().getFile().getBaseName().matches("%.ql") and + // ... and not in a test + not ( + call.getLocation() + .getFile() + .getAbsolutePath() + .toLowerCase() + .matches(["%test%", "%consistency%", "%meta%"]) + or + call.getLocation() + .getFile() + .getAbsolutePath() + .regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*") + ) +select call, "Query logic depends on implementation of 'toString'." diff --git a/ql/src/queries/style/UseSetLiteral.ql b/ql/src/queries/style/UseSetLiteral.ql new file mode 100644 index 00000000000..d0e983a1774 --- /dev/null +++ b/ql/src/queries/style/UseSetLiteral.ql @@ -0,0 +1,129 @@ +/** + * @name Use a set literal in place of `or` + * @description A chain of `or`s can be replaced with a set literal, improving readability. + * @kind problem + * @problem.severity recommendation + * @id ql/use-set-literal + * @tags maintainability + * @precision high + */ + +import ql + +/** + * A chain of disjunctions treated as one object. For example the following is + * a chain of disjunctions with three operands: + * ``` + * a or b or c + * ``` + */ +class DisjunctionChain extends Disjunction { + DisjunctionChain() { not exists(Disjunction parent | parent.getAnOperand() = this) } + + /** + * Gets any operand of the chain. + */ + Formula getAnOperandRec() { + result = getAnOperand*() and + not result instanceof Disjunction + } +} + +/** + * An equality comparison with a `Literal`. For example: + * ``` + * x = 4 + * ``` + */ +class EqualsLiteral extends ComparisonFormula { + EqualsLiteral() { + getSymbol() = "=" and + getAnOperand() instanceof Literal + } +} + +/** + * A chain of disjunctions where each operand is an equality comparison between + * the same thing and various `Literal`s. For example: + * ``` + * x = 4 or + * x = 5 or + * x = 6 + * ``` + */ +class DisjunctionEqualsLiteral extends DisjunctionChain { + DisjunctionEqualsLiteral() { + // VarAccess on the same variable + exists(VarDef v | + forex(Formula f | f = getAnOperandRec() | + f.(EqualsLiteral).getAnOperand().(VarAccess).getDeclaration() = v + ) + ) + or + // FieldAccess on the same variable + exists(VarDecl v | + forex(Formula f | f = getAnOperandRec() | + f.(EqualsLiteral).getAnOperand().(FieldAccess).getDeclaration() = v + ) + ) + or + // ThisAccess + forex(Formula f | f = getAnOperandRec() | + f.(EqualsLiteral).getAnOperand() instanceof ThisAccess + ) + or + // ResultAccess + forex(Formula f | f = getAnOperandRec() | + f.(EqualsLiteral).getAnOperand() instanceof ResultAccess + ) + // (in principle something like GlobalValueNumbering could be used to generalize this) + } +} + +/** + * A call with a single `Literal` argument. For example: + * ``` + * myPredicate(4) + * ``` + */ +class CallLiteral extends Call { + CallLiteral() { + getNumberOfArguments() = 1 and + getArgument(0) instanceof Literal + } +} + +/** + * A chain of disjunctions where each operand is a call to the same predicate + * using various `Literal`s. For example: + * ``` + * myPredicate(4) or + * myPredicate(5) or + * myPredicate(6) + * ``` + */ +class DisjunctionPredicateLiteral extends DisjunctionChain { + DisjunctionPredicateLiteral() { + // Call to the same target + exists(PredicateOrBuiltin target | + forex(Formula f | f = getAnOperandRec() | f.(CallLiteral).getTarget() = target) + ) + } +} + +from DisjunctionChain d, string msg, int c +where + ( + d instanceof DisjunctionEqualsLiteral and + msg = + "This formula of " + c.toString() + + " comparisons can be replaced with a single equality on a set literal, improving readability." + or + d instanceof DisjunctionPredicateLiteral and + msg = + "This formula of " + c.toString() + + " predicate calls can be replaced with a single call on a set literal, improving readability." + ) and + c = count(d.getAnOperandRec()) and + c >= 4 +select d, msg diff --git a/ql/src/queries/style/docs/ClassDocs.ql b/ql/src/queries/style/docs/ClassDocs.ql new file mode 100644 index 00000000000..1dad0867996 --- /dev/null +++ b/ql/src/queries/style/docs/ClassDocs.ql @@ -0,0 +1,26 @@ +/** + * @name Class QLDoc style. + * @description The QLDoc for a class should start with "A", "An", or "The". + * @kind problem + * @problem.severity warning + * @id ql/class-doc-style + * @tags maintainability + * @precision very-high + */ + +import ql + +bindingset[s] +predicate badStyle(string s) { + not s.replaceAll("/**", "") + .replaceAll("*", "") + .splitAt("\n") + .trim() + .matches(["A %", "An %", "The %", "INTERNAL%", "DEPRECATED%"]) +} + +from Class c +where + badStyle(c.getQLDoc().getContents()) and + not c.isPrivate() +select c.getQLDoc(), "The QLDoc for a class should start with 'A', 'An', or 'The'." diff --git a/ql/src/queries/style/docs/MissingQLDoc.ql b/ql/src/queries/style/docs/MissingQLDoc.ql new file mode 100644 index 00000000000..c7da02073a3 --- /dev/null +++ b/ql/src/queries/style/docs/MissingQLDoc.ql @@ -0,0 +1,25 @@ +/** + * @name Missing QLDoc. + * @description Library classes should have QLDoc. + * @kind problem + * @problem.severity recommendation + * @id ql/missing-qldoc + * @tags maintainability + * @precision high + */ + +import ql + +from File f, Class c +where + f = c.getLocation().getFile() and + not exists(c.getQLDoc()) and // no QLDoc + f.getExtension() = "qll" and // in a library + not c.isPrivate() and // class is public + not exists(Module m | + m.getAMember*() = c and + m.isPrivate() // modules containing the class are public + ) and + not exists(c.getAliasType()) and // class is not just an alias + not f.getParentContainer*().getBaseName().toLowerCase() = ["internal", "experimental", "test"] // exclusions +select c, "This library class should have QLDoc." diff --git a/ql/src/queries/style/docs/NonUSSpelling.ql b/ql/src/queries/style/docs/NonUSSpelling.ql new file mode 100644 index 00000000000..8861629ca87 --- /dev/null +++ b/ql/src/queries/style/docs/NonUSSpelling.ql @@ -0,0 +1,38 @@ +/** + * @name Non US spelling + * @description QLDocs shold use US spelling. + * @kind problem + * @problem.severity warning + * @id ql/non-us-spelling + * @tags maintainability + * @precision very-high + */ + +import ql + +predicate non_us_word(string wrong, string right) { + exists(string s | + wrong = s.splitAt("/", 0) and + right = s.splitAt("/", 1) and + s = ["colour/color", "authorise/authorize", "analyse/analyze"] + ) +} + +bindingset[s] +predicate contains_non_us_spelling(string s, string wrong, string right) { + non_us_word(wrong, right) and + ( + s.matches("%" + wrong + "%") and + wrong != "analyse" + or + // analyses (as a noun) is fine + s.regexpMatch(".*analyse[^s].*") and + wrong = "analyse" + ) +} + +from QLDoc doc, string wrong, string right +where contains_non_us_spelling(doc.getContents().toLowerCase(), wrong, right) +select doc, + "This QLDoc comment contains the non-US spelling '" + wrong + "', which should instead be '" + + right + "'." diff --git a/ql/test/callgraph/Foo.qll b/ql/test/callgraph/Foo.qll index d9a00db69bc..3bd6484be12 100644 --- a/ql/test/callgraph/Foo.qll +++ b/ql/test/callgraph/Foo.qll @@ -31,3 +31,9 @@ module Aliases { alias0() // <- works } } + +module Buildins { + predicate replaceAll(string s) { "foo".replaceAll("foo", "bar") = s } + + predicate regexpCapture(string s) { "foo".regexpCapture("\\w", 1) = s } +} diff --git a/ql/test/callgraph/Overrides.qll b/ql/test/callgraph/Overrides.qll new file mode 100644 index 00000000000..1adcab1b949 --- /dev/null +++ b/ql/test/callgraph/Overrides.qll @@ -0,0 +1,30 @@ +import ql + +class Foo extends int { + Foo() { this in [1, 2, 3] } + + int bar() { result = this } + + predicate baz(int i) { i = this.bar() } +} + +class Bar extends Foo { + Bar() { this = [1, 2] } + + override int bar() { result = 10 * this } + + override predicate baz(int i) { i = this.bar() } +} + +class Baz extends Foo { + Baz() { this = 1 } + + override int bar() { result = 100 * this } + + override predicate baz(int i) { i = this.bar() } +} + +query predicate test(Foo f, int i, int j) { + f.bar() = i and + f.baz(j) +} diff --git a/ql/test/callgraph/callgraph.expected b/ql/test/callgraph/callgraph.expected index 39ba4dd101a..e4540d519ff 100644 --- a/ql/test/callgraph/callgraph.expected +++ b/ql/test/callgraph/callgraph.expected @@ -1,3 +1,4 @@ +getTarget | Foo.qll:5:26:5:30 | PredicateCall | Foo.qll:3:1:3:26 | ClasslessPredicate foo | | Foo.qll:10:21:10:25 | PredicateCall | Foo.qll:8:3:8:28 | ClassPredicate bar | | Foo.qll:14:30:14:40 | MemberCall | Foo.qll:10:3:10:27 | ClassPredicate baz | @@ -6,3 +7,16 @@ | Foo.qll:29:5:29:16 | PredicateCall | Foo.qll:26:3:26:32 | ClasslessPredicate alias2 | | Foo.qll:31:5:31:12 | PredicateCall | Foo.qll:22:3:22:32 | ClasslessPredicate myThing0 | | Foo.qll:31:5:31:12 | PredicateCall | Foo.qll:24:3:24:32 | ClasslessPredicate alias0 | +| Foo.qll:36:36:36:65 | MemberCall | file://:0:0:0:0 | replaceAll | +| Foo.qll:38:39:38:67 | MemberCall | file://:0:0:0:0 | regexpCapture | +| Overrides.qll:8:30:8:39 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar | +| Overrides.qll:16:39:16:48 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar | +| Overrides.qll:16:39:16:48 | MemberCall | Overrides.qll:14:12:14:43 | ClassPredicate bar | +| Overrides.qll:24:39:24:48 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar | +| Overrides.qll:24:39:24:48 | MemberCall | Overrides.qll:22:12:22:44 | ClassPredicate bar | +| Overrides.qll:28:3:28:9 | MemberCall | Overrides.qll:6:3:6:29 | ClassPredicate bar | +| Overrides.qll:29:3:29:10 | MemberCall | Overrides.qll:8:3:8:41 | ClassPredicate baz | +| packs/src/SrcThing.qll:4:3:4:8 | PredicateCall | packs/lib/LibThing/Foo.qll:1:1:1:30 | ClasslessPredicate foo | +| packs/src/SrcThing.qll:5:3:5:8 | PredicateCall | packs/src/SrcThing.qll:8:1:8:30 | ClasslessPredicate bar | +dependsOn +| packs/src/qlpack.yml:1:1:1:4 | ql-testing-src-pack | packs/lib/qlpack.yml:1:1:1:4 | ql-testing-lib-pack | diff --git a/ql/test/callgraph/callgraph.ql b/ql/test/callgraph/callgraph.ql index 4b68e49e361..9ff79048b84 100644 --- a/ql/test/callgraph/callgraph.ql +++ b/ql/test/callgraph/callgraph.ql @@ -1,3 +1,5 @@ import ql query AstNode getTarget(Call call) { result = call.getTarget() } + +query YAML::QLPack dependsOn(YAML::QLPack pack) { result = pack.getADependency() } diff --git a/ql/test/callgraph/packs/lib/LibThing/Foo.qll b/ql/test/callgraph/packs/lib/LibThing/Foo.qll new file mode 100644 index 00000000000..56454a95557 --- /dev/null +++ b/ql/test/callgraph/packs/lib/LibThing/Foo.qll @@ -0,0 +1 @@ +predicate foo(int i) { i = 3 } diff --git a/ql/test/callgraph/packs/lib/qlpack.yml b/ql/test/callgraph/packs/lib/qlpack.yml new file mode 100644 index 00000000000..92e83d1e3d8 --- /dev/null +++ b/ql/test/callgraph/packs/lib/qlpack.yml @@ -0,0 +1,3 @@ +name: ql-testing-lib-pack +version: 0.1.0 +extractor: ql-test-stuff \ No newline at end of file diff --git a/ql/test/callgraph/packs/src/SrcThing.qll b/ql/test/callgraph/packs/src/SrcThing.qll new file mode 100644 index 00000000000..77c812235d9 --- /dev/null +++ b/ql/test/callgraph/packs/src/SrcThing.qll @@ -0,0 +1,8 @@ +import LibThing.Foo + +query predicate test(int i) { + foo(i) and + bar(i) +} + +predicate bar(int i) { i = 4 } diff --git a/ql/test/callgraph/packs/src/qlpack.yml b/ql/test/callgraph/packs/src/qlpack.yml new file mode 100644 index 00000000000..dcf148fe721 --- /dev/null +++ b/ql/test/callgraph/packs/src/qlpack.yml @@ -0,0 +1,4 @@ +name: ql-testing-src-pack +version: 0.1.0 +dependencies: + ql-testing-lib-pack: "*" \ No newline at end of file diff --git a/ql/test/printAst/printAst.expected b/ql/test/printAst/printAst.expected index 7b296161d4d..eb4340d2adb 100644 --- a/ql/test/printAst/printAst.expected +++ b/ql/test/printAst/printAst.expected @@ -220,6 +220,8 @@ nodes | file://:0:0:0:0 | none | semmle.label | [BuiltinPredicate] none | | file://:0:0:0:0 | pow | semmle.label | [BuiltinPredicate] pow | | file://:0:0:0:0 | prefix | semmle.label | [BuiltinPredicate] prefix | +| file://:0:0:0:0 | regexpCapture | semmle.label | [BuiltinPredicate] regexpCapture | +| file://:0:0:0:0 | regexpFind | semmle.label | [BuiltinPredicate] regexpFind | | file://:0:0:0:0 | regexpMatch | semmle.label | [BuiltinPredicate] regexpMatch | | file://:0:0:0:0 | regexpReplaceAll | semmle.label | [BuiltinPredicate] regexpReplaceAll | | file://:0:0:0:0 | replaceAll | semmle.label | [BuiltinPredicate] replaceAll | diff --git a/ql/test/queries/style/UseSetLiteral/UseSetLiteral.expected b/ql/test/queries/style/UseSetLiteral/UseSetLiteral.expected new file mode 100644 index 00000000000..fac79ff078e --- /dev/null +++ b/ql/test/queries/style/UseSetLiteral/UseSetLiteral.expected @@ -0,0 +1,8 @@ +| test.qll:4:3:7:7 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | +| test.qll:30:3:33:10 | Disjunction | This formula of 4 predicate calls can be replaced with a single call on a set literal, improving readability. | +| test.qll:44:3:47:12 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | +| test.qll:62:7:65:14 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | +| test.qll:68:7:71:13 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | +| test.qll:74:7:77:13 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | +| test.qll:87:3:90:9 | Disjunction | This formula of 4 predicate calls can be replaced with a single call on a set literal, improving readability. | +| test.qll:128:3:134:3 | Disjunction | This formula of 4 comparisons can be replaced with a single equality on a set literal, improving readability. | diff --git a/ql/test/queries/style/UseSetLiteral/UseSetLiteral.qlref b/ql/test/queries/style/UseSetLiteral/UseSetLiteral.qlref new file mode 100644 index 00000000000..d4047ebc29f --- /dev/null +++ b/ql/test/queries/style/UseSetLiteral/UseSetLiteral.qlref @@ -0,0 +1 @@ +queries/style/UseSetLiteral.ql \ No newline at end of file diff --git a/ql/test/queries/style/UseSetLiteral/test.qll b/ql/test/queries/style/UseSetLiteral/test.qll new file mode 100644 index 00000000000..36a5f938f89 --- /dev/null +++ b/ql/test/queries/style/UseSetLiteral/test.qll @@ -0,0 +1,135 @@ +import ql + +predicate test1(int a) { + a = 1 or // BAD + a = 2 or + a = 3 or + a = 4 +} + +predicate test2(int a) { + a = [1, 2, 3, 4] // GOOD +} + +predicate test3(int a) { + a = 1 and // GOOD (for the purposes of this query) + a = 2 and + a = 3 and + a = 4 +} + +bindingset[a] +predicate test4(int a) { + a < 1 or // GOOD (for the purposes of this query) + a = 2 or + a >= 3 or + a > 4 +} + +predicate test5() { + test1(1) or // BAD + test1(2) or + test1(3) or + test1(4) +} + +predicate test6() { + test1(1) or // GOOD + test2(2) or + test3(3) or + test4(4) +} + +int test7() { + 1 = result or // BAD + 2 = result or + 3 = result or + 4 = result +} + +predicate test8() { + test7() = 1 or // BAD [NOT DETECTED] + test7() = 2 or + test7() = 3 or + test7() = 4 +} + +class MyTest8Class extends int { + string s; + + MyTest8Class() { + ( + this = 1 or // BAD + this = 2 or + this = 3 or + this = 4 + ) and + ( + s = "1" or // BAD + s = "2" or + s = "3" or + s = "4" + ) and + exists(float f | + f = 1.0 or // BAD + f = 1.5 or + f = 2.0 or + f = 2.5 + ) + } + + predicate is(int x) { x = this } + + int get() { result = this } +} + +predicate test9(MyTest8Class c) { + c.is(1) or // BAD + c.is(2) or + c.is(3) or + c.is(4) +} + +predicate test10(MyTest8Class c) { + c.get() = 1 or // BAD [NOT DETECTED] + c.get() = 2 or + c.get() = 3 or + c.get() = 4 +} + +bindingset[a, b, c, d] +predicate test11(int a, int b, int c, int d) { + a = 1 or // GOOD + b = 2 or + c = 3 or + d = 4 +} + +bindingset[a, b] +predicate test12(int a, int b) { + a = 1 or // BAD [NOT DETECTED] + a = 2 or + a = 3 or + a = 4 or + b = 0 +} + +predicate test13(int a, int b) { + a = 1 and b = 1 // GOOD + or + a = 2 and b = 4 + or + a = 3 and b = 9 + or + a = 4 and b = 16 +} + +predicate test14(int a) { + a = 1 // BAD + or + ( + (a = 2 or a = 3) + or + a = 4 + ) +} diff --git a/tools/qltest.cmd b/tools/qltest.cmd index 374810e3804..2573d4f929e 100644 --- a/tools/qltest.cmd +++ b/tools/qltest.cmd @@ -4,6 +4,8 @@ type NUL && "%CODEQL_DIST%\codeql.exe" database index-files ^ --prune=**/*.testproj ^ --include-extension=.ql ^ --include-extension=.qll ^ + --include-extension=.dbscheme ^ + --include-extension=.yml ^ --size-limit=5m ^ --language=ql ^ "%CODEQL_EXTRACTOR_QL_WIP_DATABASE%" diff --git a/tools/qltest.sh b/tools/qltest.sh index 19547bfa5df..3712b2a5a10 100755 --- a/tools/qltest.sh +++ b/tools/qltest.sh @@ -6,6 +6,8 @@ exec "${CODEQL_DIST}/codeql" database index-files \ --prune="**/*.testproj" \ --include-extension=.ql \ --include-extension=.qll \ + --include-extension=.dbscheme \ + --include-extension=.yml \ --size-limit=5m \ --language=ql \ --working-dir=.\