pub struct Editor { /* private fields */ }Expand description
One document, analysed: what the front end made of the text the editor last sent.
Implementations§
Source§impl Editor
impl Editor
Sourcepub fn of(name: &str, text: &str) -> Editor
pub fn of(name: &str, text: &str) -> Editor
Parse, expand, check, place and secure one document, and index what an editor can ask about.
A project rather than a lone module, with the standard library as the only other place
modules come from: a file being edited may import bignum, and an editor that answered
“cannot find add_big” for every name in it would be answering about a program the compiler
does not have. There is no directory here — a browser tab has none, and a language server
resolving a relative path off a URI is a decision docs/65
did not take — so the loader serves this text as the root and nothing else, and
crate::stdlib answers the rest.
A library is analysed as a library, not refused: most files being edited are, and
crate::project::slice_or_library is the same entry beck check uses to say so.
Sourcepub fn completing_from(self, previous: &Index) -> Editor
pub fn completing_from(self, previous: &Index) -> Editor
Borrow the previous analysis’s names, for text that does not check.
A half-typed name is an unresolved name, so the most common state of a file being written in is the state that has no program and therefore no name table. An editor that answered nothing there would answer nothing exactly when it was being asked, so a consumer keeps its last analysis and hands it here.
What this is not is a stale answer presented as a current one: the names are marked
stale, the diagnostics are always this text’s, and nothing else is
carried over. docs/98 §98.1’s rule — a
stale table beside a red error teaches somebody something false — is about derived
answers like a placement table, and this is a completion list; the difference is that the
consumer is told.
Sourcepub fn stale(&self) -> bool
pub fn stale(&self) -> bool
True when the names came from an earlier text than the one being shown.
Sourcepub fn placed(&self) -> Option<&Placed>
pub fn placed(&self) -> Option<&Placed>
The checked program, for a caller that wants more than an editor’s questions.
pub fn diagnostics(&self) -> &Diagnostics
pub fn source_map(&self) -> &SourceMap
Sourcepub fn marks(&self) -> Vec<Mark>
pub fn marks(&self) -> Vec<Mark>
Every diagnostic, as a range and the text a terminal would print.
Sourcepub fn symbols(&self) -> impl Iterator<Item = (&str, &Symbol)>
pub fn symbols(&self) -> impl Iterator<Item = (&str, &Symbol)>
The names this document declares, in name order — documentSymbol’s answer.
Imported names are excluded: they are not symbols of this file, and an outline listing them would list the standard library under every module that used it.
pub fn symbol(&self, name: &str) -> Option<&Symbol>
Sourcepub fn hover(&self, offset: u32) -> Option<&Symbol>
pub fn hover(&self, offset: u32) -> Option<&Symbol>
What to say about the name under the caret.
Sourcepub fn class_hover(&self, offset: u32) -> Option<String>
pub fn class_hover(&self, offset: u32) -> Option<String>
What to say about the class under the caret, when the caret is in a class= value.
docs/104 §104.4: “hover
print the declarations […] that is the Tailwind IntelliSense extension, without an
extension, because the answers come from the compiler.” A class is not a name this document
declares, so it is not in Editor::hover’s index and never could be — what it is, is a
token inside a string, answered from the same table beck build emits the sheet from.
Sourcepub fn class_completions(&self, offset: u32) -> Vec<Completion>
pub fn class_completions(&self, offset: u32) -> Vec<Completion>
The utilities that could finish the class being typed, best-first.
Empty when the caret is not inside a class= value, which is what keeps four thousand
utility names out of every other completion in the file.
Sourcepub fn definition(&self, offset: u32) -> Option<(u32, u32)>
pub fn definition(&self, offset: u32) -> Option<(u32, u32)>
Where the name under the caret is declared, in this document.
Sourcepub fn completions(&self, offset: u32) -> Vec<Completion>
pub fn completions(&self, offset: u32) -> Vec<Completion>
What could finish the word being typed, best-first.
Names before keywords, because a name is specific to this program and a keyword is not, and within each group the order is the name order the index already keeps. A caret that is not in a word offers everything — which is what an editor’s “show me what is here” gesture asks for.
Sourcepub fn prefix(&self, offset: u32) -> String
pub fn prefix(&self, offset: u32) -> String
The word a completion would replace, so a client can send an edit rather than a guess.
Sourcepub fn references(&self, offset: u32) -> Vec<Occurrence>
pub fn references(&self, offset: u32) -> Vec<Occurrence>
Every place the name under the caret appears in this document.
Empty rather than partial when the two accounts of the document disagree — see
occurrences, which is where that rule is.
Sourcepub fn occurrences(&self, name: &str) -> Option<Vec<Occurrence>>
pub fn occurrences(&self, name: &str) -> Option<Vec<Occurrence>>
Every place name appears, or None when this document’s two accounts of it disagree.
§The two accounts, and why both
The lexical account is the token stream: every run of the text that reads
name, keywords included. It is complete by construction — the lexer saw the whole file —
and it knows nothing, so a local variable that happens to share the name is in it, and so is
the page in expect page contains "1", which is the grammar’s word rather than a
reference to the signal of that name.
The semantic account is the checked program: a CoreKind::Global node per reference,
resolved, so a local of the same name is not in it and a name reached through an import
is. It knows everything and is not complete: a reference the checker rewrote — a trait
method resolved to an impl, a macro’s expansion — has a span that is a call site rather
than an identifier.
What makes an edit safe is the two agreeing: every semantic reference begins on a lexical
identifier that reads name, and the only lexical identifier left over is the
declaration’s own. A file where that holds has no shadow, no unspanned mention and no
rewritten reference, and the lexical ranges are then the whole truth about where the name
is — which is also why the edits are the lexical ranges and never the spans. Where
it does not hold this answers None, and both callers decline rather than edit — because
the alternative to declining is a rename that silently changes what a program means, which
is worse than a rename that does not happen.
Sourcepub fn rename(&self, offset: u32, to: &str) -> Result<Vec<Occurrence>, Refusal>
pub fn rename(&self, offset: u32, to: &str) -> Result<Vec<Occurrence>, Refusal>
Where a rename would edit, or why it will not.
The edits are occurrences’, and everything else here is a refusal.
docs/03 §3.4’s rule for placement — a
compile error with a suggested annotation, never a silent guess — is the same rule this
keeps for an edit: a refusal an author can read beats a rewrite they have to check.
The last check is the expensive and the decisive one: the proposed text is analysed,
and a rename that would not compile is not offered. That costs one more compile of one file
— docs/64 §64.6’s 4.7 ms at the worst
file in this tree — on a keystroke nobody types twice a minute, and it is what turns the
reasoning above into a fact about the text rather than an argument about the IR.
Sourcepub fn hints(&self) -> Vec<Hint>
pub fn hints(&self) -> Vec<Hint>
What the compiler worked out that the source does not say, where it could be written down.
The two inferred halves of a Beck signature, and only those: where a definition runs, which §3.4 makes a solved constraint rather than an annotation, and what it performs, which §3.6 makes an inferred row a boundary later has to declare. A name whose source already carries the annotation gets no hint for it — an inlay hint repeating what is on the line beside it is noise, and the point of these is that they are the part nobody wrote.
Every label is what an author could paste in at the offset it carries, which is why the
effect hint is rendered by render_uses and the tier hint reads @on(...): a hint you
can accept is worth more than a hint you have to translate.