From f7de35664fed96b030d00f323ade18dca1ece7d5 Mon Sep 17 00:00:00 2001 From: aboyko Date: Wed, 27 Nov 2024 21:27:41 -0500 Subject: [PATCH] Validate non-saved docs on close --- .../languageserver/util/SimpleLanguageServer.java | 14 +++++++++++--- .../util/SimpleTextDocumentService.java | 1 + .../vscode/commons/util/text/LazyTextDocument.java | 2 +- .../ide/vscode/commons/util/text/TextDocument.java | 13 ++++++++++++- .../boot/app/BootLanguageServerInitializer.java | 11 ++++++++++- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java index e344bb2ac..21569701d 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleLanguageServer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2023 VMware Inc. + * Copyright (c) 2016, 2024 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -111,6 +111,7 @@ import org.springframework.ide.vscode.commons.util.Assert; import org.springframework.ide.vscode.commons.util.AsyncRunner; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.CollectionUtil; +import org.springframework.ide.vscode.commons.util.text.LazyTextDocument; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; @@ -760,8 +761,15 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd TextDocument doc = documents.getLatestSnapshot(docId.getUri()); if (doc == null) { - //Do not bother reconciling if document doesn't exist anymore (got closed in the meantime) - return; + // If document doesn't exist anymore it likely got closed in the meantime. Still needs validation. + LanguageComputer languageDetector = appContext.getBean(LanguageComputer.class); + if (languageDetector != null) { + doc = new LazyTextDocument(uri.toASCIIString(), languageDetector.computeLanguage(uri)); + } else { + // Cannot determine the language? Give up. + log.warn("Cannot determine the language for document: " + uri); + return; + } } if (testListener != null) { diff --git a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java index 02e265d37..52b1e348f 100644 --- a/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java +++ b/headless-services/commons/commons-language-server/src/main/java/org/springframework/ide/vscode/commons/languageserver/util/SimpleTextDocumentService.java @@ -640,6 +640,7 @@ public class SimpleTextDocumentService implements TextDocumentService, DocumentE if (url != null) { TextDocument doc = getLatestSnapshot(url); if (doc != null) { + doc.saved(); for (Consumer l : documentSaveListeners) { l.accept(new TextDocumentSaveChange(doc)); } diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java index 224c03472..eaf55e086 100644 --- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/LazyTextDocument.java @@ -29,7 +29,7 @@ public class LazyTextDocument extends TextDocument { } public LazyTextDocument(String uri, LanguageId languageId) { - this(uri, LanguageId.JAVA, () -> { + this(uri, languageId, () -> { try { InputStream stream = URI.create(uri).toURL().openStream(); return IOUtil.toString(stream); diff --git a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/TextDocument.java b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/TextDocument.java index 2403a5dc7..8468ab3a5 100644 --- a/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/TextDocument.java +++ b/headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/text/TextDocument.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016, 2021 Pivotal, Inc. + * Copyright (c) 2016, 2024 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -37,6 +37,7 @@ public class TextDocument implements IDocument { private final String uri; private Text text = new Text(""); private int version; + private boolean changedSinceLastSave = false; public TextDocument(String uri, LanguageId languageId) { this(uri, languageId, 0, ""); @@ -48,6 +49,7 @@ public class TextDocument implements IDocument { this.text = other.text; this.lineTracker.set(text.toString()); this.version = other.version; + this.changedSinceLastSave = other.changedSinceLastSave; } public TextDocument(String uri, LanguageId languageId, int version, String text) { @@ -95,6 +97,7 @@ public class TextDocument implements IDocument { apply(change); } this.version = newVersion; + this.changedSinceLastSave = true; } else { log.warn("Change event with bad version ignored"); } @@ -298,4 +301,12 @@ public class TextDocument implements IDocument { } return null; } + + public void saved() { + this.changedSinceLastSave = false; + } + + public boolean hasChangedSinceLastSave() { + return this.changedSinceLastSave; + } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java index 64d15da6a..f73391844 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootLanguageServerInitializer.java @@ -190,7 +190,16 @@ public class BootLanguageServerInitializer implements InitializingBean { TextDocument doc = params.getDocument(); server.validateWith(doc.getId(), reconcileEngine); }); - + server.getTextDocumentService().onDidClose(doc -> { + if (doc.hasChangedSinceLastSave()) { + /* + * If doc is changed since last save closing it would ignore the latest changes. + * Therefore the file requires to be validated again. + */ + server.validateWith(doc.getId(), reconcileEngine); + } + + }); // ServerUtils.listenToClassFileChanges(server.getWorkspaceService().getFileObserver(), projectFinder, project -> validateAll(components, server, project)); }); config.addListener(evt -> {