diff --git a/launch/jdt.ls.remote.server.launch b/launch/jdt.ls.remote.server.launch
index 1d8e1a2fcf..dcc44cfdee 100644
--- a/launch/jdt.ls.remote.server.launch
+++ b/launch/jdt.ls.remote.server.launch
@@ -36,7 +36,7 @@
-
+
diff --git a/launch/jdt.ls.socket-stream.launch b/launch/jdt.ls.socket-stream.launch
index 9dbec2e0b6..88b4236284 100644
--- a/launch/jdt.ls.socket-stream.launch
+++ b/launch/jdt.ls.socket-stream.launch
@@ -37,7 +37,7 @@
-
+
diff --git a/org.eclipse.jdt.ls.core/.classpath b/org.eclipse.jdt.ls.core/.classpath
index 5e3f97eca3..f16168535a 100644
--- a/org.eclipse.jdt.ls.core/.classpath
+++ b/org.eclipse.jdt.ls.core/.classpath
@@ -4,6 +4,7 @@
+
diff --git a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
index ff4cf7875e..87d440ef96 100644
--- a/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.ls.core/META-INF/MANIFEST.MF
@@ -62,6 +62,7 @@ Export-Package: org.eclipse.jdt.ls.core.contentassist;x-friends:="org.eclipse.jd
org.eclipse.lsp4j.legacy.typeHierarchy;x-friends:="org.eclipse.jdt.ls.tests"
Bundle-ClassPath: lib/jsoup-1.14.2.jar,
lib/remark-1.2.0.jar,
+ lib/google-java-format-1.13.0.jar,
.
Bundle-Vendor: %Bundle-Vendor
Automatic-Module-Name: org.eclipse.jdt.ls.core
diff --git a/org.eclipse.jdt.ls.core/build.properties b/org.eclipse.jdt.ls.core/build.properties
index 26d037ace9..a0e3793b69 100644
--- a/org.eclipse.jdt.ls.core/build.properties
+++ b/org.eclipse.jdt.ls.core/build.properties
@@ -5,6 +5,7 @@ bin.includes = META-INF/,\
plugin.xml,\
lib/jsoup-1.14.2.jar,\
lib/remark-1.2.0.jar,\
+ lib/google-java-format-1.13.0.jar,\
lifecycle-mapping-metadata.xml,\
plugin.properties,\
gradle/checksums/checksums.json,\
diff --git a/org.eclipse.jdt.ls.core/pom.xml b/org.eclipse.jdt.ls.core/pom.xml
index 3dc4a33950..fdbb99786a 100644
--- a/org.eclipse.jdt.ls.core/pom.xml
+++ b/org.eclipse.jdt.ls.core/pom.xml
@@ -27,6 +27,11 @@
jsoup
1.14.2
+
+ com.google.googlejavaformat
+ google-java-format
+ 1.13.0
+
diff --git a/org.eclipse.jdt.ls.core/src/com/google/googlejavaformat/java/GoogleJavaFormatter.java b/org.eclipse.jdt.ls.core/src/com/google/googlejavaformat/java/GoogleJavaFormatter.java
new file mode 100644
index 0000000000..ab59910a18
--- /dev/null
+++ b/org.eclipse.jdt.ls.core/src/com/google/googlejavaformat/java/GoogleJavaFormatter.java
@@ -0,0 +1,130 @@
+package com.google.googlejavaformat.java;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Range;
+import com.google.googlejavaformat.java.SnippetFormatter.SnippetKind;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.formatter.CodeFormatter;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.text.edits.MultiTextEdit;
+import org.eclipse.text.edits.ReplaceEdit;
+import org.eclipse.text.edits.TextEdit;
+
+/** Runs the Google Java formatter on the given code. */
+public class GoogleJavaFormatter extends CodeFormatter {
+
+ private static final int INDENTATION_SIZE = 2;
+
+ @Override
+ public TextEdit format(
+ int kind, String source, int offset, int length, int indentationLevel, String lineSeparator) {
+ IRegion[] regions = new IRegion[] {new Region(offset, length)};
+ return formatInternal(kind, source, regions, indentationLevel);
+ }
+
+ @Override
+ public TextEdit format(
+ int kind, String source, IRegion[] regions, int indentationLevel, String lineSeparator) {
+ return formatInternal(kind, source, regions, indentationLevel);
+ }
+
+ @Override
+ public String createIndentationString(int indentationLevel) {
+ Preconditions.checkArgument(
+ indentationLevel >= 0,
+ "Indentation level cannot be less than zero. Given: %s",
+ indentationLevel);
+ int spaces = indentationLevel * INDENTATION_SIZE;
+ StringBuilder buf = new StringBuilder(spaces);
+ for (int i = 0; i < spaces; i++) {
+ buf.append(' ');
+ }
+ return buf.toString();
+ }
+
+ /** Runs the Google Java formatter on the given source, with only the given ranges specified. */
+ private TextEdit formatInternal(int kind, String source, IRegion[] regions, int initialIndent) {
+ try {
+ boolean includeComments =
+ (kind & CodeFormatter.F_INCLUDE_COMMENTS) == CodeFormatter.F_INCLUDE_COMMENTS;
+ kind &= ~CodeFormatter.F_INCLUDE_COMMENTS;
+ SnippetKind snippetKind;
+ switch (kind) {
+ case ASTParser.K_EXPRESSION:
+ snippetKind = SnippetKind.EXPRESSION;
+ break;
+ case ASTParser.K_STATEMENTS:
+ snippetKind = SnippetKind.STATEMENTS;
+ break;
+ case ASTParser.K_CLASS_BODY_DECLARATIONS:
+ snippetKind = SnippetKind.CLASS_BODY_DECLARATIONS;
+ break;
+ case ASTParser.K_COMPILATION_UNIT:
+ snippetKind = SnippetKind.COMPILATION_UNIT;
+ break;
+ default:
+ throw new IllegalArgumentException(String.format("Unknown snippet kind: %d", kind));
+ }
+ List replacements =
+ new SnippetFormatter()
+ .format(
+ snippetKind, source, rangesFromRegions(regions), initialIndent, includeComments);
+ if (idempotent(source, regions, replacements)) {
+ // Do not create edits if there's no diff.
+ return null;
+ }
+ // Convert replacements to text edits.
+ return editFromReplacements(replacements);
+ } catch (IllegalArgumentException | FormatterException exception) {
+ // Do not format on errors.
+ return null;
+ }
+ }
+
+ private List> rangesFromRegions(IRegion[] regions) {
+ List> ranges = new ArrayList<>();
+ for (IRegion region : regions) {
+ ranges.add(Range.closedOpen(region.getOffset(), region.getOffset() + region.getLength()));
+ }
+ return ranges;
+ }
+
+ /** @return {@code true} if input and output texts are equal, else {@code false}. */
+ private boolean idempotent(String source, IRegion[] regions, List replacements) {
+ // This implementation only checks for single replacement.
+ if (replacements.size() == 1) {
+ Replacement replacement = replacements.get(0);
+ String output = replacement.getReplacementString();
+ // Entire source case: input = output, nothing changed.
+ if (output.equals(source)) {
+ return true;
+ }
+ // Single region and single replacement case: if they are equal, nothing changed.
+ if (regions.length == 1) {
+ Range range = replacement.getReplaceRange();
+ String snippet = source.substring(range.lowerEndpoint(), range.upperEndpoint());
+ if (output.equals(snippet)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private TextEdit editFromReplacements(List replacements) {
+ // Split the replacements that cross line boundaries.
+ TextEdit edit = new MultiTextEdit();
+ for (Replacement replacement : replacements) {
+ Range replaceRange = replacement.getReplaceRange();
+ edit.addChild(
+ new ReplaceEdit(
+ replaceRange.lowerEndpoint(),
+ replaceRange.upperEndpoint() - replaceRange.lowerEndpoint(),
+ replacement.getReplacementString()));
+ }
+ return edit;
+ }
+}
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FormatterHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FormatterHandler.java
index 2b44431a97..e5922de679 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FormatterHandler.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FormatterHandler.java
@@ -38,7 +38,9 @@
import org.eclipse.jdt.internal.ui.preferences.formatter.ProfileVersionerCore;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
+import org.eclipse.jdt.ls.core.internal.preferences.FormatterPreferences;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
+import org.eclipse.jdt.ls.core.internal.preferences.Preferences.FormatterScheme;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
@@ -56,6 +58,8 @@
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
+import com.google.googlejavaformat.java.GoogleJavaFormatter;
+
/**
* @author IBM Corporation (Markus Keller)
*/
@@ -108,18 +112,29 @@ private List format(ICompilationUnit cu, IDocument d
return Collections.emptyList();
}
- CodeFormatter formatter = ToolFactory.createCodeFormatter(getOptions(options, cu));
+ CodeFormatter formatter;
+ if (this.preferenceManager.getPreferences().getFormatterScheme().equals(FormatterScheme.google)) {
+ formatter = new GoogleJavaFormatter();
+ } else {
+ formatter = ToolFactory.createCodeFormatter(getOptions(options, cu));
+ }
String lineDelimiter = TextUtilities.getDefaultLineDelimiter(document);
String sourceToFormat = document.get();
int kind = getFormattingKind(cu, includeComments);
- TextEdit format = formatter.format(kind, sourceToFormat, region.getOffset(), region.getLength(), 0, lineDelimiter);
- if (format == null || format.getChildren().length == 0 || monitor.isCanceled()) {
- // nothing to return
- return Collections.emptyList();
+
+ try {
+ TextEdit format = formatter.format(kind, sourceToFormat, region.getOffset(), region.getLength(), 0, lineDelimiter);
+ if (format == null || format.getChildren().length == 0 || monitor.isCanceled()) {
+ // nothing to return
+ return Collections.emptyList();
+ }
+ MultiTextEdit flatEdit = TextEditUtil.flatten(format);
+ return convertEdits(flatEdit.getChildren(), document);
+ } catch (Throwable e) {
+ JavaLanguageServerPlugin.logException(e);
}
- MultiTextEdit flatEdit = TextEditUtil.flatten(format);
- return convertEdits(flatEdit.getChildren(), document);
+ return Collections.emptyList();
}
private int getFormattingKind(ICompilationUnit cu, boolean includeComments) {
@@ -150,6 +165,7 @@ public static Map getOptions(FormattingOptions options, ICompila
Map customOptions = options.entrySet().stream().filter(map -> chekIfValueIsNotNull(map.getValue())).collect(toMap(e -> e.getKey(), e -> getOptionValue(e.getValue())));
eclipseOptions.putAll(customOptions);
+ eclipseOptions.putAll(FormatterPreferences.toEclipseOptions(JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getFormatterSettings()));
Integer tabSize = options.getTabSize();
if (tabSize != null) {
diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/FormatterPreferences.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/FormatterPreferences.java
new file mode 100644
index 0000000000..e548341e50
--- /dev/null
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/FormatterPreferences.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Red Hat Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Microsoft Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.ls.core.internal.preferences;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+
+public class FormatterPreferences {
+
+ // @formatter:off
+ // < JDTLS settings, eclipse settings >
+ private static Map eclipseOptions = Map.ofEntries(
+ Map.entry("lineSplit", DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT),
+ Map.entry("comment.line.length", DefaultCodeFormatterConstants.FORMATTER_COMMENT_LINE_LENGTH),
+ Map.entry("join.wrapped.lines", DefaultCodeFormatterConstants.FORMATTER_JOIN_WRAPPED_LINES),
+ Map.entry("use.on.off.tags", DefaultCodeFormatterConstants.FORMATTER_USE_ON_OFF_TAGS),
+ Map.entry("disabling.tag", DefaultCodeFormatterConstants.FORMATTER_DISABLING_TAG),
+ Map.entry("enabling.tag", DefaultCodeFormatterConstants.FORMATTER_ENABLING_TAG),
+ Map.entry("indent.parameter.description", DefaultCodeFormatterConstants.FORMATTER_COMMENT_INDENT_PARAMETER_DESCRIPTION),
+ Map.entry("indent.root.tags", DefaultCodeFormatterConstants.FORMATTER_COMMENT_INDENT_ROOT_TAGS),
+ Map.entry("align.tags.descriptions.grouped", DefaultCodeFormatterConstants.FORMATTER_COMMENT_ALIGN_TAGS_DESCREIPTIONS_GROUPED),
+ Map.entry("align.tags.names.descriptions", DefaultCodeFormatterConstants.FORMATTER_COMMENT_ALIGN_TAGS_NAMES_DESCRIPTIONS),
+ Map.entry("clear.blank.lines.in.javadoc.comment", DefaultCodeFormatterConstants.FORMATTER_COMMENT_CLEAR_BLANK_LINES_IN_JAVADOC_COMMENT),
+ Map.entry("blank.lines.between.import.groups", DefaultCodeFormatterConstants.FORMATTER_BLANK_LINES_BETWEEN_IMPORT_GROUPS),
+ Map.entry("format.line.comments", DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_LINE_COMMENT),
+ Map.entry("format.block.comments", DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_BLOCK_COMMENT),
+ Map.entry("format.javadoc.comments", DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT_JAVADOC_COMMENT),
+ Map.entry("keep.loop.body.block.on.one.line", DefaultCodeFormatterConstants.FORMATTER_KEEP_LOOP_BODY_BLOCK_ON_ONE_LINE),
+ Map.entry("keep.anonymous.type.declaration.on.one.line", DefaultCodeFormatterConstants.FORMATTER_KEEP_ANONYMOUS_TYPE_DECLARATION_ON_ONE_LINE),
+ Map.entry("keep.type.declaration.on.one.line", DefaultCodeFormatterConstants.FORMATTER_KEEP_TYPE_DECLARATION_ON_ONE_LINE),
+ Map.entry("keep.method.body.on.one.line", DefaultCodeFormatterConstants.FORMATTER_KEEP_METHOD_BODY_ON_ONE_LINE),
+ Map.entry("insert.space.after.closing.angle.bracket.in.type.arguments", DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENTS),
+ Map.entry("insert.space.after.opening.brace.in.array.initializer", DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_OPENING_BRACE_IN_ARRAY_INITIALIZER),
+ Map.entry("insert.space.before.closing.brace.in.array.initializer", DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_CLOSING_BRACE_IN_ARRAY_INITIALIZER),
+ Map.entry("brace.position.for.block", DefaultCodeFormatterConstants.FORMATTER_BRACE_POSITION_FOR_BLOCK),
+ Map.entry("alignment.for.enum.constants", DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_ENUM_CONSTANTS),
+ Map.entry("alignment.for.parameters.in.method.declaration", DefaultCodeFormatterConstants.FORMATTER_ALIGNMENT_FOR_PARAMETERS_IN_METHOD_DECLARATION)
+ );
+
+ // < JDTLS camelCase value, eclipse underline value>
+ private static Map valueMap = Map.ofEntries(
+ Map.entry("commonLines", "common_lines"),
+ Map.entry("separateLinesIfNotEmpty", "separate_lines_if_not_empty"),
+ Map.entry("separateLinesIfWrapped", "separate_lines_if_wrapped"),
+ Map.entry("separateLines", "separate_lines"),
+ Map.entry("preservePositions", "preserve_positions"),
+ Map.entry("never", "one_line_never"),
+ Map.entry("ifEmpty", "one_line_if_empty"),
+ Map.entry("ifSingleItem", "one_line_if_single_item"),
+ Map.entry("always", "one_line_always"),
+ Map.entry("preserve", "one_line_preserve"),
+ Map.entry("doNotInsert", "do not insert"),
+ Map.entry("endOfLine", "end_of_line"),
+ Map.entry("nextLine", "next_line"),
+ Map.entry("nextLineIndented", "next_line_indented"),
+ Map.entry("nextLineOnWrap", "next_line_on_wrap")
+ );
+ // @formatter:on
+
+ /**
+ * Convert known language server formatter options to eclipse formatter
+ * settings.
+ *
+ * @param lsOptions
+ * the given language server formatter options
+ * @return the converted eclipse formatter options
+ */
+ public static Map toEclipseOptions(Map lsOptions) {
+ return lsOptions.entrySet().stream().filter(option -> eclipseOptions.containsKey(option.getKey())).collect(Collectors.toMap(option -> eclipseOptions.get(option.getKey()), option -> {
+ String value = option.getValue();
+ if (valueMap.containsKey(value)) {
+ return valueMap.get(value);
+ }
+ return value;
+ }));
+ }
+
+ /**
+ * Convert language server formatter alignment value to eclipse formatter
+ * alignment value.
+ *
+ * @param alignmentValue
+ * the given language server formatter alignment value
+ * @return the converted eclipse formatter alignment value
+ */
+ public static String getEclipseAlignmentValue(Map alignmentValue) {
+ Object forceSplit = alignmentValue.getOrDefault("force.split", Boolean.FALSE);
+ Object indentationStyle = alignmentValue.getOrDefault("indentation.style", "indentDefault");
+ Object wrappingStyle = alignmentValue.getOrDefault("wrapping.style", "compact");
+ if (forceSplit instanceof Boolean forceSplitBoolean && indentationStyle instanceof String indentationStyleString && wrappingStyle instanceof String wrappingStyleString) {
+ int indentationStyleInt = 0;
+ switch (indentationStyleString) {
+ case "indentDefault":
+ indentationStyleInt = DefaultCodeFormatterConstants.INDENT_DEFAULT;
+ break;
+ case "indentOnColumn":
+ indentationStyleInt = DefaultCodeFormatterConstants.INDENT_ON_COLUMN;
+ break;
+ case "indentByOne":
+ indentationStyleInt = DefaultCodeFormatterConstants.INDENT_BY_ONE;
+ break;
+ default:
+ return null;
+ }
+ int wrappingStyleInt = 0;
+ switch (wrappingStyleString) {
+ case "noSplit":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_NO_SPLIT;
+ break;
+ case "compact":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_COMPACT;
+ break;
+ case "compactFirstBreak":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_COMPACT_FIRST_BREAK;
+ break;
+ case "onePerLine":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_ONE_PER_LINE;
+ break;
+ case "nextShifted":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_NEXT_SHIFTED;
+ break;
+ case "nextPerLine":
+ wrappingStyleInt = DefaultCodeFormatterConstants.WRAP_NEXT_PER_LINE;
+ break;
+ default:
+ return null;
+ }
+ return DefaultCodeFormatterConstants.createAlignmentValue(forceSplitBoolean, wrappingStyleInt, indentationStyleInt);
+ }
+ return null;
+ }
+}
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 1a54866d94..c73cbc3f51 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
@@ -114,6 +114,10 @@ public class Preferences {
*/
public static final String JAVA_CONFIGURATION_RUNTIMES = "java.configuration.runtimes";
public static final List JAVA_CONFIGURATION_RUNTIMES_DEFAULT;
+ /**
+ * Specifies the java formatter scheme.
+ */
+ public static final String JAVA_FORMATTER_SCHEME = "java.format.scheme";
/**
* Specifies the file path or url to the formatter xml url.
*/
@@ -619,6 +623,8 @@ public class Preferences {
private String formatterUrl;
private String settingsUrl;
private String formatterProfileName;
+ private Map formatterSettings;
+ private FormatterScheme formatterScheme;
private Collection rootPaths;
private Collection triggerFiles;
private Collection projectConfigurations;
@@ -722,6 +728,22 @@ static FeatureStatus fromString(String value, FeatureStatus defaultStatus) {
}
}
+ public static enum FormatterScheme {
+ eclipse, google;
+
+ static FormatterScheme fromString(String value, FormatterScheme defaultValue) {
+ if (value != null) {
+ String val = value.toLowerCase();
+ try {
+ return valueOf(val);
+ } catch (Exception e) {
+ //fall back to default severity
+ }
+ }
+ return defaultValue;
+ }
+ }
+
public static class ReferencedLibraries {
private Set include;
private Set exclude;
@@ -850,6 +872,8 @@ public Preferences() {
formatterUrl = null;
settingsUrl = null;
formatterProfileName = null;
+ formatterSettings = new HashMap<>();
+ formatterScheme = FormatterScheme.eclipse;
importOrder = JAVA_IMPORT_ORDER_DEFAULT;
filteredTypes = JAVA_COMPLETION_FILTERED_TYPES_DEFAULT;
parallelBuildsCount = PreferenceInitializer.PREF_MAX_CONCURRENT_BUILDS_DEFAULT;
@@ -1122,6 +1146,52 @@ public static Preferences createFrom(Map configuration) {
boolean javaFormatComments = getBoolean(configuration, JAVA_FORMAT_COMMENTS, true);
prefs.setJavaFormatComments(javaFormatComments);
+ String formatterSchemeString = getString(configuration, JAVA_FORMATTER_SCHEME);
+ if (formatterSchemeString != null) {
+ FormatterScheme formatterScheme = FormatterScheme.fromString(formatterSchemeString, FormatterScheme.eclipse);
+ if (formatterScheme != null) {
+ prefs.setFormatterScheme(formatterScheme);
+ }
+ } else {
+ Object formatterSchemeValue = getValue(configuration, JAVA_FORMATTER_SCHEME);
+ if (formatterSchemeValue instanceof Map) {
+ Map formatterSchemeValueMap = (Map) formatterSchemeValue;
+ Object style = formatterSchemeValueMap.getOrDefault("style", FormatterScheme.eclipse.toString());
+ if (style instanceof String schemeString) {
+ FormatterScheme formatterScheme = FormatterScheme.fromString(schemeString, FormatterScheme.eclipse);
+ if (formatterScheme != null) {
+ prefs.setFormatterScheme(formatterScheme);
+ }
+ }
+ Object path = formatterSchemeValueMap.getOrDefault("path", null);
+ if (path instanceof String pathString) {
+ prefs.setFormatterUrl(pathString);
+ }
+ Object profile = formatterSchemeValueMap.getOrDefault("profile", null);
+ if (profile instanceof String profileString) {
+ prefs.setFormatterProfileName(profileString);
+ }
+ Object configurations = formatterSchemeValueMap.getOrDefault("configurations", new HashMap<>());
+ if (configurations instanceof Map) {
+ Map configurationMap = (Map) configurations;
+ Map formatterSettingsMap = new HashMap<>();
+ configurationMap.forEach((k, v) -> {
+ Object value = v;
+ if (value instanceof Double d) {
+ value = d.intValue();
+ } else if (value instanceof Map) {
+ Map valueMap = (Map) value;
+ value = FormatterPreferences.getEclipseAlignmentValue(valueMap);
+ }
+ if (value != null) {
+ formatterSettingsMap.put(String.valueOf(k), String.valueOf(value));
+ }
+ });
+ prefs.setFormatterSettings(formatterSettingsMap);
+ }
+ }
+ }
+
List javaImportOrder = getList(configuration, JAVA_IMPORT_ORDER_KEY, JAVA_IMPORT_ORDER_DEFAULT);
prefs.setImportOrder(javaImportOrder);
@@ -1288,6 +1358,15 @@ public Preferences setSettingsUrl(String settingsUrl) {
return this;
}
+ public Preferences setFormatterSettings(Map formatterSettings) {
+ this.formatterSettings = formatterSettings;
+ return this;
+ }
+
+ public void setFormatterScheme(FormatterScheme formatterScheme) {
+ this.formatterScheme = formatterScheme;
+ }
+
public Preferences setResourceFilters(List resourceFilters) {
this.resourceFilters = resourceFilters == null ? new ArrayList<>() : resourceFilters;
return this;
@@ -1607,6 +1686,14 @@ public URI getFormatterAsURI() {
return asURI(formatterUrl);
}
+ public Map getFormatterSettings() {
+ return this.formatterSettings;
+ }
+
+ public FormatterScheme getFormatterScheme() {
+ return this.formatterScheme;
+ }
+
public String getSettingsUrl() {
return settingsUrl;
}