feat: establish first-class lexical language parity #2
8 changed files with 201 additions and 0 deletions
test(scan): add first-class language fixtures
commit
1935710459
|
|
@ -49,6 +49,11 @@ fixtures for:
|
||||||
- duplicate symbols, nested scopes, strings, comments, and unsupported syntax;
|
- duplicate symbols, nested scopes, strings, comments, and unsupported syntax;
|
||||||
- stable graph identities and evidence under repeated scans.
|
- stable graph identities and evidence under repeated scans.
|
||||||
|
|
||||||
|
The positive baseline corpus lives in `tests/fixtures/languages`, with its
|
||||||
|
shared contract in `tests/language_parity.rs`. Gap slices should extend these
|
||||||
|
fixtures with a positive construct and its nearest clean negative before
|
||||||
|
changing extraction behavior.
|
||||||
|
|
||||||
Real-repository benchmarks supplement these fixtures but do not replace them.
|
Real-repository benchmarks supplement these fixtures but do not replace them.
|
||||||
Compare graph counts and health metrics only after confirming that analyzed
|
Compare graph counts and health metrics only after confirming that analyzed
|
||||||
files, constructs, and evidence coverage remain stable. A lower health score can
|
files, constructs, and evidence coverage remain stable. A lower health score can
|
||||||
|
|
|
||||||
13
tests/fixtures/languages/c/basic.c
vendored
Normal file
13
tests/fixtures/languages/c/basic.c
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "support.h"
|
||||||
|
|
||||||
|
struct Worker {
|
||||||
|
int state;
|
||||||
|
};
|
||||||
|
|
||||||
|
int start() {
|
||||||
|
return helper();
|
||||||
|
}
|
||||||
|
|
||||||
|
int helper() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
12
tests/fixtures/languages/cpp/basic.cpp
vendored
Normal file
12
tests/fixtures/languages/cpp/basic.cpp
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "support.hpp"
|
||||||
|
|
||||||
|
class Worker : public Base {
|
||||||
|
public:
|
||||||
|
void start() {
|
||||||
|
helper();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int helper() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
tests/fixtures/languages/dart/basic.dart
vendored
Normal file
9
tests/fixtures/languages/dart/basic.dart
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import 'package:example/base.dart';
|
||||||
|
|
||||||
|
class Controller extends Base {
|
||||||
|
void start() {
|
||||||
|
helper();
|
||||||
|
}
|
||||||
|
|
||||||
|
void helper() {}
|
||||||
|
}
|
||||||
9
tests/fixtures/languages/javascript/basic.js
vendored
Normal file
9
tests/fixtures/languages/javascript/basic.js
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Base } from './base.js';
|
||||||
|
|
||||||
|
class Worker extends Base {}
|
||||||
|
|
||||||
|
function start() {
|
||||||
|
helper();
|
||||||
|
}
|
||||||
|
|
||||||
|
function helper() {}
|
||||||
9
tests/fixtures/languages/rust/basic.rs
vendored
Normal file
9
tests/fixtures/languages/rust/basic.rs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
use crate::support::Dependency;
|
||||||
|
|
||||||
|
pub struct Worker;
|
||||||
|
|
||||||
|
pub fn start() {
|
||||||
|
helper();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn helper() {}
|
||||||
9
tests/fixtures/languages/typescript/basic.ts
vendored
Normal file
9
tests/fixtures/languages/typescript/basic.ts
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Base } from './base.js';
|
||||||
|
|
||||||
|
class Worker extends Base {}
|
||||||
|
|
||||||
|
function start(): void {
|
||||||
|
helper();
|
||||||
|
}
|
||||||
|
|
||||||
|
function helper(): void {}
|
||||||
135
tests/language_parity.rs
Normal file
135
tests/language_parity.rs
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
use brick::model::{EdgeKind, NodeKind};
|
||||||
|
use brick::scan::scan;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
struct FixtureCase {
|
||||||
|
directory: &'static str,
|
||||||
|
language: &'static str,
|
||||||
|
classes: &'static [&'static str],
|
||||||
|
functions: &'static [&'static str],
|
||||||
|
imports: usize,
|
||||||
|
inherits: usize,
|
||||||
|
calls: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn first_class_language_fixtures_have_stable_baseline_evidence() {
|
||||||
|
let cases = [
|
||||||
|
FixtureCase {
|
||||||
|
directory: "dart",
|
||||||
|
language: "dart",
|
||||||
|
classes: &["Controller"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 1,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
FixtureCase {
|
||||||
|
directory: "rust",
|
||||||
|
language: "rust",
|
||||||
|
classes: &["Worker"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 0,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
FixtureCase {
|
||||||
|
directory: "c",
|
||||||
|
language: "cpp",
|
||||||
|
classes: &["Worker"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 0,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
FixtureCase {
|
||||||
|
directory: "cpp",
|
||||||
|
language: "cpp",
|
||||||
|
classes: &["Worker"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 1,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
FixtureCase {
|
||||||
|
directory: "javascript",
|
||||||
|
language: "javascript",
|
||||||
|
classes: &["Worker"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 1,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
FixtureCase {
|
||||||
|
directory: "typescript",
|
||||||
|
language: "typescript",
|
||||||
|
classes: &["Worker"],
|
||||||
|
functions: &["helper", "start"],
|
||||||
|
imports: 1,
|
||||||
|
inherits: 1,
|
||||||
|
calls: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for case in cases {
|
||||||
|
assert_fixture(case);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_fixture(case: FixtureCase) {
|
||||||
|
let root = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("tests/fixtures/languages")
|
||||||
|
.join(case.directory);
|
||||||
|
let building = scan(&root).unwrap();
|
||||||
|
let mut classes: Vec<_> = building
|
||||||
|
.nodes
|
||||||
|
.iter()
|
||||||
|
.filter(|node| {
|
||||||
|
node.language.as_deref() == Some(case.language) && node.kind == NodeKind::Class
|
||||||
|
})
|
||||||
|
.map(|node| node.name.as_str())
|
||||||
|
.collect();
|
||||||
|
let mut functions: Vec<_> = building
|
||||||
|
.nodes
|
||||||
|
.iter()
|
||||||
|
.filter(|node| {
|
||||||
|
node.language.as_deref() == Some(case.language) && node.kind == NodeKind::Function
|
||||||
|
})
|
||||||
|
.map(|node| node.name.as_str())
|
||||||
|
.collect();
|
||||||
|
classes.sort_unstable();
|
||||||
|
functions.sort_unstable();
|
||||||
|
|
||||||
|
assert_eq!(classes, case.classes, "{} class baseline", case.directory);
|
||||||
|
assert_eq!(
|
||||||
|
functions, case.functions,
|
||||||
|
"{} function baseline",
|
||||||
|
case.directory
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
edge_count(&building, EdgeKind::Imports),
|
||||||
|
case.imports,
|
||||||
|
"{} import baseline",
|
||||||
|
case.directory
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
edge_count(&building, EdgeKind::Inherits),
|
||||||
|
case.inherits,
|
||||||
|
"{} inheritance baseline",
|
||||||
|
case.directory
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
edge_count(&building, EdgeKind::Calls),
|
||||||
|
case.calls,
|
||||||
|
"{} call baseline",
|
||||||
|
case.directory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edge_count(building: &brick::Building, kind: EdgeKind) -> usize {
|
||||||
|
building
|
||||||
|
.edges
|
||||||
|
.iter()
|
||||||
|
.filter(|edge| edge.kind == kind)
|
||||||
|
.count()
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue