diff --git a/README.md b/README.md index 38fdac5e8..83a524bbd 100644 --- a/README.md +++ b/README.md @@ -35,14 +35,14 @@ is available from the plugin repository. To install it, go to your IDE's settings and select the `Plugins` category. Click the `Marketplace` tab, search for the `google-java-format` plugin, and click the `Install` button. -The plugin will be disabled by default. To enable it in the current project, go -to `File→Settings...→google-java-format Settings` (or `IntelliJ -IDEA→Preferences...→Other Settings→google-java-format Settings` on macOS) and -check the `Enable google-java-format` checkbox. (A notification will be -presented when you first open a project offering to do this for you.) +The plugin will be disabled by default. To enable, +[open the Project settings](https://www.jetbrains.com/help/idea/configure-project-settings.html), +then click "google-java-format Settings" and check the "Enable +google-java-format" checkbox. -To enable it by default in new projects, use `File→Other Settings→Default -Settings...`. +To enable it by default in new projects, +[open the default settings for new projects](https://www.jetbrains.com/help/idea/configure-project-settings.html#new-default-settings) +and configure it under "Other Settings/google-java-format Settings". When enabled, it will replace the normal `Reformat Code` and `Optimize Imports` actions. @@ -50,8 +50,9 @@ actions. #### IntelliJ JRE Config The google-java-format plugin uses some internal classes that aren't available -without extra configuration. To use the plugin, go to `Help→Edit Custom VM -Options...` and paste in these lines: +without extra configuration. To use the plugin, you need to +[add some options to your IDE's Java runtime](https://www.jetbrains.com/help/idea/tuning-the-ide.html#procedure-jvm-options). +To do that, go to `Help→Edit Custom VM Options...` and paste in these lines: ``` --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED diff --git a/core/pom.xml b/core/pom.xml index c3753a150..4bf08f0b2 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -22,7 +22,7 @@ com.google.googlejavaformat google-java-format-parent - HEAD-SNAPSHOT + 1.24.0 google-java-format diff --git a/core/src/main/java/com/google/googlejavaformat/FormatterDiagnostic.java b/core/src/main/java/com/google/googlejavaformat/FormatterDiagnostic.java index be7f8a6ca..252da5bdf 100644 --- a/core/src/main/java/com/google/googlejavaformat/FormatterDiagnostic.java +++ b/core/src/main/java/com/google/googlejavaformat/FormatterDiagnostic.java @@ -49,7 +49,7 @@ public int line() { } /** - * Returns the 0-indexed column number on which the error occurred, or {@code -1} if the error + * Returns the 1-indexed column number on which the error occurred, or {@code -1} if the error * does not have a column. */ public int column() { @@ -61,14 +61,14 @@ public String message() { return message; } + @Override public String toString() { StringBuilder sb = new StringBuilder(); if (lineNumber >= 0) { sb.append(lineNumber).append(':'); } if (column >= 0) { - // internal column numbers are 0-based, but diagnostics use 1-based indexing by convention - sb.append(column + 1).append(':'); + sb.append(column).append(':'); } if (lineNumber >= 0 || column >= 0) { sb.append(' '); diff --git a/core/src/main/java/com/google/googlejavaformat/java/FormatterException.java b/core/src/main/java/com/google/googlejavaformat/java/FormatterException.java index 808916c2c..5ca939bbb 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/FormatterException.java +++ b/core/src/main/java/com/google/googlejavaformat/java/FormatterException.java @@ -16,10 +16,13 @@ import static java.util.Locale.ENGLISH; +import com.google.common.base.CharMatcher; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.googlejavaformat.FormatterDiagnostic; import java.util.List; +import java.util.regex.Pattern; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; @@ -55,4 +58,22 @@ private static FormatterDiagnostic toFormatterDiagnostic(Diagnostic input) { return FormatterDiagnostic.create( (int) input.getLineNumber(), (int) input.getColumnNumber(), input.getMessage(ENGLISH)); } + + public String formatDiagnostics(String path, String input) { + List lines = Splitter.on(NEWLINE_PATTERN).splitToList(input); + StringBuilder sb = new StringBuilder(); + for (FormatterDiagnostic diagnostic : diagnostics()) { + sb.append(path).append(":").append(diagnostic).append(System.lineSeparator()); + int line = diagnostic.line(); + int column = diagnostic.column(); + if (line != -1 && column != -1) { + sb.append(CharMatcher.breakingWhitespace().trimTrailingFrom(lines.get(line - 1))) + .append(System.lineSeparator()); + sb.append(" ".repeat(column - 1)).append('^').append(System.lineSeparator()); + } + } + return sb.toString(); + } + + private static final Pattern NEWLINE_PATTERN = Pattern.compile("\\R"); } diff --git a/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java b/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java index d34ecc43f..d54b2317e 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java +++ b/core/src/main/java/com/google/googlejavaformat/java/JavaCommentsHelper.java @@ -49,7 +49,11 @@ public String rewrite(Tok tok, int maxWidth, int column0) { List lines = new ArrayList<>(); Iterator it = Newlines.lineIterator(text); while (it.hasNext()) { - lines.add(CharMatcher.whitespace().trimTrailingFrom(it.next())); + if (tok.isSlashSlashComment()) { + lines.add(CharMatcher.whitespace().trimFrom(it.next())); + } else { + lines.add(CharMatcher.whitespace().trimTrailingFrom(it.next())); + } } if (tok.isSlashSlashComment()) { return indentLineComments(lines, column0); diff --git a/core/src/main/java/com/google/googlejavaformat/java/JavaInputAstVisitor.java b/core/src/main/java/com/google/googlejavaformat/java/JavaInputAstVisitor.java index e00877e96..01f9a3e05 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/JavaInputAstVisitor.java +++ b/core/src/main/java/com/google/googlejavaformat/java/JavaInputAstVisitor.java @@ -1875,10 +1875,10 @@ public Void visitCase(CaseTree node, Void unused) { markForPartialFormat(); builder.forcedBreak(); if (node.getExpression() == null) { - token("default", plusTwo); + token("default", ZERO); token(":"); } else { - token("case", plusTwo); + token("case", ZERO); builder.space(); scan(node.getExpression(), null); token(":"); diff --git a/core/src/main/java/com/google/googlejavaformat/java/Main.java b/core/src/main/java/com/google/googlejavaformat/java/Main.java index 0845e0ec2..f1affa74d 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/Main.java +++ b/core/src/main/java/com/google/googlejavaformat/java/Main.java @@ -20,7 +20,6 @@ import com.google.common.io.ByteStreams; import com.google.common.util.concurrent.MoreExecutors; -import com.google.googlejavaformat.FormatterDiagnostic; import com.google.googlejavaformat.java.JavaFormatterOptions.Style; import java.io.IOError; import java.io.IOException; @@ -175,9 +174,7 @@ private int formatFiles(CommandLineOptions parameters, JavaFormatterOptions opti for (FormatFileCallable.Result result : results) { Path path = result.path(); if (result.exception() != null) { - for (FormatterDiagnostic diagnostic : result.exception().diagnostics()) { - errWriter.println(path + ":" + diagnostic); - } + errWriter.print(result.exception().formatDiagnostics(path.toString(), result.input())); allOk = false; continue; } @@ -224,9 +221,7 @@ private int formatStdin(CommandLineOptions parameters, JavaFormatterOptions opti FormatFileCallable.Result result = new FormatFileCallable(parameters, null, input, options).call(); if (result.exception() != null) { - for (FormatterDiagnostic diagnostic : result.exception().diagnostics()) { - errWriter.println(stdinFilename + ":" + diagnostic); - } + errWriter.print(result.exception().formatDiagnostics(stdinFilename, input)); ok = false; } else { String output = result.output(); diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocFormatter.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocFormatter.java index 03938a677..4d45c9874 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocFormatter.java +++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocFormatter.java @@ -66,6 +66,12 @@ private static String render(List input, int blockIndent) { case FOOTER_JAVADOC_TAG_START: output.writeFooterJavadocTagStart(token); break; + case SNIPPET_BEGIN: + output.writeSnippetBegin(token); + break; + case SNIPPET_END: + output.writeSnippetEnd(token); + break; case LIST_OPEN_TAG: output.writeListOpen(token); break; diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java index cc707ae7e..d40f34c6b 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java +++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocLexer.java @@ -42,6 +42,8 @@ import static com.google.googlejavaformat.java.javadoc.Token.Type.PARAGRAPH_OPEN_TAG; import static com.google.googlejavaformat.java.javadoc.Token.Type.PRE_CLOSE_TAG; import static com.google.googlejavaformat.java.javadoc.Token.Type.PRE_OPEN_TAG; +import static com.google.googlejavaformat.java.javadoc.Token.Type.SNIPPET_BEGIN; +import static com.google.googlejavaformat.java.javadoc.Token.Type.SNIPPET_END; import static com.google.googlejavaformat.java.javadoc.Token.Type.TABLE_CLOSE_TAG; import static com.google.googlejavaformat.java.javadoc.Token.Type.TABLE_OPEN_TAG; import static com.google.googlejavaformat.java.javadoc.Token.Type.WHITESPACE; @@ -97,6 +99,7 @@ private static String stripJavadocBeginAndEnd(String input) { private final NestingCounter preDepth = new NestingCounter(); private final NestingCounter codeDepth = new NestingCounter(); private final NestingCounter tableDepth = new NestingCounter(); + private boolean outerInlineTagIsSnippet; private boolean somethingSinceNewline; private JavadocLexer(CharStream input) { @@ -158,13 +161,26 @@ private Type consumeToken() throws LexException { } somethingSinceNewline = true; - if (input.tryConsumeRegex(INLINE_TAG_OPEN_PATTERN)) { + if (input.tryConsumeRegex(SNIPPET_TAG_OPEN_PATTERN)) { + if (braceDepth.value() == 0) { + braceDepth.increment(); + outerInlineTagIsSnippet = true; + return SNIPPET_BEGIN; + } + braceDepth.increment(); + return LITERAL; + } else if (input.tryConsumeRegex(INLINE_TAG_OPEN_PATTERN)) { braceDepth.increment(); return LITERAL; } else if (input.tryConsume("{")) { braceDepth.incrementIfPositive(); return LITERAL; } else if (input.tryConsume("}")) { + if (outerInlineTagIsSnippet && braceDepth.value() == 1) { + braceDepth.decrementIfPositive(); + outerInlineTagIsSnippet = false; + return SNIPPET_END; + } braceDepth.decrementIfPositive(); return LITERAL; } @@ -239,7 +255,10 @@ private Type consumeToken() throws LexException { } private boolean preserveExistingFormatting() { - return preDepth.isPositive() || tableDepth.isPositive() || codeDepth.isPositive(); + return preDepth.isPositive() + || tableDepth.isPositive() + || codeDepth.isPositive() + || outerInlineTagIsSnippet; } private void checkMatchingTags() throws LexException { @@ -400,6 +419,7 @@ private static ImmutableList optionalizeSpacesAfterLinks(List inpu *

Also trim leading and trailing blank lines, and move the trailing `}` to its own line. */ private static ImmutableList deindentPreCodeBlocks(List input) { + // TODO: b/323389829 - De-indent {@snippet ...} blocks, too. ImmutableList.Builder output = ImmutableList.builder(); for (PeekingIterator tokens = peekingIterator(input.iterator()); tokens.hasNext(); ) { if (tokens.peek().getType() != PRE_OPEN_TAG) { @@ -528,6 +548,7 @@ private static boolean hasMultipleNewlines(String s) { private static final Pattern BLOCKQUOTE_OPEN_PATTERN = openTagPattern("blockquote"); private static final Pattern BLOCKQUOTE_CLOSE_PATTERN = closeTagPattern("blockquote"); private static final Pattern BR_PATTERN = openTagPattern("br"); + private static final Pattern SNIPPET_TAG_OPEN_PATTERN = compile("^[{]@snippet\\b"); private static final Pattern INLINE_TAG_OPEN_PATTERN = compile("^[{]@\\w*"); /* * We exclude < so that we don't swallow following HTML tags. This lets us fix up "foo

" (~400 diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java index 0361415a1..8a4100e45 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java +++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/JavadocWriter.java @@ -123,6 +123,38 @@ void writeFooterJavadocTagStart(Token token) { continuingFooterTag = true; } + void writeSnippetBegin(Token token) { + requestBlankLine(); + writeToken(token); + /* + * We don't request a newline here because we should have at least a colon following on this + * line, and we may have attributes after that. + * + * (If we find it convenient, we could instead consume the entire rest of the line as part of + * the same token as `{@snippet` itself. But we already would never split the rest of the line + * across lines (because we preserve whitespace), so that might not accomplish anything. Plus, + * we'd probably want to be careful not to swallow an expectedly early closing `}`.) + */ + } + + void writeSnippetEnd(Token token) { + /* + * We don't request a newline here because we have preserved all newlines that existed in the + * input. TODO: b/323389829 - Improve upon that. Specifically: + * + * - If there is not yet a newline, we should add one. + * + * - If there are multiple newlines, we should probably collapse them. + * + * - If the closing brace isn't indented as we'd want (as in the link below, in which the whole + * @apiNote isn't indented), we should indent it. + * + * https://github.com/openjdk/jdk/blob/1ebf2cf639300728ffc024784f5dc1704317b0b3/src/java.base/share/classes/java/util/Collections.java#L5993-L6006 + */ + writeToken(token); + requestBlankLine(); + } + void writeListOpen(Token token) { requestBlankLine(); diff --git a/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java b/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java index d617824b0..f74996060 100644 --- a/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java +++ b/core/src/main/java/com/google/googlejavaformat/java/javadoc/Token.java @@ -41,6 +41,10 @@ enum Type { END_JAVADOC, /** The {@code @foo} that begins a block Javadoc tag like {@code @throws}. */ FOOTER_JAVADOC_TAG_START, + /** The opening {@code {@snippet} of a code snippet. */ + SNIPPET_BEGIN, + /** The closing {@code }} of a code snippet. */ + SNIPPET_END, LIST_OPEN_TAG, LIST_CLOSE_TAG, LIST_ITEM_OPEN_TAG, diff --git a/core/src/main/scripts/google-java-format.el b/core/src/main/scripts/google-java-format.el index 5df8a1396..1bb3ffdc2 100644 --- a/core/src/main/scripts/google-java-format.el +++ b/core/src/main/scripts/google-java-format.el @@ -2,8 +2,6 @@ ;; ;; Copyright 2015 Google, Inc. All Rights Reserved. ;; -;; Package-Requires: ((emacs "24")) -;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. ;; You may obtain a copy of the License at @@ -17,6 +15,8 @@ ;; limitations under the License. ;; Keywords: tools, Java +;; Version: 0.1.0 +;; Package-Requires: ((emacs "24")) ;;; Commentary: @@ -109,5 +109,4 @@ there is no region, then formats the current line." (defalias 'google-java-format 'google-java-format-region) (provide 'google-java-format) - ;;; google-java-format.el ends here diff --git a/core/src/test/java/com/google/googlejavaformat/java/DiagnosticTest.java b/core/src/test/java/com/google/googlejavaformat/java/DiagnosticTest.java index fc966fac3..e05a37264 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/DiagnosticTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/DiagnosticTest.java @@ -79,7 +79,7 @@ public void parseError() throws Exception { int result = main.format(path.toString()); assertThat(stdout.toString()).isEmpty(); - assertThat(stderr.toString()).contains("InvalidSyntax.java:2:29: error: expected"); + assertThat(stderr.toString()).contains("InvalidSyntax.java:2:28: error: expected"); assertThat(result).isEqualTo(1); } @@ -119,7 +119,7 @@ public void oneFileParseError() throws Exception { int result = main.format(pathOne.toString(), pathTwo.toString()); assertThat(stdout.toString()).isEqualTo(two); - assertThat(stderr.toString()).contains("One.java:1:13: error: reached end of file"); + assertThat(stderr.toString()).contains("One.java:1:12: error: reached end of file"); assertThat(result).isEqualTo(1); } @@ -141,7 +141,7 @@ public void oneFileParseErrorReplace() throws Exception { int result = main.format("-i", pathOne.toString(), pathTwo.toString()); assertThat(stdout.toString()).isEmpty(); - assertThat(stderr.toString()).contains("One.java:1:14: error: class, interface"); + assertThat(stderr.toString()).contains("One.java:1:13: error: class, interface"); assertThat(result).isEqualTo(1); // don't edit files with parse errors assertThat(Files.readAllLines(pathOne, UTF_8)).containsExactly("class One {}}"); @@ -164,7 +164,7 @@ public void parseError2() throws FormatterException, IOException, UsageException int exitCode = main.format(args); assertThat(exitCode).isEqualTo(1); - assertThat(err.toString()).contains("A.java:2:6: error: ';' expected"); + assertThat(err.toString()).contains("A.java:2:5: error: ';' expected"); } @Test @@ -179,7 +179,7 @@ public void parseErrorStdin() throws FormatterException, IOException, UsageExcep int exitCode = main.format(args); assertThat(exitCode).isEqualTo(1); - assertThat(err.toString()).contains(":2:6: error: ';' expected"); + assertThat(err.toString()).contains(":2:5: error: ';' expected"); } @Test @@ -198,7 +198,7 @@ public void lexError2() throws FormatterException, IOException, UsageException { int exitCode = main.format(args); assertThat(exitCode).isEqualTo(1); - assertThat(err.toString()).contains("A.java:2:5: error: unclosed character literal"); + assertThat(err.toString()).contains("A.java:2:4: error: unclosed character literal"); } @Test @@ -212,6 +212,6 @@ public void lexErrorStdin() throws FormatterException, IOException, UsageExcepti int exitCode = main.format(args); assertThat(exitCode).isEqualTo(1); - assertThat(err.toString()).contains(":2:5: error: unclosed character literal"); + assertThat(err.toString()).contains(":2:4: error: unclosed character literal"); } } diff --git a/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java b/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java index 6849c01f2..aab8ec5d4 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/JavadocFormattingTest.java @@ -906,6 +906,48 @@ public void unicodeCharacterCountArguableBug() { doFormatTest(input, expected); } + @Test + public void blankLinesAroundSnippetAndNoMangling() { + String[] input = { + "/**", // + " * hello world", + " * {@snippet :", + " * public class Foo {", + " * private String s;", + " * }", + " * }", + " * hello again", + " */", + "class Test {}", + }; + String[] expected = { + "/**", // + " * hello world", + " *", + " * {@snippet :", + " * public class Foo {", + " * private String s;", + " * }", + " * }", + " *", + " * hello again", + " */", + "class Test {}", + }; + doFormatTest(input, expected); + } + + @Test + public void notASnippetUnlessOuterTag() { + String[] input = { + "/** I would like to tell you about the {@code {@snippet ...}} tag. */", "class Test {}", + }; + String[] expected = { + "/** I would like to tell you about the {@code {@snippet ...}} tag. */", "class Test {}", + }; + doFormatTest(input, expected); + } + @Test public void blankLineBeforeParams() { String[] input = { diff --git a/core/src/test/java/com/google/googlejavaformat/java/MainTest.java b/core/src/test/java/com/google/googlejavaformat/java/MainTest.java index 42e12d860..2d9364082 100644 --- a/core/src/test/java/com/google/googlejavaformat/java/MainTest.java +++ b/core/src/test/java/com/google/googlejavaformat/java/MainTest.java @@ -307,7 +307,7 @@ public void importRemoveErrorParseError() throws Exception { new PrintWriter(err, true), new ByteArrayInputStream(joiner.join(input).getBytes(UTF_8))); assertThat(main.format("-")).isEqualTo(1); - assertThat(err.toString()).contains(":4:3: error: class, interface"); + assertThat(err.toString()).contains(":4:2: error: class, interface"); } finally { Locale.setDefault(backupLocale); @@ -508,7 +508,7 @@ public void assumeFilename_error() throws Exception { new PrintWriter(err, true), new ByteArrayInputStream(joiner.join(input).getBytes(UTF_8))); assertThat(main.format("--assume-filename=Foo.java", "-")).isEqualTo(1); - assertThat(err.toString()).contains("Foo.java:1:15: error: class, interface"); + assertThat(err.toString()).contains("Foo.java:1:14: error: class, interface"); } @Test @@ -635,4 +635,59 @@ public void reorderModifiersOptionTest() throws Exception { .formatSource(source)) .isEqualTo(source); } + + @Test + public void syntaxError() throws Exception { + Path path = testFolder.newFile("Test.java").toPath(); + String[] input = { + "class Test {", // + " void f(int package) {", + " int", + " }", + "}", + "", + }; + String source = joiner.join(input); + Files.writeString(path, source, UTF_8); + StringWriter out = new StringWriter(); + StringWriter err = new StringWriter(); + Main main = new Main(new PrintWriter(out, true), new PrintWriter(err, true), System.in); + int errorCode = main.format(path.toAbsolutePath().toString()); + assertWithMessage("Error Code").that(errorCode).isEqualTo(1); + String[] expected = { + path + ":2:13: error: expected", + " void f(int package) {", + " ^", + path + ":3:5: error: not a statement", + " int", + " ^", + path + ":3:8: error: ';' expected", + " int", + " ^", + "", + }; + assertThat(err.toString()).isEqualTo(joiner.join(expected)); + } + + @Test + public void syntaxErrorBeginning() throws Exception { + Path path = testFolder.newFile("Test.java").toPath(); + String[] input = { + "error", // + }; + String source = joiner.join(input); + Files.writeString(path, source, UTF_8); + StringWriter out = new StringWriter(); + StringWriter err = new StringWriter(); + Main main = new Main(new PrintWriter(out, true), new PrintWriter(err, true), System.in); + int errorCode = main.format(path.toAbsolutePath().toString()); + assertWithMessage("Error Code").that(errorCode).isEqualTo(1); + String[] expected = { + path + ":1:1: error: reached end of file while parsing", // + "error", + "^", + "", + }; + assertThat(err.toString()).isEqualTo(joiner.join(expected)); + } } diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.input new file mode 100644 index 000000000..e2b27dde1 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.input @@ -0,0 +1,15 @@ +class I1153 { + void f() { + //// (1) one + int one; + + //// (2) two + int two; + + //// (2.1) if we need to collect data using multiple different collectors, e.g. taxonomy and + //// ranges, or even two taxonomy facets that use different Category List Field, we can + //// use MultiCollectorManager, e.g.: + // TODO: This should be (2.1) two point one + int twoPointOne; + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.output new file mode 100644 index 000000000..e2b27dde1 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/I1153.output @@ -0,0 +1,15 @@ +class I1153 { + void f() { + //// (1) one + int one; + + //// (2) two + int two; + + //// (2.1) if we need to collect data using multiple different collectors, e.g. taxonomy and + //// ranges, or even two taxonomy facets that use different Category List Field, we can + //// use MultiCollectorManager, e.g.: + // TODO: This should be (2.1) two point one + int twoPointOne; + } +} diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.input b/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.input new file mode 100644 index 000000000..07ce2f4d2 --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.input @@ -0,0 +1,17 @@ +class T { + int test(String v) { + switch (v) { + // this is a line comment about "zero" + case "zero": + return 0; + case "one": + // this is a line comment about "one" + return 1; + // this is a line comment about "two" + case "two": + return 2; + default: + return -1; + } + } +} \ No newline at end of file diff --git a/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.output b/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.output new file mode 100644 index 000000000..70a0b6bea --- /dev/null +++ b/core/src/test/resources/com/google/googlejavaformat/java/testdata/LegacySwitchComment.output @@ -0,0 +1,17 @@ +class T { + int test(String v) { + switch (v) { + // this is a line comment about "zero" + case "zero": + return 0; + case "one": + // this is a line comment about "one" + return 1; + // this is a line comment about "two" + case "two": + return 2; + default: + return -1; + } + } +} diff --git a/eclipse_plugin/META-INF/MANIFEST.MF b/eclipse_plugin/META-INF/MANIFEST.MF index 913245393..e81bc8ec0 100644 --- a/eclipse_plugin/META-INF/MANIFEST.MF +++ b/eclipse_plugin/META-INF/MANIFEST.MF @@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2 Bundle-Name: google-java-format Bundle-SymbolicName: google-java-format-eclipse-plugin;singleton:=true Bundle-Vendor: Google -Bundle-Version: 1.13.0 +Bundle-Version: 1.24.0 Bundle-RequiredExecutionEnvironment: JavaSE-11 Require-Bundle: org.eclipse.jdt.core;bundle-version="3.10.0", org.eclipse.jface, diff --git a/eclipse_plugin/pom.xml b/eclipse_plugin/pom.xml index b2c6e368a..71ad8eacd 100644 --- a/eclipse_plugin/pom.xml +++ b/eclipse_plugin/pom.xml @@ -22,7 +22,7 @@ com.google.googlejavaformat google-java-format-eclipse-plugin eclipse-plugin - 1.13.0 + 1.24.0 Google Java Format Plugin for Eclipse 4.5+ diff --git a/idea_plugin/.gitignore b/idea_plugin/.gitignore index 16bc65a53..a5e690ca2 100644 --- a/idea_plugin/.gitignore +++ b/idea_plugin/.gitignore @@ -2,4 +2,5 @@ build .gradle gradle gradlew -gradlew.bat \ No newline at end of file +gradlew.bat +.intellijPlatform \ No newline at end of file diff --git a/idea_plugin/build.gradle.kts b/idea_plugin/build.gradle.kts index 0ba5032dc..c7d1d4ba1 100644 --- a/idea_plugin/build.gradle.kts +++ b/idea_plugin/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.intellij.platform.gradle.TestFrameworkType /* * Copyright 2017 Google Inc. All Rights Reserved. * @@ -15,56 +16,76 @@ */ // https://github.com/JetBrains/intellij-platform-gradle-plugin/releases -plugins { id("org.jetbrains.intellij") version "1.17.3" } - -apply(plugin = "org.jetbrains.intellij") +plugins { + id("org.jetbrains.intellij.platform") version "2.0.1" +} -apply(plugin = "java") +repositories { + mavenCentral() -repositories { mavenCentral() } + intellijPlatform { + defaultRepositories() + } +} // https://github.com/google/google-java-format/releases -val googleJavaFormatVersion = "1.22.0" +val googleJavaFormatVersion = "1.23.0" java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } -intellij { - pluginName.set("google-java-format") - plugins.set(listOf("java")) - version.set("2021.3") -} - -tasks { - patchPluginXml { - version.set("${googleJavaFormatVersion}.0") - sinceBuild.set("213") - untilBuild.set("") +intellijPlatform { + pluginConfiguration { + name = "google-java-format" + version = "${googleJavaFormatVersion}.0" + ideaVersion { + sinceBuild = "223" + untilBuild = provider { null } + } } - publishPlugin { + publishing { val jetbrainsPluginRepoToken: String by project token.set(jetbrainsPluginRepoToken) } +} +var gjfRequiredJvmArgs = + listOf( + "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) + +tasks { + runIde { + jvmArgumentProviders += CommandLineArgumentProvider { + gjfRequiredJvmArgs + } + } +} + +tasks { withType().configureEach { - jvmArgs( - "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", - ) + jvmArgs(gjfRequiredJvmArgs) } } dependencies { + intellijPlatform { + intellijIdeaCommunity("2022.3") + bundledPlugin("com.intellij.java") + instrumentationTools() + testFramework(TestFrameworkType.Plugin.Java) + } implementation("com.google.googlejavaformat:google-java-format:${googleJavaFormatVersion}") // https://mvnrepository.com/artifact/junit/junit testImplementation("junit:junit:4.13.2") // https://mvnrepository.com/artifact/com.google.truth/truth - testImplementation("com.google.truth:truth:1.4.2") + testImplementation("com.google.truth:truth:1.4.4") } diff --git a/idea_plugin/src/main/java/com/google/googlejavaformat/intellij/InitialConfigurationStartupActivity.java b/idea_plugin/src/main/java/com/google/googlejavaformat/intellij/InitialConfigurationStartupActivity.java index 940def655..95e13d325 100644 --- a/idea_plugin/src/main/java/com/google/googlejavaformat/intellij/InitialConfigurationStartupActivity.java +++ b/idea_plugin/src/main/java/com/google/googlejavaformat/intellij/InitialConfigurationStartupActivity.java @@ -27,8 +27,6 @@ final class InitialConfigurationStartupActivity implements StartupActivity.Background { private static final String NOTIFICATION_TITLE = "Enable google-java-format"; - private static final NotificationGroup NOTIFICATION_GROUP = - NotificationGroupManager.getInstance().getNotificationGroup(NOTIFICATION_TITLE); @Override public void runActivity(@NotNull Project project) { @@ -43,9 +41,11 @@ public void runActivity(@NotNull Project project) { } private void displayNewUserNotification(Project project, GoogleJavaFormatSettings settings) { + NotificationGroupManager groupManager = NotificationGroupManager.getInstance(); + NotificationGroup group = groupManager.getNotificationGroup(NOTIFICATION_TITLE); Notification notification = new Notification( - NOTIFICATION_GROUP.getDisplayId(), + group.getDisplayId(), NOTIFICATION_TITLE, "The google-java-format plugin is disabled by default. " + "Enable for this project.", diff --git a/idea_plugin/src/main/resources/META-INF/plugin.xml b/idea_plugin/src/main/resources/META-INF/plugin.xml index 378c2529c..8d7574539 100644 --- a/idea_plugin/src/main/resources/META-INF/plugin.xml +++ b/idea_plugin/src/main/resources/META-INF/plugin.xml @@ -35,6 +35,10 @@ ]]> +

1.23.0.0
+
Updated to use google-java-format 1.23.0.
+
Fix crashes in IntelliJ 2024.2 (Thanks, @nrayburn-tech!)
+
Updated to the latest IntelliJ build system (Thanks, @mmaeller!)
1.22.0.0
Updated to use google-java-format 1.22.0.
1.21.0.0
diff --git a/pom.xml b/pom.xml index 96e613a0a..32a3558a7 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ com.google.googlejavaformat google-java-format-parent pom - HEAD-SNAPSHOT + 1.24.0 core