eclipse-langium/langium

Cancellation: More Problems

cdietrich opened this issue · 5 comments

From #1562 and #1566

Additionally to the missing notifications to the client we see more problems with cancellation respectively the recovery from it.

  • shouldRelink / unlink evaluates document.references only. but this wont be maintained if the document did not enter the linking phase before the cancellation, but during the linking of another document some references in that document are resolved in this document
  • changed files are just invalidated, but not unlinked, which leads to the same problem, as reparse might be skipped if content has not changed.

To be investigated:
at end of iterative deletes, not all delete validations seems to be have sent to the client

workaround ideas:

override invalidateDocument(uri: URI): LangiumDocument | undefined {
    const result = super.invalidateDocument(uri)
    if (result !== undefined) {
      for (const node of AstUtils.streamAst(result.parseResult.value)) {
        AstUtils.streamReferences(node).forEach(refInfo => {
          const ref = refInfo.reference as DefaultReference
          if (ref._ref !== undefined) {
            delete ref._ref
            delete ref._nodeDescription
          }
        })
      }
    }
    return result
  }
protected override shouldRelink(document: LangiumDocument, changedUris: Set<string>): boolean {
    let result = super.shouldRelink(document, changedUris)

    if (!result) {
      for (const node of AstUtils.streamAst(document.parseResult.value)) {
        AstUtils.streamReferences(node).forEach(refInfo => {
          const ref = refInfo.reference as DefaultReference
          if (ref._ref !== undefined) {
            if (isLinkingError(ref._ref)) {
              result = true
            }
          }
        })
      }
    }
    return result
  }
override unlink(document: LangiumDocument): void {
    super.unlink(document)
    for (const node of AstUtils.streamAst(document.parseResult.value)) {
      AstUtils.streamReferences(node).forEach(refInfo => {
        const ref = refInfo.reference as DefaultReference
        if (ref._ref !== undefined) {
          delete ref._ref
          delete ref._nodeDescription
        }
      })
    }
  }

here is my attempts to reproduce the delete problem

main...cdietrich:langium:cd-repro2

but with longer timeouts it works....

it looks like the delete problem might be a client side one.
i dont always see all deletes arrive at the server.

created microsoft/vscode-languageserver-node#1503 for the client side clarification

Has been fixed with #1566. Release is available at langium@3.1.2.