only_semantic/
analysis.rs1use only_diagnostic::DiagnosticPhase;
2use only_syntax::{BootstrapHeader, SyntaxSnapshot, bootstrap, snapshot};
3
4use crate::SemanticSnapshot;
5use crate::lower::lower_syntax;
6use crate::symbols::build_symbol_index;
7use crate::validate::validate_document;
8
9pub fn compile_document(source: &str) -> SemanticSnapshot {
17 compile_syntax(&snapshot(source))
18}
19
20pub fn compile_document_for_runner(source: &str, runner_version: &str) -> SemanticSnapshot {
22 compile_document_with_runner(source, runner_version).1
23}
24
25pub fn compile_document_with_runner(
27 source: &str,
28 runner_version: &str,
29) -> (SyntaxSnapshot, SemanticSnapshot) {
30 let header = match bootstrap(source, runner_version) {
31 Ok(header) => header,
32 Err(diagnostic) => return snapshot_with_version_error(diagnostic),
33 };
34 let syntax = snapshot(source);
35 let mut compiled = compile_syntax(&syntax);
36 append_unversioned_parse_help(&mut compiled, header);
37 (syntax, compiled)
38}
39
40pub fn compile_syntax(snapshot: &SyntaxSnapshot) -> SemanticSnapshot {
48 let (document, mut diagnostics) = lower_syntax(snapshot);
49 let symbols = build_symbol_index(&document);
50 diagnostics.extend(validate_document(&document, &symbols));
51
52 SemanticSnapshot {
53 document,
54 diagnostics,
55 symbols,
56 }
57}
58
59fn snapshot_with_version_error(
60 diagnostic: only_diagnostic::Diagnostic,
61) -> (SyntaxSnapshot, SemanticSnapshot) {
62 let syntax = snapshot("");
63 let mut compiled = compile_syntax(&syntax);
64 compiled.diagnostics.push(diagnostic);
65 (syntax, compiled)
66}
67
68fn append_unversioned_parse_help(compiled: &mut SemanticSnapshot, header: BootstrapHeader) {
69 if header.required_version.is_some() {
70 return;
71 }
72
73 if let Some(diagnostic) = compiled
74 .diagnostics
75 .iter_mut()
76 .find(|diagnostic| diagnostic.phase == DiagnosticPhase::Parse)
77 {
78 diagnostic.message.push_str(
79 "\nnote: this file has no `!version` line\nhelp: check the syntax; it may need a newer version of only",
80 );
81 }
82}