diff --git a/unified/extractor/src/languages/mod.rs b/unified/extractor/src/languages/mod.rs index 032bc884ca3..c79806dc9d4 100644 --- a/unified/extractor/src/languages/mod.rs +++ b/unified/extractor/src/languages/mod.rs @@ -4,23 +4,13 @@ use codeql_extractor::extractor::desugaring; mod swift; /// swift-syntax JSON -> `yeast::Ast` adapter for the Swift front-end. -/// -/// Currently exercised by tests and the forthcoming runtime extraction path; -/// `allow(dead_code)` because this is a binary crate, so its public API isn't -/// counted as used until the binary itself calls it. #[path = "swift/adapter.rs"] -#[allow(dead_code)] pub mod swift_adapter; /// Swift front-end parser: shells out to `swift-syntax-parse` and adapts its -/// JSON output via [`swift_adapter`]. -/// -/// Dormant for now: the runtime Swift front-end is still tree-sitter, so -/// nothing in the binary calls this yet. `allow(dead_code)` for the same -/// binary-crate reason as [`swift_adapter`]; both allows are removed once the -/// runtime switches the Swift front-end to swift-syntax. +/// JSON output via [`swift_adapter`]. This is the live Swift front-end used by +/// [`all_language_specs`]. #[path = "swift/parse.rs"] -#[allow(dead_code)] pub mod swift_parse; /// Shared YEAST output AST schema for all languages. diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 8349214e304..32252f8a022 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -1155,16 +1155,15 @@ fn translation_rules() -> Vec> { } pub fn language_spec(desugared_ast_schema: &'static str) -> desugaring::LanguageSpec { - let ts_language: tree_sitter::Language = tree_sitter_swift::LANGUAGE.into(); let config = DesugaringConfig::::new() .add_phase("translate", PhaseKind::OneShot, translation_rules()) .with_output_node_types_yaml(desugared_ast_schema); - let desugarer = ConcreteDesugarer::new(ts_language.clone(), config) - .expect("failed to build Swift desugarer"); + let desugarer = + ConcreteDesugarer::without_language(config).expect("failed to build Swift desugarer"); desugaring::LanguageSpec { prefix: "swift", - parser: Box::new(codeql_extractor::extractor::tree_sitter_parser(ts_language)), - node_types: tree_sitter_swift::NODE_TYPES, + parser: Box::new(super::swift_parse::parse), + node_types: "", file_globs: vec!["*.swift".into(), "*.swiftinterface".into()], desugarer: Box::new(desugarer), } diff --git a/unified/extractor/tests/corpus_tests.rs b/unified/extractor/tests/corpus_tests.rs index d192b19485e..66374e56526 100644 --- a/unified/extractor/tests/corpus_tests.rs +++ b/unified/extractor/tests/corpus_tests.rs @@ -20,6 +20,14 @@ fn update_mode_enabled() -> bool { .unwrap_or(false) } +/// Whether the external swift-syntax parser is available. When it is not (e.g. +/// no Swift toolchain / the `swift-syntax-parse` binary is not on `PATH` and +/// `CODEQL_EXTRACTOR_UNIFIED_SWIFT_SYNTAX_PARSE` is unset), the corpus test is +/// skipped rather than failed — it cannot run without the Swift-backed parser. +fn parser_available() -> bool { + languages::swift_parse::parse(b"").is_ok() +} + /// Parse a corpus `.output` file. The file holds a single test case made of /// three sections separated by `---` delimiter lines: /// @@ -28,7 +36,7 @@ fn update_mode_enabled() -> bool { /// /// --- /// -/// +/// /// /// --- /// @@ -98,6 +106,14 @@ fn collect_corpus_stems(dir: &Path, out: &mut Vec) { #[test] fn test_corpus() { + if !parser_available() { + eprintln!( + "skipping test_corpus: the swift-syntax parser is unavailable \ + (set CODEQL_EXTRACTOR_UNIFIED_SWIFT_SYNTAX_PARSE or put \ + `swift-syntax-parse` on PATH)" + ); + return; + } let update_mode = update_mode_enabled(); let all_languages = languages::all_language_specs(); let corpus_dir = Path::new("tests/corpus");