diff --git a/EclipseAdapter/EclipseAdapter.iml b/EclipseAdapter/EclipseAdapter.iml index 0086e73..e5b9abc 100644 --- a/EclipseAdapter/EclipseAdapter.iml +++ b/EclipseAdapter/EclipseAdapter.iml @@ -39,5 +39,6 @@ + \ No newline at end of file diff --git a/EclipseAdapter/src/krasa/formatter/adapter/EclipseJavaFormatterAdapter.java b/EclipseAdapter/src/krasa/formatter/adapter/EclipseJavaFormatterAdapter.java index 02b46a6..8889e2f 100644 --- a/EclipseAdapter/src/krasa/formatter/adapter/EclipseJavaFormatterAdapter.java +++ b/EclipseAdapter/src/krasa/formatter/adapter/EclipseJavaFormatterAdapter.java @@ -1,11 +1,8 @@ package krasa.formatter.adapter; -import com.intellij.pom.java.LanguageLevel; import krasa.formatter.eclipse.EclipseFormatterAdapter; import krasa.formatter.exception.FileDoesNotExistsException; import krasa.formatter.exception.FormattingFailedException; -import krasa.formatter.settings.Settings; -import org.eclipse.jdt.core.formatter.CodeFormatter; import org.eclipse.jdt.internal.formatter.DefaultCodeFormatter; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; @@ -24,12 +21,9 @@ public EclipseJavaFormatterAdapter(Map options) { } @Override - public String format(String text, int startOffset, int endOffset, LanguageLevel level) + public String format(int kind, String text, int startOffset, int length, int indentationLevel, String lineSeparator, String languageLevel) throws FileDoesNotExistsException { - LOG.debug("#formatInternal"); - if (endOffset > text.length()) { - endOffset = text.length(); - } + IDocument doc = new Document(); try { doc.set(text); @@ -76,20 +70,15 @@ public String format(String text, int startOffset, int endOffset, LanguageLevel * if offset is lower than 0, length is lower than 0 or length is greater than source length. */ - LOG.debug("#starting to format by eclipse formatter"); - TextEdit edit = defaultCodeFormatter.format( - CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS, text, startOffset, - endOffset - startOffset, 0, Settings.LINE_SEPARATOR); + TextEdit edit = defaultCodeFormatter.format(kind, text, startOffset, length, indentationLevel, lineSeparator); if (edit != null) { - LOG.debug("reformatting done"); edit.apply(doc); } else { - throw new FormattingFailedException(getErrorMessage(level)); + throw new FormattingFailedException(getErrorMessage(languageLevel)); } return doc.get(); } catch (IndexOutOfBoundsException e) { - LOG.debug(e); - throw new FormattingFailedException(getErrorMessage(level)); + throw new FormattingFailedException(e, getErrorMessage(languageLevel)); } catch (BadLocationException e) { throw new RuntimeException(e); } diff --git a/build.gradle.kts b/build.gradle.kts index 9121991..198499a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,7 +52,8 @@ repositories { // Configure Gradle IntelliJ Plugin - read more: https://github.com/JetBrains/gradle-intellij-plugin intellij { // version.set("2023.1") - version.set("2022.3") + version.set("LATEST-EAP-SNAPSHOT") +// version.set("2022.3") type.set("IC") // Target IDE Platform plugins.set(listOf("java")) } diff --git a/lib/eclipse/adapter.jar b/lib/eclipse/adapter.jar index 4f5e16e..87dfb7a 100644 Binary files a/lib/eclipse/adapter.jar and b/lib/eclipse/adapter.jar differ diff --git a/src/main/java/krasa/formatter/eclipse/EclipseFormatterAdapter.java b/src/main/java/krasa/formatter/eclipse/EclipseFormatterAdapter.java index 87df15a..986a355 100644 --- a/src/main/java/krasa/formatter/eclipse/EclipseFormatterAdapter.java +++ b/src/main/java/krasa/formatter/eclipse/EclipseFormatterAdapter.java @@ -1,16 +1,15 @@ package krasa.formatter.eclipse; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.pom.java.LanguageLevel; import krasa.formatter.exception.FileDoesNotExistsException; public abstract class EclipseFormatterAdapter { protected final Logger LOG = Logger.getInstance(this.getClass().getName()); - public abstract String format(String text, int startOffset, int endOffset, LanguageLevel level) + public abstract String format(int kind, String text, int startOffset, int length, int indentationLevel, String lineSeparator, String languageLevel) throws FileDoesNotExistsException; - protected String getErrorMessage(LanguageLevel effectiveLanguageLevel) { + protected String getErrorMessage(String effectiveLanguageLevel) { return "languageLevel=" + effectiveLanguageLevel; } } diff --git a/src/main/java/krasa/formatter/eclipse/JavaCodeFormatterFacade.java b/src/main/java/krasa/formatter/eclipse/JavaCodeFormatterFacade.java index 89a46fc..eaea990 100644 --- a/src/main/java/krasa/formatter/eclipse/JavaCodeFormatterFacade.java +++ b/src/main/java/krasa/formatter/eclipse/JavaCodeFormatterFacade.java @@ -15,6 +15,7 @@ import krasa.formatter.settings.Settings; import krasa.formatter.settings.provider.JavaPropertiesProvider; import org.apache.commons.lang3.StringUtils; +import org.eclipse.jdt.core.formatter.CodeFormatter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,7 +54,14 @@ public JavaCodeFormatterFacade(Settings settings, Project project) { public String format(String text, int startOffset, int endOffset, PsiFile psiFile) throws FileDoesNotExistsException { LanguageLevel languageLevel = getLanguageLevel(psiFile); - return getCodeFormatter(languageLevel, psiFile).format(text, startOffset, endOffset, languageLevel); + EclipseFormatterAdapter adapter = getCodeFormatter(languageLevel, psiFile); + int kind = CodeFormatter.K_COMPILATION_UNIT | CodeFormatter.F_INCLUDE_COMMENTS; + String lineSeparator = "\n"; + + if (endOffset > text.length()) { + endOffset = text.length(); + } + return adapter.format(kind, text, startOffset, endOffset - startOffset, 0, lineSeparator, languageLevel.toString()); } diff --git a/src/main/java/krasa/formatter/exception/FormattingFailedException.java b/src/main/java/krasa/formatter/exception/FormattingFailedException.java index 1cf3157..a99ffa9 100644 --- a/src/main/java/krasa/formatter/exception/FormattingFailedException.java +++ b/src/main/java/krasa/formatter/exception/FormattingFailedException.java @@ -1,11 +1,14 @@ package krasa.formatter.exception; +import com.intellij.openapi.diagnostic.Logger; import krasa.formatter.plugin.InvalidPropertyFile; /** * @author Vojtech Krasa */ public class FormattingFailedException extends RuntimeException { + protected final Logger LOG = Logger.getInstance(this.getClass().getName()); + private boolean userError; public FormattingFailedException(String s) { @@ -21,6 +24,12 @@ public FormattingFailedException(InvalidPropertyFile e) { super(e); } + public FormattingFailedException(Exception e, String errorMessage) { + super(errorMessage, e); + //todo hack + LOG.debug(e); + } + public boolean isUserError() { return userError; diff --git a/src/test/java/krasa/formatter/eclipse/JavaCodeFormatterFacadeTest.java b/src/test/java/krasa/formatter/eclipse/JavaCodeFormatterFacadeTest.java index 1c105f1..4bfd768 100644 --- a/src/test/java/krasa/formatter/eclipse/JavaCodeFormatterFacadeTest.java +++ b/src/test/java/krasa/formatter/eclipse/JavaCodeFormatterFacadeTest.java @@ -1,15 +1,20 @@ package krasa.formatter.eclipse; +import com.intellij.mock.MockApplication; import com.intellij.openapi.command.impl.DummyProject; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.util.PsiUtilCore; +import krasa.formatter.settings.GlobalSettings; import krasa.formatter.settings.Settings; +import org.apache.commons.io.FileUtils; import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import java.io.File; import java.io.UnsupportedEncodingException; import static org.junit.Assert.assertEquals; @@ -149,6 +154,24 @@ public void testFormatByXML() throws Exception { Assert.assertEquals(FORMATTED2, output); } + @Test + public void testFormatByXML_Formatter_20160606() throws Exception { + MockApplication app = MockApplication.setUp(Disposer.newDisposable()); + app.registerService(GlobalSettings.class, new GlobalSettings()); + GlobalSettings instance = GlobalSettings.getInstance(); + instance.setPathToEclipse("C:/Users/vojtisek/eclipse/java-2023-03"); + + Settings settings = new Settings(); + setPathToConfigFileJava(settings, "resources/Formatter_20160606.xml"); + settings.setSelectedJavaProfile("Formatter_20160606"); + settings.setEclipseVersion(Settings.FormatterVersion.CUSTOM); + + eclipseCodeFormatterFacade = getEclipseCodeFormatterFacade(settings); + String input = FileUtils.readFileToString(new File("src/test/resources/example/Example.java"), "UTF-8"); + String output = format(input); + Assert.assertEquals(input, output); + } + @Test public void testFormatByEPF() throws Exception { Settings settings = new Settings(); diff --git a/src/test/java/krasa/formatter/utils/StringUtilsTest.java b/src/test/java/krasa/formatter/utils/StringUtilsTest.java index 74fe64c..4a5ece6 100644 --- a/src/test/java/krasa/formatter/utils/StringUtilsTest.java +++ b/src/test/java/krasa/formatter/utils/StringUtilsTest.java @@ -1,30 +1,9 @@ package krasa.formatter.utils; -import com.intellij.diagnostic.ActivityCategory; -import com.intellij.openapi.components.BaseComponent; -import com.intellij.openapi.components.ComponentConfig; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.ExtensionsArea; -import com.intellij.openapi.extensions.PluginDescriptor; -import com.intellij.openapi.extensions.PluginId; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; -import com.intellij.util.messages.MessageBus; -import kotlinx.coroutines.CoroutineScope; -import krasa.formatter.settings.Settings; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.junit.Assert; import org.junit.Test; -import org.picocontainer.PicoContainer; -import java.util.ArrayList; import java.util.List; -import java.util.Map; import static krasa.formatter.utils.StringUtils.getPackage; import static krasa.formatter.utils.StringUtils.getSimpleName; @@ -63,238 +42,240 @@ public void testTrimToList() throws Exception { strings = StringUtils.trimToList(" "); Assert.assertFalse(strings.isEmpty()); } - - @Test - public void testGenerateName() throws Exception { - ArrayList settingsList = new ArrayList(); - Project instance = new MyDummyProject(); - String s = StringUtils.generateName(settingsList, 1, instance.getName()); - Assert.assertEquals("dummy", s); - settingsList.add(new Settings(1L, "dummy")); - - s = StringUtils.generateName(settingsList, 1, instance.getName()); - Assert.assertEquals("dummy (1)", s); - settingsList.add(new Settings(1L, "dummy (1)")); - - s = StringUtils.generateName(settingsList, 1, instance.getName()); - Assert.assertEquals("dummy (2)", s); - } - - class MyDummyProject extends UserDataHolderBase implements Project { - @NotNull - @Override - public ExtensionsArea getExtensionArea() { - return null; - } - - @Override - public T instantiateClassWithConstructorInjection(@NotNull Class aClass, @NotNull Object o, @NotNull PluginId pluginId) { - return null; - } - - @Override - public @NotNull - RuntimeException createError(@NotNull Throwable throwable, @NotNull PluginId pluginId) { - return null; - } - - @Override - public @NotNull - RuntimeException createError(@NotNull @NonNls String s, @NotNull PluginId pluginId) { - return null; - } - - @Override - public @NotNull - RuntimeException createError(@NotNull @NonNls String s, @Nullable Throwable throwable, @NotNull PluginId pluginId, @Nullable Map map) { - return null; - } - - - @Override - public @NotNull - Class loadClass(@NotNull String s, @NotNull PluginDescriptor pluginDescriptor) throws ClassNotFoundException { - return null; - } - - @Override - public @NotNull T instantiateClass(@NotNull String s, @NotNull PluginDescriptor pluginDescriptor) { - return null; - } - - @Override - public @NotNull - ActivityCategory getActivityCategory(boolean b) { - return null; - } - - public MyDummyProject() { - } - - @Override - public VirtualFile getProjectFile() { - return null; - } - - @Override - @NotNull - public String getName() { - return "dummy"; - } - - @Override - @Nullable - @NonNls - public String getPresentableUrl() { - return null; - } - - @Override - @NotNull - @NonNls - public String getLocationHash() { - return "dummy"; - } - - @Nullable - @NonNls - public String getLocation() { - throw new UnsupportedOperationException("Method getLocation not implemented in " + getClass()); - } - - @Override - @NotNull - public String getProjectFilePath() { - return ""; - } - - @Override - public VirtualFile getWorkspaceFile() { - return null; - } - - @Override - @Nullable - public VirtualFile getBaseDir() { - return null; - } - - // @Override - @Override - public String getBasePath() { - return null; - } - - @Override - public void save() { - } - - @Override - public BaseComponent getComponent(String name) { - return null; - } - - @Override - public T getComponent(Class interfaceClass) { - return null; - } - - @Override - public boolean hasComponent(@NotNull Class interfaceClass) { - return false; - } - - @NotNull - public T[] getComponents(Class baseClass) { - return (T[]) ArrayUtil.EMPTY_OBJECT_ARRAY; - } - - @Override - @NotNull - public PicoContainer getPicoContainer() { - throw new UnsupportedOperationException("getPicoContainer is not implement in : " + getClass()); - } - - @Override - public boolean isInjectionForExtensionSupported() { - return false; - } - - - @NotNull - // @Override - public Class[] getComponentInterfaces() { - return new Class[0]; - } - - @Override - public boolean isDisposed() { - return false; - } - - @Override - @NotNull - public Condition getDisposed() { - return new Condition() { - @Override - public boolean value(final Object o) { - return isDisposed(); - } - }; - } - - @Override - public T getService(@NotNull Class aClass) { - return null; - } - - @NotNull - public ComponentConfig[] getComponentConfigurations() { - return new ComponentConfig[0]; - } - - @Nullable - public Object getComponent(final ComponentConfig componentConfig) { - return null; - } - - @Override - public boolean isOpen() { - return false; - } - - @Override - public boolean isInitialized() { - return false; - } - - @Override - public boolean isDefault() { - return false; - } - +// todo +// @Test +// public void testGenerateName() throws Exception { +// ArrayList settingsList = new ArrayList(); +// Project instance = new MyDummyProject(); +// String s = StringUtils.generateName(settingsList, 1, instance.getName()); +// Assert.assertEquals("dummy", s); +// settingsList.add(new Settings(1L, "dummy")); +// +// s = StringUtils.generateName(settingsList, 1, instance.getName()); +// Assert.assertEquals("dummy (1)", s); +// settingsList.add(new Settings(1L, "dummy (1)")); +// +// s = StringUtils.generateName(settingsList, 1, instance.getName()); +// Assert.assertEquals("dummy (2)", s); +// } + +// class MyDummyProject extends UserDataHolderBase implements Project { +// +// +// @NotNull // @Override - public CoroutineScope getCoroutineScope() { - return null; - } - - @Override - public MessageBus getMessageBus() { - return null; - } - - @Override - public void dispose() { - } - - @Override - public T[] getExtensions(final ExtensionPointName extensionPointName) { - throw new UnsupportedOperationException("getExtensions()"); - } - - public ComponentConfig getConfig(Class componentImplementation) { - throw new UnsupportedOperationException("Method getConfig not implemented in " + getClass()); - } - } +// public ExtensionsArea getExtensionArea() { +// return null; +// } +// +// @Override +// public T instantiateClassWithConstructorInjection(@NotNull Class aClass, @NotNull Object o, @NotNull PluginId pluginId) { +// return null; +// } +// +// @Override +// public @NotNull +// RuntimeException createError(@NotNull Throwable throwable, @NotNull PluginId pluginId) { +// return null; +// } +// +// @Override +// public @NotNull +// RuntimeException createError(@NotNull @NonNls String s, @NotNull PluginId pluginId) { +// return null; +// } +// +// @Override +// public @NotNull +// RuntimeException createError(@NotNull @NonNls String s, @Nullable Throwable throwable, @NotNull PluginId pluginId, @Nullable Map map) { +// return null; +// } +// +// +// @Override +// public @NotNull +// Class loadClass(@NotNull String s, @NotNull PluginDescriptor pluginDescriptor) throws ClassNotFoundException { +// return null; +// } +// +// @Override +// public @NotNull T instantiateClass(@NotNull String s, @NotNull PluginDescriptor pluginDescriptor) { +// return null; +// } +// +// @Override +// public @NotNull +// ActivityCategory getActivityCategory(boolean b) { +// return null; +// } +// +// public MyDummyProject() { +// } +// +// @Override +// public VirtualFile getProjectFile() { +// return null; +// } +// +// @Override +// @NotNull +// public String getName() { +// return "dummy"; +// } +// +// @Override +// @Nullable +// @NonNls +// public String getPresentableUrl() { +// return null; +// } +// +// @Override +// @NotNull +// @NonNls +// public String getLocationHash() { +// return "dummy"; +// } +// +// @Nullable +// @NonNls +// public String getLocation() { +// throw new UnsupportedOperationException("Method getLocation not implemented in " + getClass()); +// } +// +// @Override +// @NotNull +// public String getProjectFilePath() { +// return ""; +// } +// +// @Override +// public VirtualFile getWorkspaceFile() { +// return null; +// } +// +// @Override +// @Nullable +// public VirtualFile getBaseDir() { +// return null; +// } +// +// // @Override +// @Override +// public String getBasePath() { +// return null; +// } +// +// @Override +// public void save() { +// } +// +// @Override +// public BaseComponent getComponent(String name) { +// return null; +// } +// +// @Override +// public T getComponent(Class interfaceClass) { +// return null; +// } +// +// @Override +// public boolean hasComponent(@NotNull Class interfaceClass) { +// return false; +// } +// +// @NotNull +// public T[] getComponents(Class baseClass) { +// return (T[]) ArrayUtil.EMPTY_OBJECT_ARRAY; +// } +// +//// @Override +// @NotNull +// public PicoContainer getPicoContainer() { +// throw new UnsupportedOperationException("getPicoContainer is not implement in : " + getClass()); +// } +// +// @Override +// public boolean isInjectionForExtensionSupported() { +// return false; +// } +// +// +// @NotNull +// // @Override +// public Class[] getComponentInterfaces() { +// return new Class[0]; +// } +// +// @Override +// public boolean isDisposed() { +// return false; +// } +// +// @Override +// @NotNull +// public Condition getDisposed() { +// return new Condition() { +// @Override +// public boolean value(final Object o) { +// return isDisposed(); +// } +// }; +// } +// +// @Override +// public T getService(@NotNull Class aClass) { +// return null; +// } +// +// @NotNull +// public ComponentConfig[] getComponentConfigurations() { +// return new ComponentConfig[0]; +// } +// +// @Nullable +// public Object getComponent(final ComponentConfig componentConfig) { +// return null; +// } +// +// @Override +// public boolean isOpen() { +// return false; +// } +// +// @Override +// public boolean isInitialized() { +// return false; +// } +// +// @Override +// public boolean isDefault() { +// return false; +// } +// +//// @Override +// public CoroutineScope getCoroutineScope() { +// return null; +// } +// +// @Override +// public MessageBus getMessageBus() { +// return null; +// } +// +// @Override +// public void dispose() { +// } +// +//// @Override +// public T[] getExtensions(final ExtensionPointName extensionPointName) { +// throw new UnsupportedOperationException("getExtensions()"); +// } +// +// public ComponentConfig getConfig(Class componentImplementation) { +// throw new UnsupportedOperationException("Method getConfig not implemented in " + getClass()); +// } +// } } diff --git a/src/test/resources/Formatter_20160606.xml b/src/test/resources/Formatter_20160606.xml new file mode 100644 index 0000000..bd91668 --- /dev/null +++ b/src/test/resources/Formatter_20160606.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/resources/example/Example.java b/src/test/resources/example/Example.java new file mode 100644 index 0000000..92f7bb9 --- /dev/null +++ b/src/test/resources/example/Example.java @@ -0,0 +1,65 @@ +/** + * An example for comment formatting. This example is meant to illustrate the + * various possibilities offered by Eclipse in order to format comments. + */ +package mypackage; + +/** + * This is the comment for the example interface. + */ +interface Example { + // This is a long comment with whitespace that should be split in multiple + // line comments in case the line comment formatting is enabled + int foo3(); + + // void commented() { + // System.out.println("indented"); + // } + + // void indentedCommented() { + // System.out.println("indented"); + // } + + /* block comment on first column */ + int bar(); + + /* + * These possibilities include:
  • Formatting of header + * comments.
  • Formatting of Javadoc tags
+ */ + int bar2(); // This is a long comment that should be split in multiple line + // comments in case the line comment formatting is enabled + + /** + * The following is some sample code which illustrates source formatting + * within javadoc comments: + * + *
+     * public class Example {
+     *     final int a = 1;
+     *     final boolean b = true;
+     * }
+     * 
+ * + * Descriptions of parameters and return values are best appended at end of + * the javadoc comment. + * @param first + * The first parameter. For an optimum result, this should be an + * odd number between 0 and 100. + * @param second + * The second parameter. + * @throws Exception + * when the foo operation cannot be performed for one reason or + * another. + * @return The result of the foo operation, usually an even number within 0 + * and 1000. + */ + int foo(int first, int second) throws Exception; +} + +class Test { + void trailingCommented() { + System.out.println("indented"); // comment + System.out.println("indent"); // comment + } +}