diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java
index d1497c6c1c..e7368134bc 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/Preferences.java
@@ -40,6 +40,8 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import org.apache.commons.lang3.text.StrLookup;
+import org.apache.commons.lang3.text.StrSubstitutor;
import org.eclipse.core.internal.resources.PreferenceInitializer;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
@@ -114,7 +116,8 @@ public class Preferences {
public static final String JAVA_SYMBOLS_INCLUDE_SOURCE_METHOD_DECLARATIONS = "java.symbols.includeSourceMethodDeclarations";
/**
- * Include generated code (e.g. Lombok getters, setters, constructors) in document symbols.
+ * Include generated code (e.g. Lombok getters, setters, constructors) in
+ * document symbols.
*/
public static final String JAVA_SYMBOLS_INCLUDE_GENERATED_CODE = "java.symbols.includeGeneratedCode";
@@ -357,7 +360,8 @@ public class Preferences {
public static final String COMPLETION_MATCH_CASE_MODE_KEY = "java.completion.matchCase";
/**
- * Preference key to specify whether text edit of completion item can be lazily resolved.
+ * Preference key to specify whether text edit of completion item can be lazily
+ * resolved.
*/
public static final String COMPLETION_LAZY_RESOLVE_TEXT_EDIT_ENABLED_KEY = "java.completion.lazyResolveTextEdit.enabled";
@@ -561,10 +565,11 @@ public class Preferences {
public static final String CHAIN_COMPLETION_KEY = "java.completion.chain.enabled";
/**
- * Preference key to set the scope value to use when searching java code. Allowed value are
+ * Preference key to set the scope value to use when searching java code.
+ * Allowed value are
*
- * main - Scope for main code
- * all - Scope for both test and main code
+ * main - Scope for main code
+ * all - Scope for both test and main code
*
* Any other unknown value will be treated as all.
*/
@@ -789,7 +794,7 @@ static Severity fromString(String value, Severity defaultSeverity) {
String val = value.toLowerCase();
try {
return valueOf(val);
- } catch(Exception e) {
+ } catch (Exception e) {
//fall back to default severity
}
}
@@ -808,14 +813,14 @@ public MessageType toMessageType() {
}
public static enum FeatureStatus {
- disabled, interactive, automatic ;
+ disabled, interactive, automatic;
static FeatureStatus fromString(String value, FeatureStatus defaultStatus) {
if (value != null) {
String val = value.toLowerCase();
try {
return valueOf(val);
- } catch(Exception e) {
+ } catch (Exception e) {
//fall back to default severity
}
}
@@ -831,7 +836,7 @@ static SearchScope fromString(String value, SearchScope defaultScope) {
String val = value.toLowerCase();
try {
return valueOf(val);
- } catch(Exception e) {
+ } catch (Exception e) {
//fall back to default severity
}
}
@@ -909,9 +914,7 @@ public boolean equals(Object obj) {
return false;
}
ReferencedLibraries other = (ReferencedLibraries) obj;
- return Objects.equals(include, other.include)
- && Objects.equals(exclude, other.exclude)
- && Objects.equals(sources, other.sources);
+ return Objects.equals(include, other.include) && Objects.equals(exclude, other.exclude) && Objects.equals(sources, other.sources);
}
}
@@ -1058,7 +1061,8 @@ private static List getClasspathSubStringFromArtifact(String artifact) {
/**
* Create a {@link Preferences} model from a {@link Map} configuration.
*
- * @param configuration the configuration map to apply
+ * @param configuration
+ * the configuration map to apply
* @return a new Preferences object with the configuration applied
*/
public static Preferences createFrom(Map configuration) {
@@ -1068,11 +1072,16 @@ public static Preferences createFrom(Map configuration) {
/**
* Creates a deep copy of this Preferences object.
*
- * Collections are deep copied to prevent shared state. Note that:
+ *
+ * Collections are deep copied to prevent shared state. Note that:
+ *
*
- * - The configuration map itself is copied, but values within it are not (shallow copy of values)
- * - RuntimeEnvironment objects are copied by reference (shared between original and clone)
- * - IPath objects are copied by reference (safe since IPath is immutable)
+ * - The configuration map itself is copied, but values within it are not
+ * (shallow copy of values)
+ * - RuntimeEnvironment objects are copied by reference (shared between
+ * original and clone)
+ * - IPath objects are copied by reference (safe since IPath is
+ * immutable)
*
*
* @return a new Preferences object with the same values as this one
@@ -1202,11 +1211,7 @@ public Preferences clone() {
// Deep copy complex objects
if (this.referencedLibraries != null) {
- prefs.referencedLibraries = new ReferencedLibraries(
- new HashSet<>(this.referencedLibraries.getInclude()),
- new HashSet<>(this.referencedLibraries.getExclude()),
- new HashMap<>(this.referencedLibraries.getSources())
- );
+ prefs.referencedLibraries = new ReferencedLibraries(new HashSet<>(this.referencedLibraries.getInclude()), new HashSet<>(this.referencedLibraries.getExclude()), new HashMap<>(this.referencedLibraries.getSources()));
}
// Copy collection fields (these are typically not modified after creation)
@@ -1218,11 +1223,15 @@ public Preferences clone() {
}
/**
- * Create an updated {@link Preferences} model from an existing preferences and a {@link Map} with partial configuration.
- * Only the settings present in the configuration will be updated, all other settings will be preserved from the existing preferences.
+ * Create an updated {@link Preferences} model from an existing preferences and
+ * a {@link Map} with partial configuration. Only the settings present in the
+ * configuration will be updated, all other settings will be preserved from the
+ * existing preferences.
*
- * @param existing the existing preferences to update
- * @param configuration the partial configuration with updated settings
+ * @param existing
+ * the existing preferences to update
+ * @param configuration
+ * the partial configuration with updated settings
* @return a new Preferences object with updated values
*/
@SuppressWarnings("unchecked")
@@ -1248,8 +1257,7 @@ public static Preferences updateFrom(Preferences existing, Map c
// Now update only the fields that are present in the partial configuration
if (containsKey(configuration, CONFIGURATION_UPDATE_BUILD_CONFIGURATION_KEY)) {
String updateBuildConfiguration = getString(configuration, CONFIGURATION_UPDATE_BUILD_CONFIGURATION_KEY, null);
- prefs.setUpdateBuildConfigurationStatus(
- FeatureStatus.fromString(updateBuildConfiguration, existing.updateBuildConfigurationStatus));
+ prefs.setUpdateBuildConfigurationStatus(FeatureStatus.fromString(updateBuildConfiguration, existing.updateBuildConfigurationStatus));
}
if (containsKey(configuration, IMPORT_GRADLE_ENABLED)) {
@@ -1445,12 +1453,10 @@ public static Preferences updateFrom(Preferences existing, Map c
if (containsKey(configuration, JAVA_COMPLETION_GUESS_METHOD_ARGUMENTS_KEY)) {
Object guessMethodArguments = getValue(configuration, JAVA_COMPLETION_GUESS_METHOD_ARGUMENTS_KEY);
if (guessMethodArguments instanceof Boolean b) {
- prefs.setGuessMethodArgumentsMode(b ? CompletionGuessMethodArgumentsMode.INSERT_BEST_GUESSED_ARGUMENTS :
- CompletionGuessMethodArgumentsMode.INSERT_PARAMETER_NAMES);
+ prefs.setGuessMethodArgumentsMode(b ? CompletionGuessMethodArgumentsMode.INSERT_BEST_GUESSED_ARGUMENTS : CompletionGuessMethodArgumentsMode.INSERT_PARAMETER_NAMES);
} else {
String guessMethodArgumentsMode = getString(configuration, JAVA_COMPLETION_GUESS_METHOD_ARGUMENTS_KEY, null);
- prefs.setGuessMethodArgumentsMode(CompletionGuessMethodArgumentsMode.fromString(guessMethodArgumentsMode,
- existing.guessMethodArguments));
+ prefs.setGuessMethodArgumentsMode(CompletionGuessMethodArgumentsMode.fromString(guessMethodArgumentsMode, existing.guessMethodArguments));
}
}
@@ -1847,7 +1853,7 @@ public static Preferences updateFrom(Preferences existing, Map c
if (containsKey(configuration, JAVA_CLEANUPS_ACTIONS_ON_SAVE_DEPRECATED) || containsKey(configuration, JAVA_CLEANUPS_ACTIONS)) {
List cleanupActionsTemp = getList(configuration, JAVA_CLEANUPS_ACTIONS_ON_SAVE_DEPRECATED, Collections.emptyList());
List cleanupActions = getList(configuration, JAVA_CLEANUPS_ACTIONS, Collections.emptyList());
- if(cleanupActions.isEmpty() && !cleanupActionsTemp.isEmpty()) {
+ if (cleanupActions.isEmpty() && !cleanupActionsTemp.isEmpty()) {
cleanupActions = cleanupActionsTemp;
}
prefs.setCleanUpActions(cleanupActions);
@@ -1941,7 +1947,7 @@ private static boolean validateFilePattern(String filename) {
* Sets the new value of the enabled clean ups.
*
* @param enabledCleanUps
- * the new list of enabled clean ups
+ * the new list of enabled clean ups
*/
public void setCleanUpActions(List enabledCleanUps) {
this.cleanUpActions = enabledCleanUps;
@@ -1987,12 +1993,12 @@ public Preferences setGradleUserHome(String gradleUserHome) {
}
public Preferences setFormatterUrl(String formatterUrl) {
- this.formatterUrl = ResourceUtils.expandPath(formatterUrl);
+ this.formatterUrl = ResourceUtils.expandPath(expandWorkspacePath(formatterUrl));
return this;
}
public Preferences setSettingsUrl(String settingsUrl) {
- this.settingsUrl = ResourceUtils.expandPath(settingsUrl);
+ this.settingsUrl = ResourceUtils.expandPath(expandWorkspacePath(settingsUrl));
return this;
}
@@ -3038,8 +3044,8 @@ public boolean isChainCompletionEnabled() {
}
/**
- * update the null analysis options of all projects based on the null analysis mode
- * Returns the list of enabled clean ups.
+ * update the null analysis options of all projects based on the null analysis
+ * mode Returns the list of enabled clean ups.
*
* @return the list of enabled clean ups
*/
@@ -3084,8 +3090,12 @@ private boolean updateAnnotationNullAnalysisOptions(boolean enabled) {
/**
* update the null analysis options of given project
- * @param javaProject the java project to update the annotation-based null analysis options
- * @param enabled specific whether the null analysis is enabled
+ *
+ * @param javaProject
+ * the java project to update the annotation-based null
+ * analysis options
+ * @param enabled
+ * specific whether the null analysis is enabled
* @return whether the options of the given project are changed or not
*/
public boolean updateAnnotationNullAnalysisOptions(IJavaProject javaProject, boolean enabled) {
@@ -3222,10 +3232,15 @@ private String findTypeInProject(IJavaProject javaProject, String annotationType
}
/**
- * generates the null analysis options of the given nonnull type and nullable type
- * @param nonnullType the given nonnull type
- * @param nullableType the given nullable type
- * @return the map contains the null analysis options, if both given types are null, will return default null analysis options
+ * generates the null analysis options of the given nonnull type and nullable
+ * type
+ *
+ * @param nonnullType
+ * the given nonnull type
+ * @param nullableType
+ * the given nullable type
+ * @return the map contains the null analysis options, if both given types are
+ * null, will return default null analysis options
*/
private Map generateProjectNullAnalysisOptions(String nonnullType, String nullableType, String nonnullbydefaultType) {
Map options = new HashMap<>();
@@ -3291,4 +3306,21 @@ public void setSearchScope(SearchScope value) {
public SearchScope getSearchScope() {
return searchScope;
}
+
+ private String expandWorkspacePath(String path) {
+ if (path == null || rootPaths == null || rootPaths.isEmpty())
+ return path;
+ StrLookup workspaceResolver = new StrLookup() {
+ @Override
+ public String lookup(String key) {
+ if (key == "workspace") {
+ String prop = getRootPaths().iterator().next().toOSString();
+ return prop;
+ }
+ return null;
+ }
+ };
+ StrSubstitutor strSubstitutor = new StrSubstitutor(workspaceResolver);
+ return strSubstitutor.replace(formatterUrl);
+ }
}