mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: refactor pre_emit! and post_emit! to a trait
This commit is contained in:
@@ -52,6 +52,32 @@ fn property_name(type_name: &str, field_name: &str) -> String {
|
||||
name.to_owned()
|
||||
}
|
||||
|
||||
fn has_special_emission(type_name: &str) -> bool {
|
||||
matches!(
|
||||
type_name,
|
||||
"Item"
|
||||
| "AssocItem"
|
||||
| "ExternItem"
|
||||
| "Meta"
|
||||
| "MacroCall"
|
||||
| "Fn"
|
||||
| "Struct"
|
||||
| "Enum"
|
||||
| "Union"
|
||||
| "Trait"
|
||||
| "Module"
|
||||
| "Variant"
|
||||
| "PathExpr"
|
||||
| "RecordExpr"
|
||||
| "PathPat"
|
||||
| "RecordPat"
|
||||
| "TupleStructPat"
|
||||
| "MethodCallExpr"
|
||||
| "PathSegment"
|
||||
| "Const"
|
||||
)
|
||||
}
|
||||
|
||||
fn to_lower_snake_case(s: &str) -> String {
|
||||
let mut buf = String::with_capacity(s.len());
|
||||
let mut prev = false;
|
||||
@@ -355,6 +381,7 @@ struct ExtractorEnumInfo {
|
||||
snake_case_name: String,
|
||||
ast_name: String,
|
||||
variants: Vec<EnumVariantInfo>,
|
||||
has_special_emission: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Default)]
|
||||
@@ -376,6 +403,7 @@ struct ExtractorNodeInfo {
|
||||
ast_name: String,
|
||||
fields: Vec<ExtractorNodeFieldInfo>,
|
||||
has_attrs: bool,
|
||||
has_special_emission: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -406,6 +434,7 @@ fn enum_to_extractor_info(node: &AstEnumSrc) -> Option<ExtractorEnumInfo> {
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
has_special_emission: has_special_emission(&node.name),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -460,6 +489,7 @@ fn node_to_extractor_info(node: &AstNodeSrc) -> ExtractorNodeInfo {
|
||||
ast_name: node.name.clone(),
|
||||
fields,
|
||||
has_attrs,
|
||||
has_special_emission: has_special_emission(&node.name),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
//! Generated by `ast-generator`, do not edit by hand.
|
||||
|
||||
use super::base::Translator;
|
||||
use super::mappings::TextValue;
|
||||
use crate::{pre_emit,post_emit};
|
||||
use super::mappings::{TextValue, HasTrapClass, Emission};
|
||||
use crate::generated;
|
||||
use crate::trap::{Label, TrapId};
|
||||
use ra_ap_syntax::ast::{
|
||||
@@ -13,29 +12,23 @@ use ra_ap_syntax::ast::{
|
||||
use ra_ap_syntax::{AstNode, ast};
|
||||
|
||||
impl Translator<'_> {
|
||||
fn emit_else_branch(&mut self, node: &ast::ElseBranch) -> Option<Label<generated::Expr>> {
|
||||
match node {
|
||||
ast::ElseBranch::IfExpr(inner) => self.emit_if_expr(inner).map(Into::into),
|
||||
ast::ElseBranch::Block(inner) => self.emit_block_expr(inner).map(Into::into),
|
||||
}
|
||||
}
|
||||
{{#enums}}
|
||||
|
||||
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
|
||||
pre_emit!({{name}}, self, node);
|
||||
{{>pre_emission}}
|
||||
let label = match node {
|
||||
{{#variants}}
|
||||
ast::{{ast_name}}::{{variant_ast_name}}(inner) => self.emit_{{snake_case_name}}(inner).map(Into::into),
|
||||
{{/variants}}
|
||||
}?;
|
||||
post_emit!({{name}}, self, node, label);
|
||||
{{>post_emission}}
|
||||
Some(label)
|
||||
}
|
||||
{{/enums}}
|
||||
{{#nodes}}
|
||||
|
||||
pub(crate) fn emit_{{snake_case_name}}(&mut self, node: &ast::{{ast_name}}) -> Option<Label<generated::{{name}}>> {
|
||||
pre_emit!({{name}}, self, node);
|
||||
{{>pre_emission}}
|
||||
{{#has_attrs}}
|
||||
if self.should_be_excluded(node) { return None; }
|
||||
{{/has_attrs}}
|
||||
@@ -65,9 +58,15 @@ impl Translator<'_> {
|
||||
{{/fields}}
|
||||
});
|
||||
self.emit_location(label, node);
|
||||
post_emit!({{name}}, self, node, label);
|
||||
{{>post_emission}}
|
||||
self.emit_tokens(node, label.into(), node.syntax().children_with_tokens());
|
||||
Some(label)
|
||||
}
|
||||
{{/nodes}}
|
||||
}
|
||||
{{#enums}}
|
||||
{{>trap_class_mapping}}
|
||||
{{/enums}}
|
||||
{{#nodes}}
|
||||
{{>trap_class_mapping}}
|
||||
{{/nodes}}
|
||||
|
||||
3
rust/ast-generator/templates/post_emission.mustache
Normal file
3
rust/ast-generator/templates/post_emission.mustache
Normal file
@@ -0,0 +1,3 @@
|
||||
{{#has_special_emission}}
|
||||
self.post_emit(node, label);
|
||||
{{/has_special_emission}}
|
||||
5
rust/ast-generator/templates/pre_emission.mustache
Normal file
5
rust/ast-generator/templates/pre_emission.mustache
Normal file
@@ -0,0 +1,5 @@
|
||||
{{#has_special_emission}}
|
||||
if let Some(label) = self.pre_emit(node) {
|
||||
return Some(label);
|
||||
}
|
||||
{{/has_special_emission}}
|
||||
6
rust/ast-generator/templates/trap_class_mapping.mustache
Normal file
6
rust/ast-generator/templates/trap_class_mapping.mustache
Normal file
@@ -0,0 +1,6 @@
|
||||
{{#has_special_emission}}
|
||||
|
||||
impl HasTrapClass for ast::{{ast_name}} {
|
||||
type TrapClass = generated::{{name}};
|
||||
}
|
||||
{{/has_special_emission}}
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::mappings::{AddressableAst, AddressableHir, PathAst};
|
||||
use super::mappings::{AddressableAst, AddressableHir, Emission, PathAst};
|
||||
use crate::generated::{self};
|
||||
use crate::rust_analyzer::FileSemanticInformation;
|
||||
use crate::trap::{DiagnosticSeverity, TrapFile, TrapId};
|
||||
@@ -22,121 +22,165 @@ use ra_ap_syntax::{
|
||||
ast,
|
||||
};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! pre_emit {
|
||||
(Item, $self:ident, $node:ident) => {
|
||||
if let Some(label) = $self.prepare_item_expansion($node) {
|
||||
return Some(label.into());
|
||||
}
|
||||
};
|
||||
(AssocItem, $self:ident, $node:ident) => {
|
||||
if let Some(label) = $self.prepare_item_expansion(&$node.clone().into()) {
|
||||
return Some(label.into());
|
||||
}
|
||||
};
|
||||
(ExternItem, $self:ident, $node:ident) => {
|
||||
if let Some(label) = $self.prepare_item_expansion(&$node.clone().into()) {
|
||||
return Some(label.into());
|
||||
}
|
||||
};
|
||||
(Meta, $self:ident, $node:ident) => {
|
||||
// rust-analyzer doesn't expand macros in this context
|
||||
$self.macro_context_depth += 1;
|
||||
};
|
||||
($($_:tt)*) => {};
|
||||
impl Emission<ast::Item> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::Item) -> Option<Label<generated::Item>> {
|
||||
self.prepare_item_expansion(node).map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::Item, label: Label<generated::Item>) {
|
||||
self.emit_item_expansion(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove the mannually written Label conversions. These can be auto-generated by
|
||||
// changing the base class of AssocItem from AstNode to Item
|
||||
impl From<crate::trap::Label<generated::AssocItem>> for crate::trap::Label<generated::Item> {
|
||||
fn from(value: crate::trap::Label<generated::AssocItem>) -> Self {
|
||||
impl Emission<ast::AssocItem> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::AssocItem) -> Option<Label<generated::AssocItem>> {
|
||||
self.prepare_item_expansion(&node.clone().into())
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::AssocItem, label: Label<generated::AssocItem>) {
|
||||
self.emit_item_expansion(&node.clone().into(), label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::ExternItem> for Translator<'_> {
|
||||
fn pre_emit(&mut self, node: &ast::ExternItem) -> Option<Label<generated::ExternItem>> {
|
||||
self.prepare_item_expansion(&node.clone().into())
|
||||
.map(Into::into)
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, node: &ast::ExternItem, label: Label<generated::ExternItem>) {
|
||||
self.emit_item_expansion(&node.clone().into(), label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Meta> for Translator<'_> {
|
||||
fn pre_emit(&mut self, _node: &ast::Meta) -> Option<Label<generated::Meta>> {
|
||||
self.macro_context_depth += 1;
|
||||
None
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, _node: &ast::Meta, _label: Label<generated::Meta>) {
|
||||
self.macro_context_depth -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Fn> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Fn, label: Label<generated::Function>) {
|
||||
self.emit_function_has_implementation(node, label);
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Struct> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Struct, label: Label<generated::Struct>) {
|
||||
self.emit_derive_expansion(node, label);
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Enum> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Enum, label: Label<generated::Enum>) {
|
||||
self.emit_derive_expansion(node, label);
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Union> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Union, label: Label<generated::Union>) {
|
||||
self.emit_derive_expansion(node, label);
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Trait> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Trait, label: Label<generated::Trait>) {
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Module> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Module, label: Label<generated::Module>) {
|
||||
self.extract_canonical_origin(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Variant> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Variant, label: Label<generated::Variant>) {
|
||||
self.extract_canonical_origin_of_enum_variant(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::PathExpr> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::PathExpr, label: Label<generated::PathExpr>) {
|
||||
self.extract_path_canonical_destination(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::RecordExpr> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::RecordExpr, label: Label<generated::StructExpr>) {
|
||||
self.extract_path_canonical_destination(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::PathPat> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::PathPat, label: Label<generated::PathPat>) {
|
||||
self.extract_path_canonical_destination(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::RecordPat> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::RecordPat, label: Label<generated::StructPat>) {
|
||||
self.extract_path_canonical_destination(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::TupleStructPat> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::TupleStructPat, label: Label<generated::TupleStructPat>) {
|
||||
self.extract_path_canonical_destination(node, label.into());
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::MethodCallExpr> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::MethodCallExpr, label: Label<generated::MethodCallExpr>) {
|
||||
self.extract_method_canonical_destination(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::PathSegment> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::PathSegment, label: Label<generated::PathSegment>) {
|
||||
self.extract_types_from_path_segment(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::Const> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::Const, label: Label<generated::Const>) {
|
||||
self.emit_const_has_implementation(node, label);
|
||||
}
|
||||
}
|
||||
|
||||
impl Emission<ast::MacroCall> for Translator<'_> {
|
||||
fn post_emit(&mut self, node: &ast::MacroCall, label: Label<generated::MacroCall>) {
|
||||
self.extract_macro_call_expanded(node, label);
|
||||
}
|
||||
}
|
||||
// TODO: remove the manually written Label conversions. These can be auto-generated by
|
||||
// ch
|
||||
// anging the base class of AssocItem from AstNode to Item
|
||||
impl From<Label<generated::AssocItem>> for Label<generated::Item> {
|
||||
fn from(value: Label<generated::AssocItem>) -> Self {
|
||||
// SAFETY: this is safe because every concrete instance of `@assoc_item` is also an instance of `@item`
|
||||
unsafe { Self::from_untyped(value.as_untyped()) }
|
||||
}
|
||||
}
|
||||
// TODO: remove the mannually written Label conversions. These can be auto-generated by
|
||||
// TODO: remove the manually written Label conversions. These can be auto-generated by
|
||||
// changing the base class of ExternItem from AstNode to Item
|
||||
impl From<crate::trap::Label<generated::ExternItem>> for crate::trap::Label<generated::Item> {
|
||||
fn from(value: crate::trap::Label<generated::ExternItem>) -> Self {
|
||||
impl From<Label<generated::ExternItem>> for Label<generated::Item> {
|
||||
fn from(value: Label<generated::ExternItem>) -> Self {
|
||||
// SAFETY: this is safe because every concrete instance of `@extern_item` is also an instance of `@item`
|
||||
unsafe { Self::from_untyped(value.as_untyped()) }
|
||||
}
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! post_emit {
|
||||
(Meta, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.macro_context_depth -= 1;
|
||||
};
|
||||
(MacroCall, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_macro_call_expanded($node, $label);
|
||||
};
|
||||
(Function, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_function_has_implementation($node, $label);
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Trait, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Struct, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_derive_expansion($node, $label);
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Enum, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_derive_expansion($node, $label);
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Union, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_derive_expansion($node, $label);
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Module, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_canonical_origin($node, $label.into());
|
||||
};
|
||||
(Variant, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_canonical_origin_of_enum_variant($node, $label);
|
||||
};
|
||||
(Item, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_item_expansion($node, $label);
|
||||
};
|
||||
(AssocItem, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_item_expansion(
|
||||
&$node.clone().into(),
|
||||
From::<Label<generated::AssocItem>>::from($label),
|
||||
);
|
||||
};
|
||||
(ExternItem, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_item_expansion(
|
||||
&$node.clone().into(),
|
||||
From::<Label<generated::ExternItem>>::from($label),
|
||||
);
|
||||
};
|
||||
// TODO canonical origin of other items
|
||||
(PathExpr, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_path_canonical_destination($node, $label.into());
|
||||
};
|
||||
(StructExpr, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_path_canonical_destination($node, $label.into());
|
||||
};
|
||||
(PathPat, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_path_canonical_destination($node, $label.into());
|
||||
};
|
||||
(StructPat, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_path_canonical_destination($node, $label.into());
|
||||
};
|
||||
(TupleStructPat, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_path_canonical_destination($node, $label.into());
|
||||
};
|
||||
(MethodCallExpr, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_method_canonical_destination($node, $label);
|
||||
};
|
||||
(PathSegment, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.extract_types_from_path_segment($node, $label.into());
|
||||
};
|
||||
(Const, $self:ident, $node:ident, $label:ident) => {
|
||||
$self.emit_const_has_implementation($node, $label);
|
||||
};
|
||||
($($_:tt)*) => {};
|
||||
}
|
||||
|
||||
// see https://github.com/tokio-rs/tracing/issues/2730
|
||||
macro_rules! dispatch_to_tracing {
|
||||
@@ -497,6 +541,17 @@ impl<'a> Translator<'a> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn emit_else_branch(
|
||||
&mut self,
|
||||
node: &ast::ElseBranch,
|
||||
) -> Option<Label<generated::Expr>> {
|
||||
match node {
|
||||
ast::ElseBranch::IfExpr(inner) => self.emit_if_expr(inner).map(Into::into),
|
||||
ast::ElseBranch::Block(inner) => self.emit_block_expr(inner).map(Into::into),
|
||||
}
|
||||
}
|
||||
|
||||
fn canonical_path_from_type(&self, ty: Type) -> Option<String> {
|
||||
let sema = self.semantics.as_ref().unwrap();
|
||||
// rust-analyzer doesn't provide a type enum directly
|
||||
|
||||
483
rust/extractor/src/translate/generated.rs
generated
483
rust/extractor/src/translate/generated.rs
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,20 @@
|
||||
use crate::trap::{Label, TrapClass};
|
||||
use ra_ap_hir::{Enum, Function, HasContainer, Module, Semantics, Struct, Trait, Union};
|
||||
use ra_ap_ide_db::RootDatabase;
|
||||
use ra_ap_syntax::{AstNode, ast, ast::RangeItem};
|
||||
|
||||
pub(crate) trait HasTrapClass: AstNode {
|
||||
type TrapClass: TrapClass;
|
||||
}
|
||||
|
||||
pub(crate) trait Emission<T: HasTrapClass> {
|
||||
fn pre_emit(&mut self, _node: &T) -> Option<Label<T::TrapClass>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn post_emit(&mut self, _node: &T, _label: Label<T::TrapClass>) {}
|
||||
}
|
||||
|
||||
pub(crate) trait TextValue {
|
||||
fn try_get_text(&self) -> Option<String>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user