feat: publish Dever core with project scaffolding and versioned AI skills

This commit is contained in:
Antigravity committed 2026-10-04 13:37:30 +00:00
1 parent 70fa73cdc2
commit ac458ffa7f
960 files changed
+221319 -1163

No files matched your search

@@ -0,0 +1,291 @@
mod support;
use dever_core::source::SourceMap;
#[test]
fn cms_formats_share_source_model_api_and_configuration_contracts() {
let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../examples/cms");
let plain = SourceMap::load(&root.join("dever/module")).unwrap();
let markdown = SourceMap::load(&root.join("md/module")).unwrap();
let plain_settings =
dever_runtime::config::Settings::load_project(&root.join("dever")).unwrap();
let markdown_settings =
dever_runtime::config::Settings::load_project(&root.join("md")).unwrap();
let plain_program =
dever_core::check_with_settings(&plain, &plain_settings).unwrap_or_else(|errors| {
panic!(
"{}",
errors
.iter()
.map(|error| error.render(&plain))
.collect::<String>()
)
});
let markdown_program = dever_core::check_with_settings(&markdown, &markdown_settings)
.unwrap_or_else(|errors| {
panic!(
"{}",
errors
.iter()
.map(|error| error.render(&markdown))
.collect::<String>()
)
});
assert_no_application_errors(&plain_program, &plain);
assert_no_application_errors(&markdown_program, &markdown);
assert_eq!(
plain_program.model_snapshot(),
markdown_program.model_snapshot(),
);
assert_eq!(
plain_program.api_snapshot(),
markdown_program.api_snapshot()
);
// 应用测试也是双源码合同的一部分,避免 Markdown 测试退化为空断言。
let plain_with_tests =
SourceMap::load_project(&root.join("dever/module"), &root.join("dever/test")).unwrap();
let markdown_with_tests =
SourceMap::load_project(&root.join("md/module"), &root.join("md/test")).unwrap();
assert_eq!(
canonical_cms_sources(&plain_with_tests),
canonical_cms_sources(&markdown_with_tests),
);
let configuration = |format: &str| -> serde_json::Value {
serde_json::from_str(
&std::fs::read_to_string(root.join(format).join("config/setting.json")).unwrap(),
)
.unwrap()
};
assert_eq!(configuration("dever"), configuration("md"));
for (format, program, settings) in [
("dever", &plain_program, &plain_settings),
("md", &markdown_program, &markdown_settings),
] {
let profile = program.validate_database_settings(settings).unwrap();
assert!(profile.sqlite && !profile.postgres, "{format}");
let sources = if format == "dever" { &plain } else { &markdown };
let generated = dever_core::native::emit_project(program, sources, profile).unwrap();
assert!(generated.contains(
"dever_runtime::job::scope_system(None, cmd_dispatch(&args[0], &args[1])).await"
));
assert!(generated.contains(
"dever_runtime::lifecycle::serve_both(dever_runtime::api::serve(api_route), job_serve()).await"
));
}
}
fn assert_no_application_errors(program: &dever_core::hir::Program, sources: &SourceMap) {
let errors = program.application_errors().unwrap();
assert!(
errors.is_empty(),
"{}",
errors
.iter()
.map(|error| error.render(sources))
.collect::<String>()
);
}
fn canonical_cms_sources(sources: &SourceMap) -> std::collections::BTreeMap<String, String> {
use dever_core::syntax::Declaration;
let mut declarations = std::collections::BTreeMap::new();
for source in sources.files() {
// 使用编译器 AST 的边界抽取声明,避免测试另写 Markdown fence 解析器。
let package = dever_core::parse(source).unwrap();
let name = package
.name
.iter()
.map(|part| part.text.as_str())
.collect::<Vec<_>>()
.join(".");
let mut code = String::new();
for declaration in package.declarations {
let span = match declaration {
Declaration::Type(value) => value.span,
Declaration::Function(value) => value.span,
Declaration::External(value) => value.span,
Declaration::Api(value) => value.span,
Declaration::Rest(value) => value.span,
Declaration::Database(value) => value.span,
Declaration::Schedule(value) => value.span,
Declaration::ModelIndex(value) => value.span,
Declaration::Relation(value) => value.span,
Declaration::Seed(value) => value.span,
Declaration::Migration(value) => value.span,
Declaration::ModelSql(value) => value.span,
};
code.push_str(&source.text()[span.start..span.end]);
code.push('\n');
}
let mut normalized = SourceMap::default();
normalized.add(format!("{}.dever", name.replace('.', "/")), code);
let canonical = dever_core::format::format(&normalized.files()[0]).unwrap();
assert!(declarations.insert(name, canonical).is_none());
}
declarations
}
#[test]
fn maintained_examples_pass_the_same_contract_checker() {
for root in example_roots() {
let source_root = root.join("module");
let program = support::checked(&SourceMap::load(&source_root).unwrap());
let baseline = root.join("dever.api");
if baseline.exists() {
program
.check_api(&std::fs::read_to_string(baseline).unwrap())
.unwrap();
}
}
}
fn examples_root() -> std::path::PathBuf {
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../../examples/old/dever")
}
fn example_roots() -> Vec<std::path::PathBuf> {
let examples = examples_root()
.parent()
.unwrap()
.parent()
.unwrap()
.to_path_buf();
vec![examples.join("cms/dever"), examples.join("cms/md")]
}
fn archived_sources(root: &std::path::Path) -> SourceMap {
copy_archived_sources(root, false)
}
fn archived_rejected_sources(root: &std::path::Path) -> SourceMap {
copy_archived_sources(root, true)
}
fn copy_archived_sources(root: &std::path::Path, remap_main: bool) -> SourceMap {
let loaded = SourceMap::load(root).unwrap();
let mut sources = SourceMap::default();
for source in loaded.files() {
let path = if remap_main && source.path() == std::path::Path::new("main.dever") {
std::path::Path::new("app.dever")
} else {
source.path()
};
sources.add(path, source.text());
}
sources
}
#[test]
fn rejected_examples_demonstrate_the_documented_diagnostic() {
for (name, code) in [
("range", "C011"),
("failure", "C012"),
("pure", "C013"),
("coverage", "C009"),
("private", "C006"),
] {
let sources =
archived_rejected_sources(&examples_root().join("rejected").join(name).join("module"));
let errors = dever_core::check(&sources).unwrap_err();
assert!(
errors.iter().any(|error| error.code == code),
"{name}: {errors:#?}"
);
}
}
#[test]
fn constraints_and_explicit_recovery_preserve_native_execution() {
assert_eq!(
run_example("contracts", "main.main"),
"configured = domain.Port { value = 8080 }\ninvalid = domain.PortResult.Failed(port must be between 1 and 65535)\nfallback = domain.Port { value = 8080 }\n"
);
}
fn run_example(name: &str, entry: &str) -> String {
let sources = archived_sources(&examples_root().join(name).join("module"));
let program = support::checked(&sources);
let compiler = std::env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
let native = dever_core::native::compile(&program, &sources, entry, &compiler).unwrap();
let output = std::process::Command::new(native.executable())
.current_dir(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."))
.arg("sample")
.output()
.unwrap();
assert!(
output.status.success(),
"{name}: {}",
String::from_utf8_lossy(&output.stderr)
);
assert!(
output.stderr.is_empty(),
"{name}: {}",
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8(output.stdout).unwrap()
}
#[test]
fn source_roots_and_sequence_examples_preserve_expected_native_results() {
for (name, entry, expected) in [
("hello", "main.main", "hello\n"),
("privacy", "main.main", "before = 0\nafter = 1\n"),
(
"sequences",
"main.main",
"mapped = [2, 4, 6]\ntotal = 6\nstopped = main.Summary { total = 6, count = 3 }\nempty_total = 0\nbytes_total = 131\nfirst_value = 2\nmissing = null\n",
),
("stream", "main.main", "total = 208\n"),
(
"library",
"main.main",
"json = {\"message\":\"你好 Dever\",\"total\":6}\n",
),
] {
assert_eq!(run_example(name, entry), expected, "{name}");
}
}
#[test]
fn text_example_preserves_unicode_null_and_explicit_conversion_failures() {
let output = run_example("text", "main.main");
assert!(output.starts_with("cleaned = dever\ncharacter = 😀\nslice = 中😀\npieces = [a, , b]\njoined = a||b\nparsed = 42\ninvalid = null\nexact = 1.25\nrounded = 2.34\nutf8 = 你好\n"), "{output}");
assert!(
output.contains("invalid_utf8 = dever.bytes.DecodeResult.Failed("),
"{output}"
);
assert!(
output.contains("invalid_byte = dever.bytes.BufferResult.Failed("),
"{output}"
);
}
#[test]
fn parallel_example_joins_every_named_task_before_done() {
let output = run_example("parallel", "main.main");
let mut lines: Vec<_> = output.lines().collect();
assert_eq!(lines.pop(), Some("done"));
lines.sort();
assert_eq!(lines, ["alpha", "beta", "gamma"]);
}
#[test]
fn async_example_owns_tasks_groups_and_channels_until_completion() {
assert_eq!(
run_example("async", "main.main"),
"task_value = 7\ngrouped_value = 21\ncomputed = 144\n"
);
}
#[test]
fn system_example_reads_child_inputs_and_returns_invalid_sleep_as_failure() {
let output = run_example("system", "main.main");
assert!(output.contains("arguments = [sample]"), "{output}");
assert!(output.contains("clock = "), "{output}");
assert!(
output.contains("invalid_sleep = dever.time.SleepResult.Failed("),
"{output}"
);
}