mirror of
https://github.com/github/codeql.git
synced 2026-02-20 00:43:44 +01:00
Address review comments
This commit is contained in:
@@ -26,8 +26,8 @@ impl Extractor {
|
||||
.expect("Failed to parse file");
|
||||
let mut visitor = Visitor {
|
||||
source: &source,
|
||||
program: vec![Fact::Comment(format!(
|
||||
"Auto-generated FACT file for {}, generated by the cool kids",
|
||||
trap_output: vec![TrapEntry::Comment(format!(
|
||||
"Auto-generated TRAP file for {}",
|
||||
path.display()
|
||||
))],
|
||||
counter: -1,
|
||||
@@ -40,7 +40,7 @@ impl Extractor {
|
||||
traverse(&tree, &mut visitor);
|
||||
|
||||
&self.parser.reset();
|
||||
Ok(Program(visitor.program))
|
||||
Ok(Program(visitor.trap_output))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,13 +65,24 @@ fn build_union_type_lookup<'a>(schema: &'a Vec<Entry>) -> Map<&'a TypeName, &'a
|
||||
}
|
||||
|
||||
struct Visitor<'a> {
|
||||
source: &'a Vec<u8>,
|
||||
program: Vec<Fact>,
|
||||
counter: i32,
|
||||
/// The file path of the source code (as string)
|
||||
path: String,
|
||||
stack: Vec<Vec<(Option<&'static str>, Id, TypeName)>>,
|
||||
/// The source code as a UTF-8 byte array
|
||||
source: &'a Vec<u8>,
|
||||
/// The accumulated trap entries
|
||||
trap_output: Vec<TrapEntry>,
|
||||
/// A counter for generating fresh labels
|
||||
counter: i32,
|
||||
/// A lookup table from type name to dbscheme table entries
|
||||
tables: Map<&'a TypeName, &'a Entry>,
|
||||
/// A lookup table for union types mapping a type name to its direct members
|
||||
union_types: Map<&'a TypeName, &'a Set<TypeName>>,
|
||||
/// A stack for gathering information from hild nodes. Whenever a node is entered
|
||||
/// an empty list is pushed. All children append their data (field name, label, type) to
|
||||
/// the the list. When the visitor leaves a node the list containing the child data is popped
|
||||
/// from the stack and matched against the dbscheme for the node. If the expectations are met
|
||||
/// the corresponding row definitions are added to the trap_output.
|
||||
stack: Vec<Vec<(Option<&'static str>, Label, TypeName)>>,
|
||||
}
|
||||
|
||||
impl Visitor<'_> {
|
||||
@@ -113,11 +124,11 @@ impl Visitor<'_> {
|
||||
});
|
||||
if let Some(Entry::Table { fields, .. }) = table {
|
||||
self.counter += 1;
|
||||
let id = Id(self.counter);
|
||||
let loc = Loc(self.counter);
|
||||
self.program.push(Fact::New(Arg::IdArg(id)));
|
||||
self.program.push(Fact::New(Arg::LocArg(loc)));
|
||||
self.program.push(location_for(&self.path, loc, node));
|
||||
let id = Label::Normal(self.counter);
|
||||
let loc = Label::Location(self.counter);
|
||||
self.trap_output.push(TrapEntry::New(id));
|
||||
self.trap_output.push(TrapEntry::New(loc));
|
||||
self.trap_output.push(location_for(&self.path, loc, node));
|
||||
let table_name = node_type_name(node.kind(), node.is_named());
|
||||
let args: Option<Vec<Arg>>;
|
||||
if fields.is_empty() {
|
||||
@@ -126,8 +137,8 @@ impl Visitor<'_> {
|
||||
args = self.complex_node(&node, fields, child_nodes, id);
|
||||
}
|
||||
if let Some(args) = args {
|
||||
self.program
|
||||
.push(Fact::Definition(table_name, id, args, loc));
|
||||
self.trap_output
|
||||
.push(TrapEntry::Definition(table_name, id, args, loc));
|
||||
}
|
||||
if let Some(parent) = self.stack.last_mut() {
|
||||
parent.push((
|
||||
@@ -152,10 +163,10 @@ impl Visitor<'_> {
|
||||
&mut self,
|
||||
node: &Node,
|
||||
fields: &Vec<Field>,
|
||||
child_nodes: Vec<(Option<&str>, Id, TypeName)>,
|
||||
parent_id: Id,
|
||||
child_nodes: Vec<(Option<&str>, Label, TypeName)>,
|
||||
parent_id: Label,
|
||||
) -> Option<Vec<Arg>> {
|
||||
let mut map: Map<&Option<String>, (&Field, Vec<Id>)> = std::collections::BTreeMap::new();
|
||||
let mut map: Map<&Option<String>, (&Field, Vec<Label>)> = std::collections::BTreeMap::new();
|
||||
for field in fields {
|
||||
map.insert(&field.name, (field, Vec::new()));
|
||||
}
|
||||
@@ -195,7 +206,7 @@ impl Visitor<'_> {
|
||||
match &field.storage {
|
||||
Storage::Column => {
|
||||
if child_ids.len() == 1 {
|
||||
args.push(Arg::IdArg(*child_ids.first().unwrap()));
|
||||
args.push(Arg::Label(*child_ids.first().unwrap()));
|
||||
} else {
|
||||
is_valid = false;
|
||||
println!(
|
||||
@@ -217,7 +228,7 @@ impl Visitor<'_> {
|
||||
}
|
||||
Storage::Table { parent, index } => {
|
||||
for child_id in child_ids {
|
||||
self.program.push(Fact::ChildOf(
|
||||
self.trap_output.push(TrapEntry::ChildOf(
|
||||
node_type_name(&parent.kind, parent.named),
|
||||
parent_id,
|
||||
match &field.name {
|
||||
@@ -255,24 +266,24 @@ impl Visitor<'_> {
|
||||
// Emit a slice of a source file as an Arg.
|
||||
fn sliced_source_arg(source: &Vec<u8>, n: Node) -> Arg {
|
||||
let range = n.byte_range();
|
||||
Arg::StringArg(String::from(
|
||||
Arg::String(String::from(
|
||||
std::str::from_utf8(&source[range.start..range.end]).expect("Failed to decode string"),
|
||||
))
|
||||
}
|
||||
|
||||
// Emit a 'Located' fact for the provided node, appropriately calibrated.
|
||||
fn location_for<'a>(fp: &String, ident: Loc, n: Node) -> Fact {
|
||||
// Emit a 'Located' TrapEntry for the provided node, appropriately calibrated.
|
||||
fn location_for<'a>(fp: &String, label: Label, n: Node) -> TrapEntry {
|
||||
let start_line = n.start_position().row;
|
||||
let start_col = n.start_position().column;
|
||||
let end_line = n.end_position().row;
|
||||
let end_col = n.end_position().column;
|
||||
Fact::Located(vec![
|
||||
Arg::LocArg(ident),
|
||||
Arg::StringArg(fp.to_owned()),
|
||||
Arg::IntArg(start_line),
|
||||
Arg::IntArg(start_col),
|
||||
Arg::IntArg(end_line),
|
||||
Arg::IntArg(end_col),
|
||||
TrapEntry::Located(vec![
|
||||
Arg::Label(label),
|
||||
Arg::String(fp.to_owned()),
|
||||
Arg::Int(start_line),
|
||||
Arg::Int(start_col),
|
||||
Arg::Int(end_line),
|
||||
Arg::Int(end_col),
|
||||
])
|
||||
}
|
||||
|
||||
@@ -296,34 +307,35 @@ fn traverse(tree: &Tree, visitor: &mut Visitor) {
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct Program(Vec<Fact>);
|
||||
|
||||
pub struct Program(Vec<TrapEntry>);
|
||||
|
||||
impl fmt::Display for Program {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let mut text = String::new();
|
||||
for fact in &self.0 {
|
||||
text.push_str(&format!("{}\n", fact));
|
||||
for trap_entry in &self.0 {
|
||||
text.push_str(&format!("{}\n", trap_entry));
|
||||
}
|
||||
write!(f, "{}", text)
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Fact {
|
||||
|
||||
enum TrapEntry {
|
||||
// @id = *@
|
||||
New(Arg),
|
||||
New(Label),
|
||||
// @node_def(self, arg?, location)@
|
||||
Definition(String, Id, Vec<Arg>, Loc),
|
||||
Definition(String, Label, Vec<Arg>, Label),
|
||||
// @node_child(self, index, parent)@
|
||||
ChildOf(String, Id, String, Index, Id),
|
||||
ChildOf(String, Label, String, Index, Label),
|
||||
// @location(loc, path, r1, c1, r2, c2)
|
||||
Located(Vec<Arg>),
|
||||
Comment(String),
|
||||
}
|
||||
impl fmt::Display for Fact {
|
||||
impl fmt::Display for TrapEntry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Fact::New(id) => write!(f, "{} = *", id),
|
||||
Fact::Definition(n, id, args, loc) => {
|
||||
TrapEntry::New(id) => write!(f, "{} = *", id),
|
||||
TrapEntry::Definition(n, id, args, loc) => {
|
||||
let mut args_str = String::new();
|
||||
for arg in args {
|
||||
args_str.push_str(&format!("{}, ", arg));
|
||||
@@ -337,7 +349,7 @@ impl fmt::Display for Fact {
|
||||
loc
|
||||
)
|
||||
}
|
||||
Fact::ChildOf(pname, id, fname, idx, p) => write!(
|
||||
TrapEntry::ChildOf(pname, id, fname, idx, p) => write!(
|
||||
f,
|
||||
"{}({}, {}, {})",
|
||||
escape_name(&format!("{}_{}", &pname, &fname)),
|
||||
@@ -345,7 +357,7 @@ impl fmt::Display for Fact {
|
||||
idx,
|
||||
p
|
||||
),
|
||||
Fact::Located(args) => write!(
|
||||
TrapEntry::Located(args) => write!(
|
||||
f,
|
||||
"location({}, {}, {}, {}, {}, {})",
|
||||
args.get(0).unwrap(),
|
||||
@@ -355,28 +367,28 @@ impl fmt::Display for Fact {
|
||||
args.get(4).unwrap(),
|
||||
args.get(5).unwrap(),
|
||||
),
|
||||
Fact::Comment(line) => write!(f, "// {}", line),
|
||||
TrapEntry::Comment(line) => write!(f, "// {}", line),
|
||||
}
|
||||
}
|
||||
}
|
||||
// Identifiers of the form #0, #1...
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Id(i32);
|
||||
|
||||
impl fmt::Display for Id {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
enum Label {
|
||||
// Identifiers of the form #0, #1...
|
||||
Normal(i32), // #0, #1, etc.
|
||||
// Location identifiers of the form #0_loc, #1_loc...
|
||||
Location(i32), // #0_loc, #1_loc, etc.
|
||||
}
|
||||
|
||||
impl fmt::Display for Label {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "#{}", self.0)
|
||||
match self {
|
||||
Label::Normal(x) => write!(f, "#{}", x),
|
||||
Label::Location(x) => write!(f, "#{}_loc", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
// Locative identifiers of the form #0_loc, #1_loc...
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Loc(i32);
|
||||
|
||||
impl fmt::Display for Loc {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "#{}_loc", self.0)
|
||||
}
|
||||
}
|
||||
// Numeric indices.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct Index(usize);
|
||||
@@ -387,22 +399,20 @@ impl fmt::Display for Index {
|
||||
}
|
||||
}
|
||||
|
||||
// Some untyped argument to a fact.
|
||||
// Some untyped argument to a TrapEntry.
|
||||
#[derive(Debug)]
|
||||
enum Arg {
|
||||
IntArg(usize),
|
||||
StringArg(String),
|
||||
IdArg(Id),
|
||||
LocArg(Loc),
|
||||
Label(Label),
|
||||
Int(usize),
|
||||
String(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Arg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Arg::IntArg(x) => write!(f, "{}", x),
|
||||
Arg::StringArg(x) => write!(f, "\"{}\"", x.replace("\"", "\"\"")),
|
||||
Arg::IdArg(x) => write!(f, "{}", x),
|
||||
Arg::LocArg(x) => write!(f, "{}", x),
|
||||
Arg::Label(x) => write!(f, "{}", x),
|
||||
Arg::Int(x) => write!(f, "{}", x),
|
||||
Arg::String(x) => write!(f, "\"{}\"", x.replace("\"", "\"\"")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user