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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2018, 2026 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
Expand All @@ -10,14 +10,22 @@
*******************************************************************************/
package org.springframework.ide.vscode.bosh.bootiful;

import java.util.Optional;
import java.util.function.Consumer;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ide.vscode.bosh.BoshCliConfig;
import org.springframework.ide.vscode.bosh.mocks.MockCloudConfigProvider;
import org.springframework.ide.vscode.commons.languageserver.LanguageServerRunner;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.testharness.HarnessLanguageServerRunner;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;

import com.google.gson.GsonBuilder;

@Configuration
public class BoshLanguageServerTestConfiguration {

Expand All @@ -32,4 +40,11 @@ public class BoshLanguageServerTestConfiguration {
);
return harness;
}

@ConditionalOnMissingBean(LanguageServerRunner.class)
@Bean
HarnessLanguageServerRunner harnessLanguageServerRunner(Optional<Consumer<GsonBuilder>> configGsonOpt) {
return new HarnessLanguageServerRunner(configGsonOpt);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@
package org.springframework.ide.vscode.commons.java;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -142,5 +148,37 @@ public static Predicate<IJavaProject> libraryVersionGreaterOrEqual(String librar
return true;
};
}

/**
* Finds Spring Boot application.properties and application.yml files in the project's resource folders.
* Prioritizes main application.properties/yml files over profile-specific files (application-*.properties/yml).
* Excludes test resources.
*
* @param project the Java project
* @return list of Boot properties/YAML file paths, with main files prioritized over profile-specific files
*/
public static List<Path> findBootPropertiesFiles(IJavaProject project) {
try {
return project.getClasspath().getClasspathEntries().stream()
.filter(Classpath::isSource)
.filter(cpe -> !cpe.isTest()) // Exclude test resources
.filter(cpe -> !cpe.isJavaContent()) // Only resource folders
.map(cpe -> new File(cpe.getPath()).toPath())
.flatMap(folder -> {
try {
return Files.list(folder);
} catch (IOException e) {
return Stream.empty();
}
})
.filter(path -> path.getFileName().toString().matches("application(-.*)?\\.(properties|ya?ml)"))
.toList();
} catch (Exception e) {
// ignore
return Collections.emptyList();
}

}


}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2019 Pivotal, Inc.
* Copyright (c) 2016, 2026 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
Expand All @@ -21,6 +21,7 @@
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.Channels;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
Expand All @@ -39,6 +40,7 @@
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
Expand Down Expand Up @@ -101,14 +103,16 @@ public void run(String... args) throws Exception {

private Function<MessageConsumer, MessageConsumer> messageConsumer;

private Consumer<GsonBuilder> configureGson;
private Optional<Consumer<GsonBuilder>> configureGsonOpt;

Launcher<STS4LanguageClient> launcher;

public LanguageServerRunner(LanguageServerProperties properties, SimpleLanguageServer languageServer, Function<MessageConsumer, MessageConsumer> messageConsumer, Consumer<GsonBuilder> configureGson) {
public LanguageServerRunner(LanguageServerProperties properties, SimpleLanguageServer languageServer, Function<MessageConsumer, MessageConsumer> messageConsumer, Optional<Consumer<GsonBuilder>> configureGsonOpt) {
super();
this.properties = properties;
this.languageServer = languageServer;
this.messageConsumer = messageConsumer;
this.configureGson = configureGson;
this.configureGsonOpt = configureGsonOpt;
}

public void start() throws Exception {
Expand Down Expand Up @@ -189,7 +193,7 @@ public void startAsServer() throws Exception {
int serverPort = properties.getStandalonePort();
log.info("Starting LS as standlone server port = {}", serverPort);

Launcher<STS4LanguageClient> launcher = createSocketLauncher(languageServer, STS4LanguageClient.class,
launcher = createSocketLauncher(languageServer, STS4LanguageClient.class,
new InetSocketAddress("localhost", serverPort), createServerThreads(), messageConsumer);

languageServer.connect(launcher.getRemoteProxy());
Expand All @@ -213,7 +217,7 @@ private <T> Launcher<T> createSocketLauncher(
AsynchronousSocketChannel socketChannel = serverSocket.accept().get();
log.info("Client connected via socket");
return Launcher.createIoLauncher(localService, remoteInterface, Channels.newInputStream(socketChannel),
Channels.newOutputStream(socketChannel), executorService, wrapper, configureGson);
Channels.newOutputStream(socketChannel), executorService, wrapper, configureGsonOpt.orElse(null));
}

private static Connection connectToNode() throws IOException {
Expand Down Expand Up @@ -241,13 +245,13 @@ private static Connection connectToNode() throws IOException {
private Future<Void> runAsync(Connection connection) throws Exception {
LanguageServer server = this.languageServer;
ExecutorService executor = createServerThreads();
Launcher<STS4LanguageClient> launcher = Launcher.createIoLauncher(server,
launcher = Launcher.createIoLauncher(server,
STS4LanguageClient.class,
connection.in,
connection.out,
executor,
messageConsumer,
configureGson
configureGsonOpt.orElse(null)
);

if (server instanceof LanguageClientAware) {
Expand All @@ -258,4 +262,8 @@ private Future<Void> runAsync(Connection connection) throws Exception {
return launcher.startListening();
}

public Gson getGson() {
// Should only return successfully if connected to client
return launcher.getRemoteEndpoint().getJsonHandler().getGson();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2026 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
Expand All @@ -13,9 +13,8 @@
import java.util.ArrayList;
import java.util.List;

import org.eclipse.lsp4j.jsonrpc.util.ToStringBuilder;
import org.eclipse.lsp4j.jsonrpc.validation.NonNull;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;

/**
* Model object to be used in <code>client/registerCapability</code> JSON message to register file watchers
Expand All @@ -36,7 +35,6 @@ public DidChangeWatchedFilesRegistrationOptions(@NonNull final List<FileSystemWa
this.watchers = watchers;
}

@Pure
@NonNull
public List<FileSystemWatcher> getRegistrations() {
return this.watchers;
Expand All @@ -47,15 +45,13 @@ public void setRegistrations(@NonNull final List<FileSystemWatcher> watchers) {
}

@Override
@Pure
public String toString() {
ToStringBuilder b = new ToStringBuilder(this);
b.add("watchers", this.watchers);
return b.toString();
}

@Override
@Pure
public boolean equals(final Object obj) {
if (this == obj)
return true;
Expand All @@ -73,7 +69,6 @@ public boolean equals(final Object obj) {
}

@Override
@Pure
public int hashCode() {
final int prime = 31;
int result = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, Inc.
* Copyright (c) 2017, 2026 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
Expand All @@ -10,9 +10,8 @@
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.json;

import org.eclipse.lsp4j.jsonrpc.util.ToStringBuilder;
import org.eclipse.lsp4j.jsonrpc.validation.NonNull;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;

/**
* Model object to be used in <code>client/registerCapability</code> JSON message to register a file watcher
Expand Down Expand Up @@ -54,7 +53,6 @@ public FileSystemWatcher(@NonNull final String globPattern, final int kind) {
this.kind = kind;
}

@Pure
@NonNull
public String getGlobPattern() {
return this.globPattern;
Expand All @@ -64,7 +62,6 @@ public void setGlobPattern(@NonNull final String globPattern) {
this.globPattern = globPattern;
}

@Pure
@NonNull
public int getKind() {
return this.kind;
Expand All @@ -78,7 +75,6 @@ public void setKind(final int kind) {
}

@Override
@Pure
public String toString() {
ToStringBuilder b = new ToStringBuilder(this);
b.add("globPattern", this.globPattern);
Expand All @@ -87,7 +83,6 @@ public String toString() {
}

@Override
@Pure
public boolean equals(final Object obj) {
if (this == obj)
return true;
Expand All @@ -107,7 +102,6 @@ public boolean equals(final Object obj) {
}

@Override
@Pure
public int hashCode() {
final int prime = 31;
int result = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016, 2024 VMware Inc.
* Copyright (c) 2016, 2026 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
Expand Down Expand Up @@ -81,6 +81,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.ide.vscode.commons.languageserver.DiagnosticService;
import org.springframework.ide.vscode.commons.languageserver.LanguageServerRunner;
import org.springframework.ide.vscode.commons.languageserver.MessageService;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.Sts4LanguageServer;
Expand Down Expand Up @@ -261,6 +262,10 @@ public SimpleLanguageServer(String extensionId, ApplicationContext appContext, L
this.CODE_ACTION_COMMAND_ID = "sts."+EXTENSION_ID+".codeAction";
this.COMMAND_LIST_COMMAND_ID = "sts." + EXTENSION_ID + ".commandList";
}

public Gson getGson() {
return appContext.getBean(LanguageServerRunner.class).getGson();
}

protected CompletableFuture<Object> executeCommand(ExecuteCommandParams params) {
ExecuteCommandHandler handler = commands.get(params.getCommand());
Expand All @@ -286,7 +291,7 @@ protected CompletableFuture<Object> executeCommand(ExecuteCommandParams params)
})
.toFuture();
} else if (COMMAND_LIST_COMMAND_ID.equals(params.getCommand())) {
Gson gson = new Gson();
Gson gson = getGson();
CompletableFuture<Object> execution = CompletableFuture.completedFuture(null);
for (Object json : params.getArguments()) {
Command cmd = json instanceof Command ? (Command) json : gson.fromJson(json instanceof JsonElement ? (JsonElement) json : gson.toJsonTree(json), Command.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2023, 2025 VMware, Inc.
* Copyright (c) 2023, 2026 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
Expand All @@ -17,7 +17,6 @@
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.SymbolKind;

import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;

public class Bean extends AbstractSpringIndexElement implements SymbolElement {
Expand All @@ -26,7 +25,7 @@ public class Bean extends AbstractSpringIndexElement implements SymbolElement {
private final String type;
private final Location location;
private final InjectionPoint[] injectionPoints;
private final Set<String> supertypes;
private final String[] supertypes;
private final AnnotationMetadata[] annotations;
private final boolean isConfiguration;
private final String symbolLabel;
Expand Down Expand Up @@ -61,7 +60,7 @@ public Bean(
this.supertypes = null;
}
else {
this.supertypes = sanitizedSuperTypes;
this.supertypes = sanitizedSuperTypes == null ? null : sanitizedSuperTypes.toArray(new String[sanitizedSuperTypes.size()]);
}

if (annotations != null && annotations.length == 0) {
Expand Down Expand Up @@ -89,7 +88,7 @@ public InjectionPoint[] getInjectionPoints() {
}

public boolean isTypeCompatibleWith(String type) {
return type != null && ((this.type != null && this.type.equals(type)) || (supertypes != null && supertypes.contains(type)) || (Object.class.getName().equals(type) && !isInterface));
return type != null && ((this.type != null && this.type.equals(type)) || (supertypes != null && Set.of(supertypes).contains(type)) || (Object.class.getName().equals(type) && !isInterface));
}

public AnnotationMetadata[] getAnnotations() {
Expand All @@ -104,7 +103,14 @@ public Set<String> getSupertypes() {
if (supertypes == null) {
return isInterface ? DefaultValues.EMPTY_SUPERTYPES : DefaultValues.OBJECT_SUPERTYPE;
} else {
return isInterface ? supertypes : ImmutableSet.<String>builder().addAll(supertypes).add(Object.class.getName()).build();
if (isInterface) {
return Set.of(supertypes);
} else {
String[] all = new String[supertypes.length + 1];
System.arraycopy(supertypes, 0, all, 0, supertypes.length);
all[all.length - 1] = Object.class.getName();
return Set.of(all);
}
}
}

Expand Down
Loading