Repository: ast-grep/ast-grep (language: rust)

Issue:
support finding injected code in `run` with specified language



Discussion / hints:

Fix patch:
diff --git a/crates/cli/src/lang.rs b/crates/cli/src/lang.rs
index a06e2fac57..10f0eaa2ec 100644
--- a/crates/cli/src/lang.rs
+++ b/crates/cli/src/lang.rs
@@ -34,7 +34,7 @@ impl SgLang {
       Builtin(b) => b.file_types(),
       Custom(c) => c.file_types(),
     };
-    lang_globs::merge_types(self, default_types)
+    lang_globs::merge_globs(self, default_types)
   }
 
   // register_globs must be called after register_custom_language
@@ -61,9 +61,23 @@ impl SgLang {
     let langs = self.injectable_languages()?;
     // TODO: handle injected languages not found
     // e.g vue can inject scss which is not supported by sg
+    // we should report an error here
     let iter = langs.iter().filter_map(|s| SgLang::from_str(s).ok());
     Some(iter)
   }
+
+  pub fn augmented_file_type(&self) -> Types {
+    let self_type = self.file_types();
+    let injected_from = Self::all_langs().into_iter().filter_map(|lang| {
+      lang
+        .injectable_sg_langs()?
+        .any(|l| l == *self)
+        .then_some(lang)
+    });
+    let injected_types = injected_from.map(|lang| lang.file_types());
+    let all_types = std::iter::once(self_type).chain(injected_types);
+    lang_globs::merge_types(all_types)
+  }
 }
 
 impl Display for SgLang {
diff --git a/crates/cli/src/lang/lang_globs.rs b/crates/cli/src/lang/lang_globs.rs
index 49faca9289..945afa1fa1 100644
--- a/crates/cli/src/lang/lang_globs.rs
+++ b/crates/cli/src/lang/lang_globs.rs
@@ -58,7 +58,21 @@ fn get_types(lang: &SgLang) -> Option<&Types> {
   None
 }
 
-pub fn merge_types(lang: &SgLang, type1: Types) -> Types {
+pub fn merge_types(types_vec: impl Iterator<Item = Types>) -> Types {
+  let mut builder = TypesBuilder::new();
+  for types in types_vec {
+    for def in types.definitions() {
+      let name = def.name();
+      for glob in def.globs() {
+        builder.add(name, glob).expect(name);
+      }
+      builder.select(name);
+    }
+  }
+  builder.build().expect("file types must be valid")
+}
+
+pub fn merge_globs(lang: &SgLang, type1: Types) -> Types {
   let Some(type2) = get_types(lang) else {
     return type1;
   };
@@ -130,7 +144,7 @@ html: ['*.vue', '*.svelte']";
   fn test_merge_types() {
     let lang: SgLang = SupportLang::Rust.into();
     let default_types = lang.file_types();
-    let rust_types = merge_types(&lang, default_types);
+    let rust_types = merge_globs(&lang, default_types);
     assert!(rust_types.matched("a.php", false).is_ignore());
     assert!(rust_types.matched("a.rs", false).is_whitelist());
   }
@@ -146,7 +160,7 @@ html: ['*.vue', '*.svelte']";
     }
     let lang: SgLang = SupportLang::Html.into();
     let default_types = lang.file_types();
-    let html_types = merge_types(&lang, default_types);
+    let html_types = merge_globs(&lang, default_types);
     assert!(html_types.matched("a.php", false).is_ignore());
     assert!(html_types.matched("a.html", false).is_whitelist());
     assert!(html_types.matched("a.vue", false).is_whitelist());
diff --git a/crates/cli/src/run.rs b/crates/cli/src/run.rs
index c11f5d0351..6697637f35 100644
--- a/crates/cli/src/run.rs
+++ b/crates/cli/src/run.rs
@@ -300,7 +300,12 @@ impl<P: Printer> PathWorker for RunWithSpecificLang<P> {
     let arg = &self.arg;
     let pattern = self.pattern.clone();
     let lang = arg.lang.expect("must present");
-    filter_file_pattern(path, lang, pattern)
+    let path_lang = SgLang::from_path(path)?;
+    if path_lang == lang {
+      filter_file_pattern(path, lang, pattern)
+    } else {
+      filter_file_pattern_injection(path, path_lang, std::iter::once((lang, pattern))).map(|n| n.0)
+    }
   }
 }
 
diff --git a/crates/cli/src/utils.rs b/crates/cli/src/utils.rs
index 4b6becfd13..c3270e8876 100644
--- a/crates/cli/src/utils.rs
+++ b/crates/cli/src/utils.rs
@@ -314,7 +314,7 @@ impl InputArgs {
     NoIgnore::disregard(&self.no_ignore)
       .walk(&self.paths)
       .threads(threads)
-      .types(lang.file_types())
+      .types(lang.augmented_file_type())
       .build_parallel()
   }
 }


Test patch: