mirror of
https://github.com/github/codeql.git
synced 2026-05-04 21:25:44 +02:00
Merge branch 'main' into redsun82/rust-derive-macro-expansion
This commit is contained in:
@@ -62,6 +62,7 @@ pub struct Config {
|
||||
pub qltest: bool,
|
||||
pub qltest_cargo_check: bool,
|
||||
pub qltest_dependencies: Vec<String>,
|
||||
pub qltest_use_nightly: bool,
|
||||
pub sysroot: Option<PathBuf>,
|
||||
pub sysroot_src: Option<PathBuf>,
|
||||
pub rustc_src: Option<PathBuf>,
|
||||
|
||||
@@ -103,6 +103,7 @@ impl<'a> Extractor<'a> {
|
||||
}
|
||||
}
|
||||
translator.emit_source_file(&ast);
|
||||
translator.emit_truncated_diagnostics_message();
|
||||
translator.trap.commit().unwrap_or_else(|err| {
|
||||
error!(
|
||||
"Failed to write trap file for: {}: {}",
|
||||
|
||||
@@ -8,6 +8,9 @@ use std::path::Path;
|
||||
use std::process::Command;
|
||||
use tracing::info;
|
||||
|
||||
const EDITION: &str = "2021";
|
||||
const NIGHTLY: &str = "nightly-2025-06-01";
|
||||
|
||||
fn dump_lib() -> anyhow::Result<()> {
|
||||
let path_iterator = glob("*.rs").context("globbing test sources")?;
|
||||
let paths = path_iterator
|
||||
@@ -29,8 +32,11 @@ enum TestCargoManifest<'a> {
|
||||
uses_proc_macro: bool,
|
||||
uses_main: bool,
|
||||
dependencies: &'a [String],
|
||||
edition: &'a str,
|
||||
},
|
||||
Macro {
|
||||
edition: &'a str,
|
||||
},
|
||||
Macro {},
|
||||
}
|
||||
|
||||
impl TestCargoManifest<'_> {
|
||||
@@ -56,16 +62,26 @@ fn dump_cargo_manifest(dependencies: &[String]) -> anyhow::Result<()> {
|
||||
uses_proc_macro,
|
||||
uses_main: fs::exists("main.rs").context("checking existence of main.rs")?,
|
||||
dependencies,
|
||||
edition: EDITION,
|
||||
};
|
||||
if uses_proc_macro {
|
||||
TestCargoManifest::Workspace {}.dump("")?;
|
||||
lib_manifest.dump(".lib")?;
|
||||
TestCargoManifest::Macro {}.dump(".proc_macro")
|
||||
TestCargoManifest::Macro { edition: EDITION }.dump(".proc_macro")
|
||||
} else {
|
||||
lib_manifest.dump("")
|
||||
}
|
||||
}
|
||||
|
||||
fn dump_nightly_toolchain() -> anyhow::Result<()> {
|
||||
fs::write(
|
||||
"rust-toolchain.toml",
|
||||
format!("[toolchain]\nchannel = \"{NIGHTLY}\"\n"),
|
||||
)
|
||||
.context("writing rust-toolchain.toml")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_sources(config: &mut Config) -> anyhow::Result<()> {
|
||||
let path_iterator = glob("**/*.rs").context("globbing test sources")?;
|
||||
config.inputs = path_iterator
|
||||
@@ -79,6 +95,9 @@ pub(crate) fn prepare(config: &mut Config) -> anyhow::Result<()> {
|
||||
dump_lib()?;
|
||||
set_sources(config)?;
|
||||
dump_cargo_manifest(&config.qltest_dependencies)?;
|
||||
if config.qltest_use_nightly {
|
||||
dump_nightly_toolchain()?;
|
||||
}
|
||||
if config.qltest_cargo_check {
|
||||
let status = Command::new("cargo")
|
||||
.env("RUSTFLAGS", "-Awarnings")
|
||||
|
||||
@@ -11,7 +11,7 @@ members = [".lib", ".proc_macro"]
|
||||
[package]
|
||||
name = "test"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
edition = "{{ edition }}"
|
||||
[lib]
|
||||
path = "{{#uses_proc_macro}}../{{/uses_proc_macro}}lib.rs"
|
||||
{{#uses_main}}
|
||||
@@ -32,7 +32,7 @@ proc_macro = { path = "../.proc_macro" }
|
||||
[package]
|
||||
name = "proc_macro"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
edition = "{{ edition }}"
|
||||
[lib]
|
||||
path = "../proc_macro.rs"
|
||||
proc_macro = true
|
||||
|
||||
@@ -26,12 +26,38 @@ use ra_ap_syntax::{
|
||||
macro_rules! pre_emit {
|
||||
(Item, $self:ident, $node:ident) => {
|
||||
if let Some(label) = $self.prepare_item_expansion($node) {
|
||||
return Some(label);
|
||||
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());
|
||||
}
|
||||
};
|
||||
($($_:tt)*) => {};
|
||||
}
|
||||
|
||||
// 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 {
|
||||
// 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
|
||||
// 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 {
|
||||
// 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 {
|
||||
(MacroCall, $self:ident, $node:ident, $label:ident) => {
|
||||
@@ -65,6 +91,18 @@ macro_rules! post_emit {
|
||||
(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());
|
||||
@@ -126,11 +164,14 @@ pub struct Translator<'a> {
|
||||
resolve_paths: bool,
|
||||
source_kind: SourceKind,
|
||||
macro_context_depth: usize,
|
||||
diagnostic_count: usize,
|
||||
}
|
||||
|
||||
const UNKNOWN_LOCATION: (LineCol, LineCol) =
|
||||
(LineCol { line: 0, col: 0 }, LineCol { line: 0, col: 0 });
|
||||
|
||||
const DIAGNOSTIC_LIMIT_PER_FILE: usize = 100;
|
||||
|
||||
impl<'a> Translator<'a> {
|
||||
pub fn new(
|
||||
trap: TrapFile,
|
||||
@@ -151,6 +192,7 @@ impl<'a> Translator<'a> {
|
||||
resolve_paths: resolve_paths == ResolvePaths::Yes,
|
||||
source_kind,
|
||||
macro_context_depth: 0,
|
||||
diagnostic_count: 0,
|
||||
}
|
||||
}
|
||||
fn location(&self, range: TextRange) -> Option<(LineCol, LineCol)> {
|
||||
@@ -237,6 +279,36 @@ impl<'a> Translator<'a> {
|
||||
} else {
|
||||
severity
|
||||
};
|
||||
if severity > DiagnosticSeverity::Debug {
|
||||
self.diagnostic_count += 1;
|
||||
if self.diagnostic_count > DIAGNOSTIC_LIMIT_PER_FILE {
|
||||
return;
|
||||
}
|
||||
}
|
||||
self.emit_diagnostic_unchecked(severity, tag, message, full_message, location);
|
||||
}
|
||||
pub fn emit_truncated_diagnostics_message(&mut self) {
|
||||
if self.diagnostic_count > DIAGNOSTIC_LIMIT_PER_FILE {
|
||||
let count = self.diagnostic_count - DIAGNOSTIC_LIMIT_PER_FILE;
|
||||
self.emit_diagnostic_unchecked(
|
||||
DiagnosticSeverity::Warning,
|
||||
"diagnostics".to_owned(),
|
||||
"Too many diagnostic messages".to_owned(),
|
||||
format!(
|
||||
"Too many diagnostic messages, {count} diagnostic messages were suppressed"
|
||||
),
|
||||
UNKNOWN_LOCATION,
|
||||
);
|
||||
}
|
||||
}
|
||||
fn emit_diagnostic_unchecked(
|
||||
&mut self,
|
||||
severity: DiagnosticSeverity,
|
||||
tag: String,
|
||||
message: String,
|
||||
full_message: String,
|
||||
location: (LineCol, LineCol),
|
||||
) {
|
||||
let (start, end) = location;
|
||||
dispatch_to_tracing!(
|
||||
severity,
|
||||
@@ -716,10 +788,21 @@ impl<'a> Translator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_attribute_macro_target(&self, node: &ast::Item) -> bool {
|
||||
// rust-analyzer considers as an `attr_macro_call` also a plain macro call, but we want to
|
||||
// process that differently (in `extract_macro_call_expanded`)
|
||||
!matches!(node, ast::Item::MacroCall(_))
|
||||
&& self.semantics.is_some_and(|semantics| {
|
||||
let file = semantics.hir_file_for(node.syntax());
|
||||
let node = InFile::new(file, node);
|
||||
semantics.is_attr_macro_call(node)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn prepare_item_expansion(
|
||||
&mut self,
|
||||
node: &ast::Item,
|
||||
) -> Option<Label<generated::Item>> {
|
||||
) -> Option<Label<generated::MacroCall>> {
|
||||
if self.source_kind == SourceKind::Library {
|
||||
// if the item expands via an attribute macro, we want to only emit the expansion
|
||||
if let Some(expanded) = self.emit_attribute_macro_expansion(node) {
|
||||
@@ -736,13 +819,10 @@ impl<'a> Translator<'a> {
|
||||
expanded.into(),
|
||||
&mut self.trap.writer,
|
||||
);
|
||||
return Some(label.into());
|
||||
return Some(label);
|
||||
}
|
||||
}
|
||||
let semantics = self.semantics.as_ref()?;
|
||||
let file = semantics.hir_file_for(node.syntax());
|
||||
let node = InFile::new(file, node);
|
||||
if semantics.is_attr_macro_call(node) {
|
||||
if self.is_attribute_macro_target(node) {
|
||||
self.macro_context_depth += 1;
|
||||
}
|
||||
None
|
||||
@@ -785,10 +865,7 @@ impl<'a> Translator<'a> {
|
||||
&mut self,
|
||||
node: &ast::Item,
|
||||
) -> Option<Label<generated::MacroItems>> {
|
||||
let semantics = self.semantics?;
|
||||
let file = semantics.hir_file_for(node.syntax());
|
||||
let infile_node = InFile::new(file, node);
|
||||
if !semantics.is_attr_macro_call(infile_node) {
|
||||
if !self.is_attribute_macro_target(node) {
|
||||
return None;
|
||||
}
|
||||
self.macro_context_depth -= 1;
|
||||
@@ -796,7 +873,7 @@ impl<'a> Translator<'a> {
|
||||
// only expand the outermost attribute macro
|
||||
return None;
|
||||
}
|
||||
let expansion = semantics.expand_attr_macro(node)?;
|
||||
let expansion = self.semantics?.expand_attr_macro(node)?;
|
||||
self.process_item_macro_expansion(node, expansion)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user