diff --git a/packages/java-parser/src/comments.js b/packages/java-parser/src/comments.js index 19d1c250..cad7f86f 100644 --- a/packages/java-parser/src/comments.js +++ b/packages/java-parser/src/comments.js @@ -115,7 +115,7 @@ function findUpperBoundToken(tokens, comment) { /** * Extends each comments offsets to the left and the right in order to match the - * previous and next token offset. This allow to directly match the prettier-ignore + * previous and next token offset. This allow to directly match the prettier-ignore or formatter:off|on * comment to the correct CSTNode. * @param {*} tokens ordered array of tokens * @param {*} comments array of prettier-ignore comments @@ -137,6 +137,11 @@ function extendCommentRange(tokens, comments) { return ignoreComments; } +/** + * Filter comments to find prettier-ignore's ones. + * @param comments + * @returns prettier-ignore comments + */ function filterPrettierIgnore(comments) { return [...comments].filter(comment => comment.image.match( @@ -145,6 +150,12 @@ function filterPrettierIgnore(comments) { ); } +/** + * Check if an node must be ignore because of prettier-ignore comment + * @param node + * @param comments + * @param ignoredNodes + */ function shouldIgnore(node, comments, ignoredNodes) { const matchingComment = _.find( comments, @@ -167,9 +178,84 @@ function ignoredComments(tokens, comments) { return extendCommentRange(tokens, filterPrettierIgnore(comments)); } +/** + * Filter comments to find formatter:off and formatter:on. + * @param comments + * @returns formatter:off and formatter:on comments + */ +function filterFormatterOffOn(comments) { + return [...comments].filter(comment => + comment.image.match( + /(\/\/(\s*)@formatter:(off|on)(\s*))|(\/\*(\s*)@formatter:(off|on)(\s*)\*\/)/gm + ) + ); +} + +/** + * Create pairs of formatter:off and formatter:on + * @param comments + * @returns pairs of formatter:off and formatter:on + */ +function matchFormatterOffOnPair(comments) { + let isPreviousCommentOff = false; + let isCurrentCommentOff = true; + const pairs = []; + let paired = {}; + comments.forEach(comment => { + isCurrentCommentOff = comment.image.slice(-3) === "off"; + + if (!isPreviousCommentOff) { + if (isCurrentCommentOff) { + paired.off = comment; + } + } else { + if (!isCurrentCommentOff) { + paired.on = comment; + pairs.push(paired); + paired = {}; + } + } + isPreviousCommentOff = isCurrentCommentOff; + }); + + if (comments.length > 0 && isCurrentCommentOff) { + paired.on = undefined; + pairs.push(paired); + } + + return pairs; +} + +/** + * Check if the node is between formatter:off and formatter:on and change his ignore state + * @param node + * @param commentPairs + */ +function shouldNotFormat(node, commentPairs) { + const matchingPair = _.findLast( + commentPairs, + comment => comment.off.extendedRange.endOffset <= node.location.startOffset + ); + if ( + matchingPair !== undefined && + (matchingPair.on === undefined || + matchingPair.on.startOffset > node.location.endOffset) + ) { + node.ignore = true; + } +} + +function formatterOffOnComments(tokens, comments) { + const offOn = filterFormatterOffOn(comments); + const extendedRangeOffOn = extendCommentRange(tokens, offOn); + return matchFormatterOffOnPair(extendedRangeOffOn); +} + module.exports = { attachComments, shouldIgnore, + shouldNotFormat, + formatterOffOnComments, ignoredComments, attachIgnoreNodes }; diff --git a/packages/java-parser/src/index.js b/packages/java-parser/src/index.js index 2f1689c5..5d827ce2 100644 --- a/packages/java-parser/src/index.js +++ b/packages/java-parser/src/index.js @@ -4,7 +4,8 @@ const JavaParser = require("./parser"); const { attachComments, ignoredComments, - attachIgnoreNodes + attachIgnoreNodes, + formatterOffOnComments } = require("./comments"); const parser = new JavaParser(); @@ -36,6 +37,12 @@ function parse(inputText, entryPoint = "compilationUnit") { ); parser.setIgnoredComments(ignoreComments); + const offOnComments = formatterOffOnComments( + lexResult.tokens, + lexResult.groups.comments + ); + parser.setOffOnComments(offOnComments); + // Automatic CST created when parsing const cst = parser[entryPoint](); diff --git a/packages/java-parser/src/parser.js b/packages/java-parser/src/parser.js index 3c18d1ff..ab6e7cd6 100644 --- a/packages/java-parser/src/parser.js +++ b/packages/java-parser/src/parser.js @@ -10,7 +10,7 @@ const interfaces = require("./productions/interfaces"); const arrays = require("./productions/arrays"); const blocksStatements = require("./productions/blocks-and-statements"); const expressions = require("./productions/expressions"); -const { shouldIgnore } = require("./comments"); +const { shouldIgnore, shouldNotFormat } = require("./comments"); /** * This parser attempts to strongly align with the specs style at: @@ -79,6 +79,7 @@ class JavaParser extends Parser { super.cstPostNonTerminal(ruleCstResult, ruleName); if (this.isBackTracking() === false) { shouldIgnore(ruleCstResult, this.ignoredComments, this.ignoredNodes); + shouldNotFormat(ruleCstResult, this.offOnComments); } } @@ -108,6 +109,10 @@ class JavaParser extends Parser { this.ignoredNodes = {}; this.ignoredComments = [...comments]; } + + setOffOnComments(commentOffOn) { + this.offOnComments = [...commentOffOn]; + } } module.exports = JavaParser; diff --git a/packages/prettier-plugin-java/scripts/single-printer-run/_input.java b/packages/prettier-plugin-java/scripts/single-printer-run/_input.java index edf095b8..a3612b08 100644 --- a/packages/prettier-plugin-java/scripts/single-printer-run/_input.java +++ b/packages/prettier-plugin-java/scripts/single-printer-run/_input.java @@ -1,33 +1,9 @@ -public enum Enum { +public class PrettierIgnoreClass { + // @formatter:off - SOME_ENUM, ANOTHER_ENUM, LAST_ENUM; - -} - -public enum Enum { - - THIS_IS_GOOD("abc"), THIS_IS_FINE("abc"); - - public static final String thisWillBeDeleted = "DELETED"; - - private final String value; - - public Enum(String value) { - this.value = value; - } - - public String toString() { - return "STRING"; - } - -} - -class CLassWithEnum { - - public static enum VALID_THINGS { - - FIRST, SECOND + public void myMethod() { + // @formatter:on } } diff --git a/packages/prettier-plugin-java/scripts/single-printer-run/_output.java b/packages/prettier-plugin-java/scripts/single-printer-run/_output.java index f86f9a1c..6328c23f 100644 --- a/packages/prettier-plugin-java/scripts/single-printer-run/_output.java +++ b/packages/prettier-plugin-java/scripts/single-printer-run/_output.java @@ -1,25 +1,8 @@ -public enum Enum { - SOME_ENUM, ANOTHER_ENUM, LAST_ENUM; -} - -public enum Enum { - THIS_IS_GOOD("abc"), THIS_IS_FINE("abc"); - public static final String thisWillBeDeleted = "DELETED"; - - private final String value; - - public Enum(String value) { - this.value = value; - } - - public String toString() { - return "STRING"; - } -} +public class PrettierIgnoreClass { -class CLassWithEnum { + // @formatter:off - public static enum VALID_THINGS { - FIRST, SECOND; + public void myMethod() { + // @formatter:on } } diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_input.java new file mode 100644 index 00000000..fcb68371 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_input.java @@ -0,0 +1,19 @@ +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_output.java new file mode 100644 index 00000000..a6bdb391 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/begin_with_on/_output.java @@ -0,0 +1,40 @@ +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} + +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_input.java new file mode 100644 index 00000000..89158458 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_input.java @@ -0,0 +1,12 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_output.java new file mode 100644 index 00000000..96f09366 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/class/_output.java @@ -0,0 +1,23 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_input.java new file mode 100644 index 00000000..e1765cbd --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_input.java @@ -0,0 +1,25 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_output.java new file mode 100644 index 00000000..415cbefc --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/end_with_off/_output.java @@ -0,0 +1,36 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} + +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_input.java new file mode 100644 index 00000000..b8f2f6e9 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_input.java @@ -0,0 +1,8 @@ +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + // @formatter:off + System.out.println("This operation with two very long string should not break because the formatter is off"); + // @formatter:on + System.out.println("This operation with two very long string should break because the formatter is on"); + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_output.java new file mode 100644 index 00000000..590760a3 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/inside_block/_output.java @@ -0,0 +1,23 @@ +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) { + // @formatter:off + System.out.println("This operation with two very long string should not break because the formatter is off"); + + // @formatter:on + System.out.println( + "This operation with two very long string should break because the formatter is on" + ); + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_input.java new file mode 100644 index 00000000..cdb406cc --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_input.java @@ -0,0 +1,7 @@ +public class PrettierIgnoreClass { + // @formatter:off + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } + // @formatter:on +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_output.java new file mode 100644 index 00000000..2ede64a7 --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/method/_output.java @@ -0,0 +1,8 @@ +public class PrettierIgnoreClass { + + // @formatter:off + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +// @formatter:on +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_input.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_input.java new file mode 100644 index 00000000..58583fdb --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_input.java @@ -0,0 +1,24 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} +// @formatter:on +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} diff --git a/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_output.java b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_output.java new file mode 100644 index 00000000..ecaec8fc --- /dev/null +++ b/packages/prettier-plugin-java/test/unit-test/formatter-on-off/multiple/_output.java @@ -0,0 +1,47 @@ +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} + +// @formatter:off +public class PrettierIgnoreClass { + public void myMethod(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10) { + + } +} + +// @formatter:on +public class PrettierIgnoreClass { + + public void myMethod( + int param1, + int param2, + int param3, + int param4, + int param5, + int param6, + int param7, + int param8, + int param9, + int param10 + ) {} +} diff --git a/packages/prettier-plugin-java/test/unit-test/prettier-ignore/prettier-ignore-spec.js b/packages/prettier-plugin-java/test/unit-test/prettier-ignore/prettier-ignore-spec.js index dfa4e1af..708cd307 100644 --- a/packages/prettier-plugin-java/test/unit-test/prettier-ignore/prettier-ignore-spec.js +++ b/packages/prettier-plugin-java/test/unit-test/prettier-ignore/prettier-ignore-spec.js @@ -3,6 +3,7 @@ const path = require("path"); describe("prettier-java", () => { testSample(path.resolve(__dirname, "./classDeclaration")); + testSample(path.resolve(__dirname, "./formatter-on-off")); testSample(path.resolve(__dirname, "./method")); testSample(path.resolve(__dirname, "./multiple-ignore")); });