Skip to content

Commit 1e7053a

Browse files
palukkusubhramit
andauthored
Add Language Server to the UI and add the integrity/consistency check (#13697)
* adds palukku#23 adds palukku#38 adds palukku#42 * fix localization * Changes according to review comments Remove unnecessary classes and renaming * modify CHANGELOG and split checks to other classes * rename variable * add settings support and fix comments * Update jabls/src/main/java/org/jabref/languageserver/util/LspIntegrityCheck.java Co-authored-by: Subhramit Basu <[email protected]> * rename parameter * remove package and add import * rename package from manager to controller * address review comments Co-authored-by: Subhramit Basu <[email protected]> * fix tests and minor changes * address comments * fix typo --------- Co-authored-by: Subhramit Basu <[email protected]>
1 parent e443fb3 commit 1e7053a

File tree

28 files changed

+688
-149
lines changed

28 files changed

+688
-149
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
1111

1212
### Added
1313

14+
- We added the option to enable the language server in the preferences. [#13697](https://github.com/JabRef/jabref/pull/13697)
1415
- We introduced an option in Preferences under (under Linked files -> Linked file name conventions) to automatically rename linked files when an entry data changes. [#11316](https://github.com/JabRef/jabref/issues/11316)
1516
- We added tooltips (on hover) for 'Library-specific file directory', 'User-specific file directory' and 'LaTeX file directory' fields of the library properties window. [#12269](https://github.com/JabRef/jabref/issues/12269)
1617
- A space is now added by default after citations inserted via the Libre/OpenOffice integration. [#13559](https://github.com/JabRef/jabref/issues/13559)

jabgui/build.gradle.kts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ dependencies {
2020
// implementation("org.openjfx:javafx-fxml")
2121
// implementation("org.openjfx:javafx-graphics")
2222

23+
implementation(project(":jabls"))
24+
implementation(project(":jabsrv"))
25+
2326
implementation("org.openjfx:javafx-swing")
2427
implementation("org.openjfx:javafx-web")
2528

26-
implementation(project(":jabsrv"))
27-
2829
implementation("com.pixelduke:fxthemes")
2930

3031
// From JavaFX25 onwards

jabgui/src/main/java/module-info.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
open module org.jabref {
22
requires org.jabref.jablib;
3-
3+
requires org.jabref.jabls;
44
requires org.jabref.jabsrv;
55

66
// Swing

jabgui/src/main/java/org/jabref/gui/JabRefGUI.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.jabref.gui.util.UiTaskExecutor;
3434
import org.jabref.gui.util.WebViewStore;
3535
import org.jabref.http.manager.HttpServerManager;
36+
import org.jabref.languageserver.controller.LanguageServerController;
3637
import org.jabref.logic.UiCommand;
3738
import org.jabref.logic.ai.AiService;
3839
import org.jabref.logic.citation.SearchCitationsRelationsService;
@@ -86,6 +87,7 @@ public class JabRefGUI extends Application {
8687

8788
private static RemoteListenerServerManager remoteListenerServerManager;
8889
private static HttpServerManager httpServerManager;
90+
private static LanguageServerController languageServerController;
8991

9092
private Stage mainStage;
9193

@@ -156,8 +158,9 @@ public void initialize() {
156158
Injector.setModelOrService(DirectoryMonitor.class, directoryMonitor);
157159

158160
BibEntryTypesManager entryTypesManager = preferences.getCustomEntryTypesRepository();
161+
JournalAbbreviationRepository journalAbbreviationRepository = JournalAbbreviationLoader.loadRepository(preferences.getJournalAbbreviationPreferences());
159162
Injector.setModelOrService(BibEntryTypesManager.class, entryTypesManager);
160-
Injector.setModelOrService(JournalAbbreviationRepository.class, JournalAbbreviationLoader.loadRepository(preferences.getJournalAbbreviationPreferences()));
163+
Injector.setModelOrService(JournalAbbreviationRepository.class, journalAbbreviationRepository);
161164
Injector.setModelOrService(ProtectedTermsLoader.class, new ProtectedTermsLoader(preferences.getProtectedTermsPreferences()));
162165

163166
IndexManager.clearOldSearchIndices();
@@ -168,6 +171,9 @@ public void initialize() {
168171
JabRefGUI.httpServerManager = new HttpServerManager();
169172
Injector.setModelOrService(HttpServerManager.class, JabRefGUI.httpServerManager);
170173

174+
JabRefGUI.languageServerController = new LanguageServerController(preferences, journalAbbreviationRepository);
175+
Injector.setModelOrService(LanguageServerController.class, JabRefGUI.languageServerController);
176+
171177
JabRefGUI.stateManager = new JabRefGuiStateManager();
172178
Injector.setModelOrService(StateManager.class, stateManager);
173179

@@ -424,6 +430,9 @@ public void startBackgroundTasks() {
424430
if (remotePreferences.enableHttpServer()) {
425431
httpServerManager.start(stateManager, remotePreferences.getHttpServerUri());
426432
}
433+
if (remotePreferences.enableLanguageServer()) {
434+
languageServerController.start(remotePreferences.getLanguageServerPort());
435+
}
427436
}
428437

429438
@Override
@@ -467,6 +476,12 @@ public void stop() {
467476
LOGGER.trace("HttpServerManager shut down");
468477
});
469478

479+
executor.submit(() -> {
480+
LOGGER.trace("Shutting down language server controller");
481+
languageServerController.stop();
482+
LOGGER.trace("LanguageServerController shut down");
483+
});
484+
470485
executor.submit(() -> {
471486
LOGGER.trace("Stopping background tasks");
472487
Unirest.shutDown();

jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTab.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public class GeneralTab extends AbstractPreferenceTabView<GeneralTabViewModel> i
6060
@FXML private TextField remotePort;
6161
@FXML private CheckBox enableHttpServer;
6262
@FXML private TextField httpServerPort;
63+
@FXML private CheckBox enableLanguageServer;
64+
@FXML private TextField languageServerPort;
6365
@FXML private Button remoteHelp;
6466
@Inject private FileUpdateMonitor fileUpdateMonitor;
6567
@Inject private BibEntryTypesManager entryTypesManager;
@@ -147,6 +149,7 @@ public void initialize() {
147149
Platform.runLater(() -> {
148150
validationVisualizer.initVisualization(viewModel.remotePortValidationStatus(), remotePort);
149151
validationVisualizer.initVisualization(viewModel.httpPortValidationStatus(), httpServerPort);
152+
validationVisualizer.initVisualization(viewModel.languageServerPortValidationStatus(), languageServerPort);
150153
validationVisualizer.initVisualization(viewModel.fontSizeValidationStatus(), fontSize);
151154
validationVisualizer.initVisualization(viewModel.customPathToThemeValidationStatus(), customThemePath);
152155
});
@@ -158,6 +161,10 @@ public void initialize() {
158161
enableHttpServer.selectedProperty().bindBidirectional(viewModel.enableHttpServerProperty());
159162
httpServerPort.textProperty().bindBidirectional(viewModel.httpPortProperty());
160163
httpServerPort.disableProperty().bind(enableHttpServer.selectedProperty().not());
164+
165+
enableLanguageServer.selectedProperty().bindBidirectional(viewModel.enableLanguageServerProperty());
166+
languageServerPort.textProperty().bindBidirectional(viewModel.languageServerPortProperty());
167+
languageServerPort.disableProperty().bind(enableLanguageServer.selectedProperty().not());
161168
}
162169

163170
@FXML

jabgui/src/main/java/org/jabref/gui/preferences/general/GeneralTabViewModel.java

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.jabref.gui.util.DirectoryDialogConfiguration;
3434
import org.jabref.gui.util.FileDialogConfiguration;
3535
import org.jabref.http.manager.HttpServerManager;
36+
import org.jabref.languageserver.controller.LanguageServerController;
3637
import org.jabref.logic.FilePreferences;
3738
import org.jabref.logic.LibraryPreferences;
3839
import org.jabref.logic.l10n.Language;
@@ -112,6 +113,9 @@ public class GeneralTabViewModel implements PreferenceTabViewModel {
112113
private final BooleanProperty enableHttpServerProperty = new SimpleBooleanProperty();
113114
private final StringProperty httpPortProperty = new SimpleStringProperty("");
114115
private final Validator httpPortValidator;
116+
private final Validator languageServerPortValidator;
117+
private final BooleanProperty enableLanguageServerProperty = new SimpleBooleanProperty();
118+
private final StringProperty languageServerPortProperty = new SimpleStringProperty("");
115119
private final TrustStoreManager trustStoreManager;
116120

117121
private final FileUpdateMonitor fileUpdateMonitor;
@@ -149,29 +153,22 @@ public GeneralTabViewModel(DialogService dialogService, GuiPreferences preferenc
149153

150154
remotePortValidator = new FunctionBasedValidator<>(
151155
remotePortProperty,
152-
input -> {
153-
try {
154-
int portNumber = Integer.parseInt(remotePortProperty().getValue());
155-
return RemoteUtil.isUserPort(portNumber);
156-
} catch (NumberFormatException ex) {
157-
return false;
158-
}
159-
},
156+
RemoteUtil::isStringUserPort,
160157
ValidationMessage.error("%s > %s %n %n %s".formatted(
161158
Localization.lang("Network"),
162159
Localization.lang("Remote operation"),
163160
Localization.lang("You must enter an integer value in the interval 1025-65535"))));
161+
164162
httpPortValidator = new FunctionBasedValidator<>(
165163
httpPortProperty,
166-
input -> {
167-
try {
168-
int portNumber = Integer.parseInt(httpPortProperty().getValue());
169-
return RemoteUtil.isUserPort(portNumber);
170-
} catch (NumberFormatException ex) {
171-
return false;
172-
}
173-
},
164+
RemoteUtil::isStringUserPort,
174165
ValidationMessage.error("%s".formatted(Localization.lang("You must enter an integer value in the interval 1025-65535"))));
166+
167+
languageServerPortValidator = new FunctionBasedValidator<>(
168+
languageServerPortProperty,
169+
RemoteUtil::isStringUserPort,
170+
ValidationMessage.error(Localization.lang("You must enter an integer value in the interval 1025-65535")));
171+
175172
this.trustStoreManager = new TrustStoreManager(Path.of(preferences.getSSLPreferences().getTruststorePath()));
176173
}
177174

@@ -183,6 +180,10 @@ public ValidationStatus httpPortValidationStatus() {
183180
return httpPortValidator.getValidationStatus();
184181
}
185182

183+
public ValidationStatus languageServerPortValidationStatus() {
184+
return languageServerPortValidator.getValidationStatus();
185+
}
186+
186187
@Override
187188
public void setValues() {
188189
selectedLanguageProperty.setValue(workspacePreferences.getLanguage());
@@ -227,6 +228,9 @@ public void setValues() {
227228

228229
enableHttpServerProperty.setValue(remotePreferences.enableHttpServer());
229230
httpPortProperty.setValue(String.valueOf(remotePreferences.getHttpPort()));
231+
232+
enableLanguageServerProperty.setValue(remotePreferences.enableLanguageServer());
233+
languageServerPortProperty.setValue(String.valueOf(remotePreferences.getLanguageServerPort()));
230234
}
231235

232236
@Override
@@ -300,6 +304,12 @@ public void storeSettings() {
300304
}
301305
});
302306

307+
getPortAsInt(languageServerPortProperty.getValue()).ifPresent(newPort -> {
308+
if (remotePreferences.isDifferentLanguageServerPort(newPort)) {
309+
remotePreferences.setLanguageServerPort(newPort);
310+
}
311+
});
312+
303313
HttpServerManager httpServerManager = Injector.instantiateModelOrService(HttpServerManager.class);
304314
// stop in all cases, because the port might have changed
305315
httpServerManager.stop();
@@ -312,6 +322,17 @@ public void storeSettings() {
312322
httpServerManager.stop();
313323
}
314324

325+
LanguageServerController languageServerController = Injector.instantiateModelOrService(LanguageServerController.class);
326+
// stop in all cases, because the port might have changed (or other settings that can't be easily tracked https://github.com/JabRef/jabref/pull/13697#discussion_r2285997003)
327+
languageServerController.stop();
328+
if (enableLanguageServerProperty.getValue()) {
329+
remotePreferences.setEnableLanguageServer(true);
330+
languageServerController.start(remotePreferences.getLanguageServerPort());
331+
} else {
332+
remotePreferences.setEnableLanguageServer(false);
333+
languageServerController.stop();
334+
}
335+
315336
trustStoreManager.flush();
316337
}
317338

@@ -335,6 +356,10 @@ public boolean validateSettings() {
335356
validator.addValidators(httpPortValidator);
336357
}
337358

359+
if (enableLanguageServerProperty.getValue()) {
360+
validator.addValidators(languageServerPortValidator);
361+
}
362+
338363
if (fontOverrideProperty.getValue()) {
339364
validator.addValidators(fontSizeValidator);
340365
}
@@ -477,6 +502,14 @@ public StringProperty httpPortProperty() {
477502
return httpPortProperty;
478503
}
479504

505+
public BooleanProperty enableLanguageServerProperty() {
506+
return enableLanguageServerProperty;
507+
}
508+
509+
public StringProperty languageServerPortProperty() {
510+
return languageServerPortProperty;
511+
}
512+
480513
public void openBrowser() {
481514
String url = "https://themes.jabref.org";
482515
try {

jabgui/src/main/resources/org/jabref/gui/preferences/general/GeneralTab.fxml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@
8989
<TextField fx:id="httpServerPort" maxWidth="100.0" HBox.hgrow="ALWAYS" />
9090
</HBox>
9191

92+
<Label styleClass="sectionHeader" text="%Language Server" />
93+
<HBox alignment="CENTER_LEFT" spacing="10.0">
94+
<CheckBox fx:id="enableLanguageServer" text="%Enable Language Server on port" />
95+
<TextField fx:id="languageServerPort" maxWidth="100.0" HBox.hgrow="ALWAYS" />
96+
</HBox>
97+
9298
<Label styleClass="sectionHeader" text="%Libraries"/>
9399
<GridPane hgap="10.0" vgap="4.0">
94100
<columnConstraints>

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ public class JabRefCliPreferences implements CliPreferences {
374374
private static final String REMOTE_SERVER_PORT = "remoteServerPort";
375375
private static final String HTTP_SERVER_PORT = "httpServerPort";
376376
private static final String ENABLE_HTTP_SERVER = "enableHttpServer";
377+
private static final String ENABLE_LANGUAGE_SERVER = "enableLanguageServer";
378+
private static final String LANGUAGE_SERVER_PORT = "languageServerPort";
377379

378380
private static final String AI_ENABLED = "aiEnabled";
379381
private static final String AI_AUTO_GENERATE_EMBEDDINGS = "aiAutoGenerateEmbeddings";
@@ -673,6 +675,8 @@ public JabRefCliPreferences() {
673675
defaults.put(REMOTE_SERVER_PORT, 6050);
674676
defaults.put(ENABLE_HTTP_SERVER, Boolean.FALSE);
675677
defaults.put(HTTP_SERVER_PORT, 23119);
678+
defaults.put(ENABLE_LANGUAGE_SERVER, Boolean.FALSE);
679+
defaults.put(LANGUAGE_SERVER_PORT, 2087);
676680

677681
defaults.put(EXTERNAL_JOURNAL_LISTS, "");
678682
defaults.put(USE_AMS_FJOURNAL, true);
@@ -1384,12 +1388,16 @@ public RemotePreferences getRemotePreferences() {
13841388
getInt(REMOTE_SERVER_PORT),
13851389
getBoolean(USE_REMOTE_SERVER),
13861390
getInt(HTTP_SERVER_PORT),
1387-
getBoolean(ENABLE_HTTP_SERVER));
1391+
getBoolean(ENABLE_HTTP_SERVER),
1392+
getBoolean(ENABLE_LANGUAGE_SERVER),
1393+
getInt(LANGUAGE_SERVER_PORT));
13881394

13891395
EasyBind.listen(remotePreferences.portProperty(), (_, _, newValue) -> putInt(REMOTE_SERVER_PORT, newValue));
13901396
EasyBind.listen(remotePreferences.useRemoteServerProperty(), (_, _, newValue) -> putBoolean(USE_REMOTE_SERVER, newValue));
13911397
EasyBind.listen(remotePreferences.httpPortProperty(), (_, _, newValue) -> putInt(HTTP_SERVER_PORT, newValue));
13921398
EasyBind.listen(remotePreferences.enableHttpServerProperty(), (_, _, newValue) -> putBoolean(ENABLE_HTTP_SERVER, newValue));
1399+
EasyBind.listen(remotePreferences.languageServerPortProperty(), (_, _, newValue) -> putInt(LANGUAGE_SERVER_PORT, newValue));
1400+
EasyBind.listen(remotePreferences.enableLanguageServerProperty(), (_, _, newValue) -> putBoolean(ENABLE_LANGUAGE_SERVER, newValue));
13931401

13941402
return remotePreferences;
13951403
}

jablib/src/main/java/org/jabref/logic/remote/RemotePreferences.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,16 @@ public class RemotePreferences {
2727
private final IntegerProperty httpPort;
2828
private final BooleanProperty enableHttpServer;
2929

30-
public RemotePreferences(int port, boolean useRemoteServer, int httpPort, boolean enableHttpServer) {
30+
private final BooleanProperty enableLanguageServer;
31+
private final IntegerProperty languageServerPort;
32+
33+
public RemotePreferences(int port, boolean useRemoteServer, int httpPort, boolean enableHttpServer, boolean enableLanguageServer, int languageServerPort) {
3134
this.port = new SimpleIntegerProperty(port);
3235
this.useRemoteServer = new SimpleBooleanProperty(useRemoteServer);
3336
this.httpPort = new SimpleIntegerProperty(httpPort);
3437
this.enableHttpServer = new SimpleBooleanProperty(enableHttpServer);
38+
this.enableLanguageServer = new SimpleBooleanProperty(enableLanguageServer);
39+
this.languageServerPort = new SimpleIntegerProperty(languageServerPort);
3540
}
3641

3742
public int getPort() {
@@ -90,6 +95,34 @@ public void setEnableHttpServer(boolean enableHttpServer) {
9095
this.enableHttpServer.setValue(enableHttpServer);
9196
}
9297

98+
public int getLanguageServerPort() {
99+
return languageServerPort.getValue();
100+
}
101+
102+
public IntegerProperty languageServerPortProperty() {
103+
return languageServerPort;
104+
}
105+
106+
public void setLanguageServerPort(int languageServerPort) {
107+
this.languageServerPort.setValue(languageServerPort);
108+
}
109+
110+
public boolean isDifferentLanguageServerPort(int otherLanguageServerPort) {
111+
return getLanguageServerPort() != otherLanguageServerPort;
112+
}
113+
114+
public boolean enableLanguageServer() {
115+
return enableLanguageServer.getValue();
116+
}
117+
118+
public BooleanProperty enableLanguageServerProperty() {
119+
return enableLanguageServer;
120+
}
121+
122+
public void setEnableLanguageServer(boolean enableLanguageServer) {
123+
this.enableLanguageServer.setValue(enableLanguageServer);
124+
}
125+
93126
/// Gets the IP address where both the remote server and the http server are listening.
94127
public static InetAddress getIpAddress() throws UnknownHostException {
95128
return InetAddress.getByName("localhost");

jablib/src/main/java/org/jabref/logic/remote/RemoteUtil.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,13 @@ private RemoteUtil() {
88
public static boolean isUserPort(int portNumber) {
99
return (portNumber >= 1024) && (portNumber <= 65535);
1010
}
11+
12+
public static boolean isStringUserPort(String portString) {
13+
try {
14+
int portNumber = Integer.parseInt(portString);
15+
return isUserPort(portNumber);
16+
} catch (NumberFormatException e) {
17+
return false;
18+
}
19+
}
1120
}

0 commit comments

Comments
 (0)