Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion crates/opy-provider/src/edits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,25 @@ const CROSS_FILE_CODES: [&str; 7] = [
/// reports `syntaxError` only for one of these attributed to the validated
/// document itself; every diagnostic whose verdict depends on sibling
/// sources or bindings defers to the client's post-edit project `lpp/check`.
const DOCUMENT_SYNTAX_CODES: [&str; 14] = [
///
/// Intentionally deferred, so a fragment's own edits stay `valid` here and
/// the project's `lpp/check` arbitrates:
/// - name/binding verdicts (`unknown-*`, `duplicate-*`, `invalid-arity`,
/// `unresolved-reference`, `incompatible-protocol`) — the referent may be
/// declared in a sibling file;
/// - merged-table duplicates (`rule-prefix-template-duplicate`,
/// `replacement-duplicate`, `post-compile-hook-duplicate`,
/// `macro-redeclaration`) — the earlier entry may come from an include;
/// - macro and script verdicts (`macro-arity`, `macro-recursion`,
/// `script-*`) — the macro table and script files come from includes;
/// - external-file verdicts (`include-not-found`, `settings-not-found`,
/// `translations-invalid`, `settings-expression`,
/// `rule-prefix-template-invalid`) — the source text or constants the
/// verdict needs live outside the document;
/// - catalog/environment verdicts (`catalog-error`, `manifest-error`,
/// `unknown-enum-member`) — fixed-vocabulary questions the client's
/// project check answers the same way.
const DOCUMENT_SYNTAX_CODES: [&str; 16] = [
"lex-error",
"parse-error",
"workshop-source",
Expand All @@ -60,6 +78,8 @@ const DOCUMENT_SYNTAX_CODES: [&str; 14] = [
"settings-placement",
"macro-invalid",
"do-while-placement",
"invalid-string-entity",
"unknown-string-entity",
];

#[derive(Debug, Deserialize)]
Expand Down
35 changes: 35 additions & 0 deletions crates/opy-provider/tests/lpp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2588,6 +2588,41 @@ fn validate_edits_applies_normative_rules() {
"failingEditIndex": 1,
})
);

// String entities are fixed vocabulary: a malformed `\&entity;` escape in
// the document's own text is a `syntaxError`, not a deferred verdict.
let entity = |session: &mut Session, id: i64, new_text: &str| {
session.request(json!({
"jsonrpc": "2.0",
"id": id,
"method": "lpp/validateEdits",
"params": {
"document": {
"uri": "file:///project/entity.opy",
"languageId": "opy",
"version": 3,
"text": "rule \"r\":\n @Event global\n wait(0.1)\n",
},
"edits": [{
"range": {
"start": { "line": 0, "character": 6 },
"end": { "line": 0, "character": 7 },
},
"newText": new_text,
}],
},
}))
};
assert_eq!(
entity(&mut session, 10, "r \\&bogus;")["result"],
json!({ "valid": false, "version": 3, "reason": "syntaxError" }),
"an unknown entity in the edited document is a syntaxError"
);
assert_eq!(
entity(&mut session, 11, "r \\&bogus")["result"]["reason"],
"syntaxError",
"an unterminated entity in the edited document is a syntaxError"
);
session.shutdown();
}

Expand Down
Loading