From 348c6856a9c32cd4869fb92345cd8e140a275fa6 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Wed, 20 Jan 2021 07:47:26 +1300 Subject: [PATCH 01/18] Add whitespace check capability and ParenPadQuickFix --- .../checkstyle/quickfix/BaseEditQuickFix.java | 28 +++++++ .../checkstyle/quickfix/BaseQuickFix.java | 2 +- .../checkstyle/quickfix/FixableCheck.java | 3 + .../checkstyle/quickfix/IQuickFix.java | 22 ++++++ .../checkstyle/quickfix/QuickFixService.java | 62 +++++++++++++-- .../quickfix/whitepace/ParenPadQuickFix.java | 75 +++++++++++++++++++ src/constants/quickFix.ts | 3 + 7 files changed, 187 insertions(+), 8 deletions(-) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/IQuickFix.java create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java new file mode 100644 index 0000000..2f873f8 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.TextEdit; + +public abstract class BaseEditQuickFix implements IQuickFix { + + public abstract TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc); + +} diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseQuickFix.java index 8dec212..a83a0df 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseQuickFix.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.stream.Collectors; -public abstract class BaseQuickFix { +public abstract class BaseQuickFix implements IQuickFix { public abstract ASTVisitor getCorrectingASTVisitor(IRegion lineInfo, int markerStartOffset); /** diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index b7dde3a..6238593 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -34,6 +34,9 @@ public enum FixableCheck { // Modifier MODIFIER_ORDER_CHECK("ModifierOrderCheck"), REDUNDANT_MODIFIER_CHECK("RedundantModifierCheck"), + // Whitespace + PAREN_PAD_CHECK("ParenPadCheck"), + // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), UPPER_ELL_CHECK("UpperEllCheck"), ARRAY_TYPE_STYLE_CHECK("ArrayTypeStyleCheck"); diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/IQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/IQuickFix.java new file mode 100644 index 0000000..0fde8e7 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/IQuickFix.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix; + +public interface IQuickFix { + +} diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index a5427ab..5f776a1 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -37,6 +37,7 @@ import com.shengchen.checkstyle.quickfix.modifier.ModifierOrderQuickFix; import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; +import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; import com.shengchen.checkstyle.runner.api.IQuickFixService; import org.eclipse.jdt.core.ICompilationUnit; @@ -49,15 +50,20 @@ import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IRegion; import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; public class QuickFixService implements IQuickFixService { - private final Map quickFixMap; + private final Map quickFixMap; public QuickFixService() { quickFixMap = new HashMap<>(); @@ -81,9 +87,10 @@ public QuickFixService() { quickFixMap.put(FixableCheck.STRING_LITERAL_EQUALITY.toString(), new StringLiteralEqualityQuickFix()); quickFixMap.put(FixableCheck.MULTIPLE_VARIABLE_DECLARATIONS_CHECK.toString(), new MultipleVariableDeclarationsQuickFix()); + quickFixMap.put(FixableCheck.PAREN_PAD_CHECK.toString(), new ParenPadQuickFix()); } - public BaseQuickFix getQuickFix(String sourceName) { + public IQuickFix getQuickFix(String sourceName) { return quickFixMap.get(sourceName); } @@ -100,16 +107,57 @@ public WorkspaceEdit quickFix( final CompilationUnit astRoot = (CompilationUnit) astParser.createAST(null); astRoot.recordModifications(); + final List edits = new ArrayList<>(); + for (int i = 0; i < offsets.size(); i++) { final int offset = offsets.get(i).intValue(); - final BaseQuickFix quickFix = getQuickFix(sourceNames.get(i)); - if (quickFix != null) { - final IRegion lineInfo = document.getLineInformationOfOffset(offset); - astRoot.accept(quickFix.getCorrectingASTVisitor(lineInfo, offset)); + final IRegion lineInfo = document.getLineInformationOfOffset(offset); + final IQuickFix quickFix = getQuickFix(sourceNames.get(i)); + if (quickFix instanceof BaseQuickFix) { + astRoot.accept(((BaseQuickFix) quickFix).getCorrectingASTVisitor(lineInfo, offset)); + } else if (quickFix instanceof BaseEditQuickFix) { + final TextEdit edit = ((BaseEditQuickFix) quickFix).createTextEdit(lineInfo, offset, document); + if (edit != null) { + addAllEdits(edits, edit); + } } } final TextEdit edit = astRoot.rewrite(document, null); - return EditUtils.convertToWorkspaceEdit(unit, edit); + addAllEdits(edits, edit); + final MultiTextEdit result = new MultiTextEdit(); + for (final TextEdit anotherEdit : edits) { + result.addChild(anotherEdit.copy()); + } + return EditUtils.convertToWorkspaceEdit(unit, result); + } + + private void addAllEdits(final List edits, final TextEdit edit) { + for (final TextEdit anEdit : allEdits(edit)) { + if (canAddEdit(anEdit, edits)) { + edits.add(anEdit); + } + } + } + + /** + * Check whether we can add the given new edit to our list of existing edits. This prevents + * edits that might conflict or double-up. + */ + private boolean canAddEdit(TextEdit edit, Collection existingEdits) { + for (final TextEdit existingEdit : existingEdits) { + if (existingEdit.covers(edit) || existingEdit.getOffset() == edit.getOffset()) { + return false; + } + } + return true; + } + + private Iterable allEdits(TextEdit edit) { + if (edit instanceof MultiTextEdit) { + return Arrays.asList(((MultiTextEdit) edit).getChildren()); + } else { + return Collections.singleton(edit); + } } } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java new file mode 100644 index 0000000..fbd94ed --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.TextEdit; + +public class ParenPadQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final char marker = doc.getChar(markerStartOffset); + if (marker == '(') { + final String string = doc.get(markerStartOffset + 1, lineInfo.getLength() - fromStartOfLine - 1); + final int leadingWhitespace = measureLeadingWhitespace(string); + if (leadingWhitespace > 0) { + return new DeleteEdit(markerStartOffset + 1, leadingWhitespace); + } + } else if (marker == ')' && fromStartOfLine > 0) { + final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); + final int trailingWhitespace = measureTrailingWhitespace(string); + if (trailingWhitespace > 0) { + return new DeleteEdit(markerStartOffset - trailingWhitespace, trailingWhitespace); + } + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + + private int measureLeadingWhitespace(String string) { + final int n = string.length(); + for (int i = 0; i < n; i++) { + if (!Character.isWhitespace(string.charAt(i))) { + return i; + } + } + return n; + } + + private int measureTrailingWhitespace(String string) { + final int n = string.length(); + for (int i = n - 1; i >= 0; i--) { + if (!Character.isWhitespace(string.charAt(i))) { + return n - 1 - i; + } + } + return n; + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index f6f98ee..cb26e01 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -25,6 +25,9 @@ export enum FixableCheck { ModifierOrderCheck = 'ModifierOrderCheck', RedundantModifierCheck = 'RedundantModifierCheck', + // Whitespace + ParenPadCheck = 'ParenPadCheck', + // Misc FinalParametersCheck = 'FinalParametersCheck', UncommentedMainCheck = 'UncommentedMainCheck', From 32aa9ea2e0a4add4431328e817e99654ca548e2a Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Wed, 20 Jan 2021 18:57:35 +1300 Subject: [PATCH 02/18] Fix whitespace quick fix compatibility with AST fixes --- .../checkstyle/quickfix/QuickFixService.java | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 5f776a1..e3bdfd8 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -50,6 +50,7 @@ import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IRegion; import org.eclipse.lsp4j.WorkspaceEdit; +import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; @@ -107,7 +108,7 @@ public WorkspaceEdit quickFix( final CompilationUnit astRoot = (CompilationUnit) astParser.createAST(null); astRoot.recordModifications(); - final List edits = new ArrayList<>(); + final List textEdits = new ArrayList<>(); for (int i = 0; i < offsets.size(); i++) { final int offset = offsets.get(i).intValue(); @@ -118,24 +119,26 @@ public WorkspaceEdit quickFix( } else if (quickFix instanceof BaseEditQuickFix) { final TextEdit edit = ((BaseEditQuickFix) quickFix).createTextEdit(lineInfo, offset, document); if (edit != null) { - addAllEdits(edits, edit); + addAllEdits(edit, textEdits); } } } - final TextEdit edit = astRoot.rewrite(document, null); - addAllEdits(edits, edit); - final MultiTextEdit result = new MultiTextEdit(); - for (final TextEdit anotherEdit : edits) { - result.addChild(anotherEdit.copy()); + final MultiTextEdit result = (MultiTextEdit) astRoot.rewrite(document, null); + for (final TextEdit anotherEdit : textEdits) { + try { + result.addChild(anotherEdit); + } catch (MalformedTreeException e) { + /* Ignore text edits that can't be added; it is due to conflicts with an AST edit */ + } } return EditUtils.convertToWorkspaceEdit(unit, result); } - private void addAllEdits(final List edits, final TextEdit edit) { - for (final TextEdit anEdit : allEdits(edit)) { - if (canAddEdit(anEdit, edits)) { - edits.add(anEdit); + private void addAllEdits(final TextEdit source, final List dest) { + for (final TextEdit anEdit : allEdits(source)) { + if (canAddEdit(anEdit, dest)) { + dest.add(anEdit); } } } @@ -146,8 +149,14 @@ private void addAllEdits(final List edits, final TextEdit edit) { */ private boolean canAddEdit(TextEdit edit, Collection existingEdits) { for (final TextEdit existingEdit : existingEdits) { - if (existingEdit.covers(edit) || existingEdit.getOffset() == edit.getOffset()) { - return false; + if (existingEdit instanceof MultiTextEdit) { + if (!canAddEdit(edit, Arrays.asList(((MultiTextEdit) existingEdit).getChildren()))) { + return false; + } + } else { + if (existingEdit.covers(edit) || existingEdit.getOffset() == edit.getOffset()) { + return false; + } } } return true; From 380573aba8420ffcd8b5a6a149c99f72b12e2ad8 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 14 Jan 2021 22:42:01 +1300 Subject: [PATCH 03/18] Add WhitespaceAfter quick fix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/WhitespaceAfterQuickFix.java | 67 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 71 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index 6238593..b052f31 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -36,6 +36,7 @@ public enum FixableCheck { // Whitespace PAREN_PAD_CHECK("ParenPadCheck"), + WHITESPACE_AFTER_CHECK("WhitespaceAfterCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index e3bdfd8..15e10b9 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -38,6 +38,7 @@ import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; +import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAfterQuickFix; import com.shengchen.checkstyle.runner.api.IQuickFixService; import org.eclipse.jdt.core.ICompilationUnit; @@ -89,6 +90,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.MULTIPLE_VARIABLE_DECLARATIONS_CHECK.toString(), new MultipleVariableDeclarationsQuickFix()); quickFixMap.put(FixableCheck.PAREN_PAD_CHECK.toString(), new ParenPadQuickFix()); + quickFixMap.put(FixableCheck.WHITESPACE_AFTER_CHECK.toString(), new WhitespaceAfterQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java new file mode 100644 index 0000000..75ee804 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.TextEdit; + +import java.util.function.Predicate; + +public class WhitespaceAfterQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final String string = doc.get(markerStartOffset, lineInfo.getLength() - fromStartOfLine); + + final char marker = string.charAt(0); + if (marker == ',' || marker == ';' || marker == ')') { + return new InsertEdit(markerStartOffset + 1, " "); + } + + if (Character.isLetter(marker)) { + /* Literal if, else, while, do, for */ + final int tokenLength = measureToken(string, Character::isLetter); + if (tokenLength > 0 && tokenLength < string.length()) { + return new InsertEdit(markerStartOffset + tokenLength, " "); + } + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + + private int measureToken(String string, Predicate tokenPredicate) { + final int n = string.length(); + for (int i = 0; i < n; i++) { + if (!tokenPredicate.test(string.charAt(i))) { + return i; + } + } + return n; + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index cb26e01..1b2b1af 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -27,6 +27,7 @@ export enum FixableCheck { // Whitespace ParenPadCheck = 'ParenPadCheck', + WhitespaceAfterCheck = 'WhitespaceAfterCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From 156dc4d71336c98fe179c5cb8286f945beec8b6e Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Fri, 15 Jan 2021 07:35:12 +1300 Subject: [PATCH 04/18] Add WhitespaceAround quick fix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/WhitespaceAroundQuickFix.java | 83 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 87 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index b052f31..e0ad2ce 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -37,6 +37,7 @@ public enum FixableCheck { // Whitespace PAREN_PAD_CHECK("ParenPadCheck"), WHITESPACE_AFTER_CHECK("WhitespaceAfterCheck"), + WHITESPACE_AROUND_CHECK("WhitespaceAroundCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 15e10b9..8e4bbe2 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -39,6 +39,7 @@ import com.shengchen.checkstyle.quickfix.utils.EditUtils; import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAfterQuickFix; +import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAroundQuickFix; import com.shengchen.checkstyle.runner.api.IQuickFixService; import org.eclipse.jdt.core.ICompilationUnit; @@ -91,6 +92,7 @@ public QuickFixService() { new MultipleVariableDeclarationsQuickFix()); quickFixMap.put(FixableCheck.PAREN_PAD_CHECK.toString(), new ParenPadQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AFTER_CHECK.toString(), new WhitespaceAfterQuickFix()); + quickFixMap.put(FixableCheck.WHITESPACE_AROUND_CHECK.toString(), new WhitespaceAroundQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java new file mode 100644 index 0000000..cb45b86 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.MultiTextEdit; +import org.eclipse.text.edits.TextEdit; + +import java.util.function.Predicate; + +public class WhitespaceAroundQuickFix extends BaseEditQuickFix { + + private static final String OPERATORS = "-=!&|^<>"; + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final String string = doc.get(lineInfo.getOffset(), lineInfo.getLength()); + + final char marker = string.charAt(fromStartOfLine); + final int tokenLength; + + if (marker == '{' || marker == '}') { + tokenLength = 1; + } else if (OPERATORS.indexOf(marker) != -1) { + tokenLength = measureToken(string, c -> OPERATORS.indexOf(c) != -1); + } else if (Character.isLetter(marker)) { + /* Literal if, else, while, do, for */ + tokenLength = measureToken(string, Character::isLetter); + } else { + tokenLength = 0; + } + + if (tokenLength > 0) { + final MultiTextEdit result = new MultiTextEdit(); + if (fromStartOfLine > 0 && !Character.isWhitespace(string.charAt(fromStartOfLine - 1))) { + result.addChild(new InsertEdit(lineInfo.getOffset() + fromStartOfLine, " ")); + } + if (fromStartOfLine + tokenLength < string.length() && + !Character.isWhitespace(string.charAt(fromStartOfLine + tokenLength))) { + result.addChild(new InsertEdit(lineInfo.getOffset() + fromStartOfLine + tokenLength, " ")); + } + return result; + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + + private int measureToken(String string, Predicate tokenPredicate) { + final int n = string.length(); + for (int i = 0; i < n; i++) { + if (!tokenPredicate.test(string.charAt(i))) { + return i; + } + } + return n; + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index 1b2b1af..bff033a 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -28,6 +28,7 @@ export enum FixableCheck { // Whitespace ParenPadCheck = 'ParenPadCheck', WhitespaceAfterCheck = 'WhitespaceAfterCheck', + WhitespaceAroundCheck = 'WhitespaceAroundCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From f2b6bdda09388da6548471225e8a396df6abe90a Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 21 Jan 2021 09:57:29 +1300 Subject: [PATCH 05/18] Fix applying edit quick fixes with AST quick fixes --- .../java/com/shengchen/checkstyle/quickfix/QuickFixService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 8e4bbe2..201c3ef 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -131,7 +131,7 @@ public WorkspaceEdit quickFix( final MultiTextEdit result = (MultiTextEdit) astRoot.rewrite(document, null); for (final TextEdit anotherEdit : textEdits) { try { - result.addChild(anotherEdit); + result.addChild(anotherEdit.copy()); } catch (MalformedTreeException e) { /* Ignore text edits that can't be added; it is due to conflicts with an AST edit */ } From a345f72401f45d719d29bbd5d8556d248dc00d20 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 21 Jan 2021 15:09:41 +1300 Subject: [PATCH 06/18] Add NoWhitespaceBeforeCheck quick fix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/NoWhitespaceBeforeQuickFix.java | 59 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 63 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index e0ad2ce..4954d02 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -38,6 +38,7 @@ public enum FixableCheck { PAREN_PAD_CHECK("ParenPadCheck"), WHITESPACE_AFTER_CHECK("WhitespaceAfterCheck"), WHITESPACE_AROUND_CHECK("WhitespaceAroundCheck"), + NO_WHITESPACE_BEFORE_CHECK("NoWhitespaceBeforeCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 201c3ef..2847884 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -37,6 +37,7 @@ import com.shengchen.checkstyle.quickfix.modifier.ModifierOrderQuickFix; import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; +import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceBeforeQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAfterQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAroundQuickFix; @@ -93,6 +94,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.PAREN_PAD_CHECK.toString(), new ParenPadQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AFTER_CHECK.toString(), new WhitespaceAfterQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AROUND_CHECK.toString(), new WhitespaceAroundQuickFix()); + quickFixMap.put(FixableCheck.NO_WHITESPACE_BEFORE_CHECK.toString(), new NoWhitespaceBeforeQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java new file mode 100644 index 0000000..8b73374 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.TextEdit; + +import java.util.function.Predicate; + +public class NoWhitespaceBeforeQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); + + final int length = measureTokenBackwards(string, Character::isWhitespace); + if (length > 0) { + return new DeleteEdit(markerStartOffset - length, length); + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + + private int measureTokenBackwards(String string, Predicate tokenPredicate) { + final int n = string.length(); + for (int i = n - 1; i >= 0; i--) { + if (!tokenPredicate.test(string.charAt(i))) { + return n - 1 - i; + } + } + return n; + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index bff033a..3398db3 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -29,6 +29,7 @@ export enum FixableCheck { ParenPadCheck = 'ParenPadCheck', WhitespaceAfterCheck = 'WhitespaceAfterCheck', WhitespaceAroundCheck = 'WhitespaceAroundCheck', + NoWhitespaceBeforeCheck = 'NoWhitespaceBeforeCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From 33b391ca260ee1c3f98bec8c6d5a475bc4d32cbe Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 21 Jan 2021 16:00:38 +1300 Subject: [PATCH 07/18] Fix WhitespaceAroundQuickFix with non-blocks --- .../quickfix/whitepace/WhitespaceAroundQuickFix.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java index cb45b86..a6b2eef 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java @@ -44,10 +44,10 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document if (marker == '{' || marker == '}') { tokenLength = 1; } else if (OPERATORS.indexOf(marker) != -1) { - tokenLength = measureToken(string, c -> OPERATORS.indexOf(c) != -1); + tokenLength = measureToken(string, fromStartOfLine, c -> OPERATORS.indexOf(c) != -1); } else if (Character.isLetter(marker)) { /* Literal if, else, while, do, for */ - tokenLength = measureToken(string, Character::isLetter); + tokenLength = measureToken(string, fromStartOfLine, Character::isLetter); } else { tokenLength = 0; } @@ -70,11 +70,11 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document } } - private int measureToken(String string, Predicate tokenPredicate) { + private int measureToken(String string, int start, Predicate tokenPredicate) { final int n = string.length(); - for (int i = 0; i < n; i++) { + for (int i = start; i < n; i++) { if (!tokenPredicate.test(string.charAt(i))) { - return i; + return i - start; } } return n; From 4dcae0a7da3a60c6cc723c42778078478d22df58 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 21 Jan 2021 16:27:06 +1300 Subject: [PATCH 08/18] Add NewlineAtEndOfFileQuickFix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/NewlineAtEndOfFileQuickFix.java | 45 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 49 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index 4954d02..a8acc0f 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -39,6 +39,7 @@ public enum FixableCheck { WHITESPACE_AFTER_CHECK("WhitespaceAfterCheck"), WHITESPACE_AROUND_CHECK("WhitespaceAroundCheck"), NO_WHITESPACE_BEFORE_CHECK("NoWhitespaceBeforeCheck"), + NEWLINE_AT_END_OF_FILE_CHECK("NewlineAtEndOfFileCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 2847884..3a9af75 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -37,6 +37,7 @@ import com.shengchen.checkstyle.quickfix.modifier.ModifierOrderQuickFix; import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; +import com.shengchen.checkstyle.quickfix.whitepace.NewlineAtEndOfFileQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceBeforeQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAfterQuickFix; @@ -95,6 +96,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.WHITESPACE_AFTER_CHECK.toString(), new WhitespaceAfterQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AROUND_CHECK.toString(), new WhitespaceAroundQuickFix()); quickFixMap.put(FixableCheck.NO_WHITESPACE_BEFORE_CHECK.toString(), new NoWhitespaceBeforeQuickFix()); + quickFixMap.put(FixableCheck.NEWLINE_AT_END_OF_FILE_CHECK.toString(), new NewlineAtEndOfFileQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java new file mode 100644 index 0000000..1673ed1 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.TextEdit; + +public class NewlineAtEndOfFileQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final String lastChar = doc.getLength() > 0 ? doc.get(doc.getLength() - 1, 1) : ""; + + if (lastChar.isEmpty() || !"\n".equals(lastChar)) { + return new InsertEdit(doc.getLength(), "\n"); + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index 3398db3..eac5eae 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -30,6 +30,7 @@ export enum FixableCheck { WhitespaceAfterCheck = 'WhitespaceAfterCheck', WhitespaceAroundCheck = 'WhitespaceAroundCheck', NoWhitespaceBeforeCheck = 'NoWhitespaceBeforeCheck', + NewlineAtEndOfFileCheck = 'NewlineAtEndOfFileCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From 8de767ee269a8b419e8cc5c9853b5e01832257c1 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Thu, 21 Jan 2021 17:25:23 +1300 Subject: [PATCH 09/18] Add NoWhitespaceAfterCheck quick fix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/NoWhitespaceAfterQuickFix.java | 60 +++++++++++++++++++ .../whitepace/NoWhitespaceBeforeQuickFix.java | 1 + src/constants/quickFix.ts | 1 + 5 files changed, 65 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index a8acc0f..d7c457f 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -38,6 +38,7 @@ public enum FixableCheck { PAREN_PAD_CHECK("ParenPadCheck"), WHITESPACE_AFTER_CHECK("WhitespaceAfterCheck"), WHITESPACE_AROUND_CHECK("WhitespaceAroundCheck"), + NO_WHITESPACE_AFTER_CHECK("NoWhitespaceAfterCheck"), NO_WHITESPACE_BEFORE_CHECK("NoWhitespaceBeforeCheck"), NEWLINE_AT_END_OF_FILE_CHECK("NewlineAtEndOfFileCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 3a9af75..8d060a3 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -38,6 +38,7 @@ import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; import com.shengchen.checkstyle.quickfix.whitepace.NewlineAtEndOfFileQuickFix; +import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceAfterQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceBeforeQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.ParenPadQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.WhitespaceAfterQuickFix; @@ -95,6 +96,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.PAREN_PAD_CHECK.toString(), new ParenPadQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AFTER_CHECK.toString(), new WhitespaceAfterQuickFix()); quickFixMap.put(FixableCheck.WHITESPACE_AROUND_CHECK.toString(), new WhitespaceAroundQuickFix()); + quickFixMap.put(FixableCheck.NO_WHITESPACE_AFTER_CHECK.toString(), new NoWhitespaceAfterQuickFix()); quickFixMap.put(FixableCheck.NO_WHITESPACE_BEFORE_CHECK.toString(), new NoWhitespaceBeforeQuickFix()); quickFixMap.put(FixableCheck.NEWLINE_AT_END_OF_FILE_CHECK.toString(), new NewlineAtEndOfFileQuickFix()); } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java new file mode 100644 index 0000000..6acb5d7 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.TextEdit; + +import java.util.function.Predicate; + +public class NoWhitespaceAfterQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + /* Marker is first non-whitespace character after the problem */ + final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); + + final int length = measureTokenBackwards(string, Character::isWhitespace); + if (length > 0) { + return new DeleteEdit(markerStartOffset - length, length); + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + + private int measureTokenBackwards(String string, Predicate tokenPredicate) { + final int n = string.length(); + for (int i = n - 1; i >= 0; i--) { + if (!tokenPredicate.test(string.charAt(i))) { + return n - 1 - i; + } + } + return n; + } + +} diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java index 8b73374..2f56a23 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java @@ -33,6 +33,7 @@ public class NoWhitespaceBeforeQuickFix extends BaseEditQuickFix { public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + /* Marker is first non-whitespace character after the problem */ final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); final int length = measureTokenBackwards(string, Character::isWhitespace); diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index eac5eae..f4073f3 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -29,6 +29,7 @@ export enum FixableCheck { ParenPadCheck = 'ParenPadCheck', WhitespaceAfterCheck = 'WhitespaceAfterCheck', WhitespaceAroundCheck = 'WhitespaceAroundCheck', + NoWhitespaceAfterCheck = 'NoWhitespaceAfterCheck', NoWhitespaceBeforeCheck = 'NoWhitespaceBeforeCheck', NewlineAtEndOfFileCheck = 'NewlineAtEndOfFileCheck', From 85ae4dbfb3c18c875751eab7c2efc705d20defcd Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 22:41:40 +1300 Subject: [PATCH 10/18] Support Checkstyle violation message key This will provide more information to the quick fixes about exactly what the violation was, so the quick fix can respond to the configuration. --- .../checkstyle/checker/CheckerListener.java | 4 +++- .../checkstyle/quickfix/QuickFixService.java | 3 ++- .../checkstyle/runner/DelegateCommandHandler.java | 5 +++-- .../shengchen/checkstyle/runner/api/CheckResult.java | 12 +++++++++++- .../checkstyle/runner/api/IQuickFixService.java | 3 ++- src/checkstyleDiagnosticCollector.ts | 5 +++-- src/commands/fix.ts | 4 ++-- src/extension.ts | 2 +- src/models.ts | 7 ++++++- src/quickFixProvider.ts | 2 ++ 10 files changed, 35 insertions(+), 12 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.checker/src/main/java/com/shengchen/checkstyle/checker/CheckerListener.java b/jdtls.ext/com.shengchen.checkstyle.checker/src/main/java/com/shengchen/checkstyle/checker/CheckerListener.java index 66381af..275d92b 100644 --- a/jdtls.ext/com.shengchen.checkstyle.checker/src/main/java/com/shengchen/checkstyle/checker/CheckerListener.java +++ b/jdtls.ext/com.shengchen.checkstyle.checker/src/main/java/com/shengchen/checkstyle/checker/CheckerListener.java @@ -43,7 +43,9 @@ public void addError(AuditEvent error) { error.getLocalizedMessage().getColumnCharIndex() + 1, error.getMessage(), severity.toString().toLowerCase(), - error.getSourceName().substring(error.getSourceName().lastIndexOf('.') + 1))); + error.getSourceName().substring(error.getSourceName().lastIndexOf('.') + 1), + error.getLocalizedMessage().getKey()) + ); } @Override diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 8d060a3..c29bb64 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -108,7 +108,8 @@ public IQuickFix getQuickFix(String sourceName) { public WorkspaceEdit quickFix( String fileToCheckUri, List offsets, - List sourceNames + List sourceNames, + List violationKeys ) throws JavaModelException, IllegalArgumentException, BadLocationException { final ICompilationUnit unit = JDTUtils.resolveCompilationUnit(fileToCheckUri); final Document document = new Document(unit.getSource()); diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/DelegateCommandHandler.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/DelegateCommandHandler.java index 3b25726..fb11e93 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/DelegateCommandHandler.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/DelegateCommandHandler.java @@ -103,11 +103,12 @@ protected Map> checkCode(List filesToCheckUris protected WorkspaceEdit quickFix( String fileToCheckUri, List offsets, - List sourceNames + List sourceNames, + List violationKeys ) throws JavaModelException, IllegalArgumentException, BadLocationException { if (quickfixService == null) { quickfixService = checkstyleLoader.loadQuickFixService(); } - return quickfixService.quickFix(fileToCheckUri, offsets, sourceNames); + return quickfixService.quickFix(fileToCheckUri, offsets, sourceNames, violationKeys); } } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/CheckResult.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/CheckResult.java index c5da6bc..b62d94d 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/CheckResult.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/CheckResult.java @@ -23,13 +23,15 @@ public class CheckResult { private String message; private String severity; private String sourceName; + private String key; - public CheckResult(int line, int column, String msg, String severity, String sourceName) { + public CheckResult(int line, int column, String msg, String severity, String sourceName, String key) { this.line = line; this.column = column; this.message = msg; this.severity = severity; this.sourceName = sourceName; + this.key = key; } public int getLine() { @@ -72,4 +74,12 @@ public void setSourceName(String sourceName) { this.sourceName = sourceName; } + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/IQuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/IQuickFixService.java index 61b8750..d734646 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/IQuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/runner/api/IQuickFixService.java @@ -28,7 +28,8 @@ public interface IQuickFixService { public WorkspaceEdit quickFix( String fileToCheckUri, List offsets, - List sourceNames + List sourceNames, + List violationKeys ) throws JavaModelException, IllegalArgumentException, BadLocationException; } diff --git a/src/checkstyleDiagnosticCollector.ts b/src/checkstyleDiagnosticCollector.ts index eda5933..afaa254 100644 --- a/src/checkstyleDiagnosticCollector.ts +++ b/src/checkstyleDiagnosticCollector.ts @@ -2,7 +2,7 @@ // Licensed under the GNU LGPLv3 license. import { Diagnostic, DiagnosticCollection, DiagnosticSeverity, Disposable, languages, Range, Uri } from 'vscode'; -import { ICheckstyleResult } from './models'; +import { ICheckstyleDiagnostic, ICheckstyleResult } from './models'; class CheckstyleDiagnosticCollector implements Disposable { private diagnosticCollection: DiagnosticCollection; @@ -12,7 +12,7 @@ class CheckstyleDiagnosticCollector implements Disposable { } public addDiagnostics(uri: Uri, violations: ICheckstyleResult[]): void { - const diagnostics: Diagnostic[] = []; + const diagnostics: ICheckstyleDiagnostic[] = []; for (const violation of violations) { if (violation.severity === 'ignore') { continue; // Do not report ignored diagnostics @@ -25,6 +25,7 @@ class CheckstyleDiagnosticCollector implements Disposable { severity: this.parseDiagnosticSeverity(violation.severity), source: 'Checkstyle', code: violation.sourceName, + violationKey: violation.key, }); } this.diagnosticCollection.set(uri, diagnostics); diff --git a/src/commands/fix.ts b/src/commands/fix.ts index 65cf138..2b19273 100644 --- a/src/commands/fix.ts +++ b/src/commands/fix.ts @@ -9,10 +9,10 @@ import { applyWorkspaceEdit } from '../utils/editUtils'; import { handleErrors } from '../utils/errorUtils'; import { executeJavaLanguageServerCommand } from './executeJavaLanguageServerCommand'; -export async function fixCheckstyleViolations(uri: Uri, offsets: number[], sourceNames: string[]): Promise { +export async function fixCheckstyleViolations(uri: Uri, offsets: number[], sourceNames: string[], violationKeys: string[]): Promise { try { const workspaceEdit: ls.WorkspaceEdit | undefined = await executeJavaLanguageServerCommand( - CheckstyleServerCommands.QUICK_FIX, uri.toString(), offsets, sourceNames); + CheckstyleServerCommands.QUICK_FIX, uri.toString(), offsets, sourceNames, violationKeys); if (!workspaceEdit) { checkstyleChannel.appendLine('Unable to get quick fix item from Language Server.'); return; diff --git a/src/extension.ts b/src/extension.ts index 20618ad..8123f94 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -49,6 +49,6 @@ async function doActivate(_operationId: string, context: ExtensionContext): Prom instrumentOperationAsVsCodeCommand(CheckstyleExtensionCommands.SET_CHECKSTYLE_CONFIGURATION, async (uri?: Uri) => await setConfiguration(uri)), instrumentOperationAsVsCodeCommand(CheckstyleExtensionCommands.SET_CHECKSTYLE_VERSION, async (version?: string) => await setVersion(version)), instrumentOperationAsVsCodeCommand(CheckstyleExtensionCommands.CHECK_CODE_WITH_CHECKSTYLE, async (uri?: Uri) => await checkCode(uri)), - instrumentOperationAsVsCodeCommand(CheckstyleExtensionCommands.FIX_CHECKSTYLE_VIOLATIONS, async (uri: Uri, offsets: number[], sourceNames: string[]) => await fixCheckstyleViolations(uri, offsets, sourceNames)), + instrumentOperationAsVsCodeCommand(CheckstyleExtensionCommands.FIX_CHECKSTYLE_VIOLATIONS, async (uri: Uri, offsets: number[], sourceNames: string[], violationKeys: string[]) => await fixCheckstyleViolations(uri, offsets, sourceNames, violationKeys)), ); } diff --git a/src/models.ts b/src/models.ts index b210244..09387eb 100644 --- a/src/models.ts +++ b/src/models.ts @@ -1,6 +1,6 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the GNU LGPLv3 license. -import { QuickPickItem } from 'vscode'; +import { Diagnostic, QuickPickItem } from 'vscode'; export interface IQuickPickItemEx extends QuickPickItem { value?: T; @@ -12,6 +12,7 @@ export interface ICheckstyleResult { message: string; severity: 'ignore' | 'info' | 'warning' | 'error'; sourceName: string; + key: string; } export interface ICheckstyleConfiguration { @@ -20,3 +21,7 @@ export interface ICheckstyleConfiguration { properties: object; modules: string[]; } + +export interface ICheckstyleDiagnostic extends Diagnostic { + violationKey: string; +} diff --git a/src/quickFixProvider.ts b/src/quickFixProvider.ts index 1ead6af..4c37a7f 100644 --- a/src/quickFixProvider.ts +++ b/src/quickFixProvider.ts @@ -5,6 +5,7 @@ import * as _ from 'lodash'; import { CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, Diagnostic, Range, Selection, TextDocument } from 'vscode'; import { checkstyleDiagnosticCollector } from './checkstyleDiagnosticCollector'; import { CheckstyleExtensionCommands } from './constants/commands'; +import { ICheckstyleDiagnostic } from './models'; import { isQuickFixAvailable } from './utils/quickFixUtils'; class QuickFixProvider implements CodeActionProvider { @@ -93,6 +94,7 @@ function createFixAllDiagnostics(document: TextDocument, diagnostics: Diagnostic document.uri, diagnostics.map((diagnostic: Diagnostic) => document.offsetAt(diagnostic.range.start)), diagnostics.map((diagnostic: Diagnostic) => diagnostic.code), + diagnostics.map((diagnostic: ICheckstyleDiagnostic) => diagnostic.violationKey), ], }, kind: CodeActionKind.QuickFix, From 7bcf764ff58585d2915a64bc40ef378fa45a3c71 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 22:45:22 +1300 Subject: [PATCH 11/18] Pass Checkstyle violation key to text edit quick fixes --- .../com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java | 2 +- .../com/shengchen/checkstyle/quickfix/QuickFixService.java | 4 +++- .../quickfix/whitepace/NewlineAtEndOfFileQuickFix.java | 2 +- .../quickfix/whitepace/NoWhitespaceAfterQuickFix.java | 2 +- .../quickfix/whitepace/NoWhitespaceBeforeQuickFix.java | 2 +- .../checkstyle/quickfix/whitepace/ParenPadQuickFix.java | 2 +- .../quickfix/whitepace/WhitespaceAfterQuickFix.java | 2 +- .../quickfix/whitepace/WhitespaceAroundQuickFix.java | 2 +- 8 files changed, 10 insertions(+), 8 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java index 2f873f8..9f9ecba 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java @@ -23,6 +23,6 @@ public abstract class BaseEditQuickFix implements IQuickFix { - public abstract TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc); + public abstract TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc); } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index c29bb64..467f145 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -125,10 +125,12 @@ public WorkspaceEdit quickFix( final int offset = offsets.get(i).intValue(); final IRegion lineInfo = document.getLineInformationOfOffset(offset); final IQuickFix quickFix = getQuickFix(sourceNames.get(i)); + final String violationKey = violationKeys.get(i); if (quickFix instanceof BaseQuickFix) { astRoot.accept(((BaseQuickFix) quickFix).getCorrectingASTVisitor(lineInfo, offset)); } else if (quickFix instanceof BaseEditQuickFix) { - final TextEdit edit = ((BaseEditQuickFix) quickFix).createTextEdit(lineInfo, offset, document); + final TextEdit edit = ((BaseEditQuickFix) quickFix).createTextEdit( + lineInfo, offset, violationKey, document); if (edit != null) { addAllEdits(edit, textEdits); } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java index 1673ed1..05e18f6 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java @@ -28,7 +28,7 @@ public class NewlineAtEndOfFileQuickFix extends BaseEditQuickFix { @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final String lastChar = doc.getLength() > 0 ? doc.get(doc.getLength() - 1, 1) : ""; diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java index 6acb5d7..9d7584e 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java @@ -30,7 +30,7 @@ public class NoWhitespaceAfterQuickFix extends BaseEditQuickFix { @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); /* Marker is first non-whitespace character after the problem */ diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java index 2f56a23..5397b5a 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java @@ -30,7 +30,7 @@ public class NoWhitespaceBeforeQuickFix extends BaseEditQuickFix { @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); /* Marker is first non-whitespace character after the problem */ diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java index fbd94ed..6da0c93 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java @@ -28,7 +28,7 @@ public class ParenPadQuickFix extends BaseEditQuickFix { @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); final char marker = doc.getChar(markerStartOffset); diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java index 75ee804..d8cedc0 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java @@ -30,7 +30,7 @@ public class WhitespaceAfterQuickFix extends BaseEditQuickFix { @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); final String string = doc.get(markerStartOffset, lineInfo.getLength() - fromStartOfLine); diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java index a6b2eef..cb80dc0 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java @@ -33,7 +33,7 @@ public class WhitespaceAroundQuickFix extends BaseEditQuickFix { private static final String OPERATORS = "-=!&|^<>"; @Override - public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, Document doc) { + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); final String string = doc.get(lineInfo.getOffset(), lineInfo.getLength()); From cd2444ba384d3df8c429f58e87332e77607c0c2e Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 22:45:47 +1300 Subject: [PATCH 12/18] ParenPadQuickFix: use violation key to choose correct fix --- .../quickfix/whitepace/ParenPadQuickFix.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java index 6da0c93..28b4d98 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/ParenPadQuickFix.java @@ -23,8 +23,12 @@ import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IRegion; import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.TextEdit; +/** + * Quick fix for https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/checks/whitespace/ParenPadCheck.html + */ public class ParenPadQuickFix extends BaseEditQuickFix { @Override @@ -33,16 +37,24 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String v final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); final char marker = doc.getChar(markerStartOffset); if (marker == '(') { - final String string = doc.get(markerStartOffset + 1, lineInfo.getLength() - fromStartOfLine - 1); - final int leadingWhitespace = measureLeadingWhitespace(string); - if (leadingWhitespace > 0) { - return new DeleteEdit(markerStartOffset + 1, leadingWhitespace); + if ("ws.followed".equals(violationKey)) { + final String string = doc.get(markerStartOffset + 1, lineInfo.getLength() - fromStartOfLine - 1); + final int leadingWhitespace = measureLeadingWhitespace(string); + if (leadingWhitespace > 0) { + return new DeleteEdit(markerStartOffset + 1, leadingWhitespace); + } + } else if ("ws.notFollowed".equals(violationKey)) { + return new InsertEdit(markerStartOffset + 1, " "); } } else if (marker == ')' && fromStartOfLine > 0) { - final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); - final int trailingWhitespace = measureTrailingWhitespace(string); - if (trailingWhitespace > 0) { - return new DeleteEdit(markerStartOffset - trailingWhitespace, trailingWhitespace); + if ("ws.preceded".equals(violationKey)) { + final String string = doc.get(lineInfo.getOffset(), fromStartOfLine); + final int trailingWhitespace = measureTrailingWhitespace(string); + if (trailingWhitespace > 0) { + return new DeleteEdit(markerStartOffset - trailingWhitespace, trailingWhitespace); + } + } else if ("ws.notPreceded".equals(violationKey)) { + return new InsertEdit(markerStartOffset, " "); } } From cd0d3d717d7df67f9b9466abb04e56156d3c63a6 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 22:59:02 +1300 Subject: [PATCH 13/18] Fix issue with whitespace changes conflicting with AST changes e.g. public static void main(String[] args) { becomes public static void main(final String[] args ) { under --- .../checkstyle/quickfix/QuickFixService.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 467f145..5d0f8f5 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -137,14 +137,26 @@ public WorkspaceEdit quickFix( } } - final MultiTextEdit result = (MultiTextEdit) astRoot.rewrite(document, null); - for (final TextEdit anotherEdit : textEdits) { + /* Add text edits before AST edits, as whitespace changes need to be applied first */ + final MultiTextEdit result = new MultiTextEdit(); + for (final TextEdit textEdit : textEdits) { try { - result.addChild(anotherEdit.copy()); + result.addChild(textEdit.copy()); } catch (MalformedTreeException e) { - /* Ignore text edits that can't be added; it is due to conflicts with an AST edit */ + /* Ignore text edits that can't be added; it is due to conflicts */ } } + + final MultiTextEdit astEdits = (MultiTextEdit) astRoot.rewrite(document, null); + while (astEdits.getChildrenSize() > 0) { + final TextEdit astEdit = astEdits.removeChild(0); + try { + result.addChild(astEdit); + } catch (MalformedTreeException e) { + /* Ignore text edits that can't be added; it is due to conflicts */ + } + } + return EditUtils.convertToWorkspaceEdit(unit, result); } From 5843bf6b4d5168adb3e28736885a380877adc9e8 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 23:27:14 +1300 Subject: [PATCH 14/18] Move whitespace utility functions into BaseEditQuickFix --- .../checkstyle/quickfix/BaseEditQuickFix.java | 33 +++++++++++++++++++ .../whitepace/NoWhitespaceAfterQuickFix.java | 12 ------- .../whitepace/NoWhitespaceBeforeQuickFix.java | 12 ------- .../whitepace/WhitespaceAfterQuickFix.java | 12 ------- .../whitepace/WhitespaceAroundQuickFix.java | 12 ------- 5 files changed, 33 insertions(+), 48 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java index 9f9ecba..ed1dcd8 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/BaseEditQuickFix.java @@ -21,8 +21,41 @@ import org.eclipse.jface.text.IRegion; import org.eclipse.text.edits.TextEdit; +import java.util.function.Predicate; + public abstract class BaseEditQuickFix implements IQuickFix { public abstract TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc); + + protected int measureToken(String string, Predicate tokenPredicate) { + return measureToken(string, 0, tokenPredicate); + } + + protected int measureToken(String string, int from, Predicate tokenPredicate) { + final int n = string.length(); + for (int i = from; i < n; i++) { + if (!tokenPredicate.test(string.charAt(i))) { + return i - from; + } + } + return n - from; + } + + protected int measureTokenBackwards(String string, Predicate tokenPredicate) { + return measureTokenBackwards(string, -1, tokenPredicate); + } + + protected int measureTokenBackwards(String string, int from, Predicate tokenPredicate) { + final int n = string.length(); + if (from == -1) { + from = n - 1; + } + for (int i = from; i >= 0; i--) { + if (!tokenPredicate.test(string.charAt(i))) { + return from - i; + } + } + return from + 1; + } } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java index 9d7584e..c4db1ea 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceAfterQuickFix.java @@ -25,8 +25,6 @@ import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.TextEdit; -import java.util.function.Predicate; - public class NoWhitespaceAfterQuickFix extends BaseEditQuickFix { @Override @@ -47,14 +45,4 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String v } } - private int measureTokenBackwards(String string, Predicate tokenPredicate) { - final int n = string.length(); - for (int i = n - 1; i >= 0; i--) { - if (!tokenPredicate.test(string.charAt(i))) { - return n - 1 - i; - } - } - return n; - } - } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java index 5397b5a..cbf4cc3 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NoWhitespaceBeforeQuickFix.java @@ -25,8 +25,6 @@ import org.eclipse.text.edits.DeleteEdit; import org.eclipse.text.edits.TextEdit; -import java.util.function.Predicate; - public class NoWhitespaceBeforeQuickFix extends BaseEditQuickFix { @Override @@ -47,14 +45,4 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String v } } - private int measureTokenBackwards(String string, Predicate tokenPredicate) { - final int n = string.length(); - for (int i = n - 1; i >= 0; i--) { - if (!tokenPredicate.test(string.charAt(i))) { - return n - 1 - i; - } - } - return n; - } - } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java index d8cedc0..a6e595d 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAfterQuickFix.java @@ -25,8 +25,6 @@ import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.TextEdit; -import java.util.function.Predicate; - public class WhitespaceAfterQuickFix extends BaseEditQuickFix { @Override @@ -54,14 +52,4 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String v } } - private int measureToken(String string, Predicate tokenPredicate) { - final int n = string.length(); - for (int i = 0; i < n; i++) { - if (!tokenPredicate.test(string.charAt(i))) { - return i; - } - } - return n; - } - } diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java index cb80dc0..6b96cec 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/WhitespaceAroundQuickFix.java @@ -26,8 +26,6 @@ import org.eclipse.text.edits.MultiTextEdit; import org.eclipse.text.edits.TextEdit; -import java.util.function.Predicate; - public class WhitespaceAroundQuickFix extends BaseEditQuickFix { private static final String OPERATORS = "-=!&|^<>"; @@ -70,14 +68,4 @@ public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String v } } - private int measureToken(String string, int start, Predicate tokenPredicate) { - final int n = string.length(); - for (int i = start; i < n; i++) { - if (!tokenPredicate.test(string.charAt(i))) { - return i - start; - } - } - return n; - } - } From 9de7299c1406bcb656b901a0877bda5337f9f721 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 23:27:34 +1300 Subject: [PATCH 15/18] Add GenericWhitespaceQuickFix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/GenericWhitespaceQuickFix.java | 63 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 67 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/GenericWhitespaceQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index d7c457f..5d18839 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -41,6 +41,7 @@ public enum FixableCheck { NO_WHITESPACE_AFTER_CHECK("NoWhitespaceAfterCheck"), NO_WHITESPACE_BEFORE_CHECK("NoWhitespaceBeforeCheck"), NEWLINE_AT_END_OF_FILE_CHECK("NewlineAtEndOfFileCheck"), + GENERIC_WHITESPACE_CHECK("GenericWhitespaceCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 5d0f8f5..84180f4 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -37,6 +37,7 @@ import com.shengchen.checkstyle.quickfix.modifier.ModifierOrderQuickFix; import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; +import com.shengchen.checkstyle.quickfix.whitepace.GenericWhitespaceQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NewlineAtEndOfFileQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceAfterQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceBeforeQuickFix; @@ -99,6 +100,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.NO_WHITESPACE_AFTER_CHECK.toString(), new NoWhitespaceAfterQuickFix()); quickFixMap.put(FixableCheck.NO_WHITESPACE_BEFORE_CHECK.toString(), new NoWhitespaceBeforeQuickFix()); quickFixMap.put(FixableCheck.NEWLINE_AT_END_OF_FILE_CHECK.toString(), new NewlineAtEndOfFileQuickFix()); + quickFixMap.put(FixableCheck.GENERIC_WHITESPACE_CHECK.toString(), new GenericWhitespaceQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/GenericWhitespaceQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/GenericWhitespaceQuickFix.java new file mode 100644 index 0000000..28c6df8 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/GenericWhitespaceQuickFix.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.TextEdit; + +/** + * Quick fix for + * https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/checks/whitespace/GenericWhitespaceCheck.html + */ +public class GenericWhitespaceQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final String string = doc.get(lineInfo.getOffset(), lineInfo.getLength()); + + if ("ws.illegalFollow".equals(violationKey)) { + return new InsertEdit(markerStartOffset + 1, " "); + } else if ("ws.notPreceded".equals(violationKey)) { + return new InsertEdit(markerStartOffset, " "); + } else if ("ws.followed".equals(violationKey)) { + final int tokenLength = measureToken(string, fromStartOfLine + 1, Character::isWhitespace); + if (tokenLength > 0) { + return new DeleteEdit(markerStartOffset + 1, tokenLength); + } + } else if ("ws.preceded".equals(violationKey)) { + final int tokenLength = measureTokenBackwards(string, fromStartOfLine - 1, Character::isWhitespace); + if (tokenLength > 0) { + return new DeleteEdit(markerStartOffset - tokenLength, tokenLength); + } + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index f4073f3..ace0244 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -32,6 +32,7 @@ export enum FixableCheck { NoWhitespaceAfterCheck = 'NoWhitespaceAfterCheck', NoWhitespaceBeforeCheck = 'NoWhitespaceBeforeCheck', NewlineAtEndOfFileCheck = 'NewlineAtEndOfFileCheck', + GenericWhitespaceCheck = 'GenericWhitespaceCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From bfe328b6c7f6cd1e6d760c5848cea907375723c9 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Mon, 25 Jan 2021 23:31:08 +1300 Subject: [PATCH 16/18] Add MethodParamPadQuickFix --- .../checkstyle/quickfix/FixableCheck.java | 1 + .../checkstyle/quickfix/QuickFixService.java | 2 + .../whitepace/MethodParamPadQuickFix.java | 56 +++++++++++++++++++ src/constants/quickFix.ts | 1 + 4 files changed, 60 insertions(+) create mode 100644 jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/MethodParamPadQuickFix.java diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java index 5d18839..eeec08e 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/FixableCheck.java @@ -42,6 +42,7 @@ public enum FixableCheck { NO_WHITESPACE_BEFORE_CHECK("NoWhitespaceBeforeCheck"), NEWLINE_AT_END_OF_FILE_CHECK("NewlineAtEndOfFileCheck"), GENERIC_WHITESPACE_CHECK("GenericWhitespaceCheck"), + METHOD_PARAM_PAD_CHECK("MethodParamPadCheck"), // Misc FINAL_PARAMETERS_CHECK("FinalParametersCheck"), UNCOMMENTED_MAIN_CHECK("UncommentedMainCheck"), diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index 84180f4..d738532 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -38,6 +38,7 @@ import com.shengchen.checkstyle.quickfix.modifier.RedundantModifierQuickFix; import com.shengchen.checkstyle.quickfix.utils.EditUtils; import com.shengchen.checkstyle.quickfix.whitepace.GenericWhitespaceQuickFix; +import com.shengchen.checkstyle.quickfix.whitepace.MethodParamPadQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NewlineAtEndOfFileQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceAfterQuickFix; import com.shengchen.checkstyle.quickfix.whitepace.NoWhitespaceBeforeQuickFix; @@ -101,6 +102,7 @@ public QuickFixService() { quickFixMap.put(FixableCheck.NO_WHITESPACE_BEFORE_CHECK.toString(), new NoWhitespaceBeforeQuickFix()); quickFixMap.put(FixableCheck.NEWLINE_AT_END_OF_FILE_CHECK.toString(), new NewlineAtEndOfFileQuickFix()); quickFixMap.put(FixableCheck.GENERIC_WHITESPACE_CHECK.toString(), new GenericWhitespaceQuickFix()); + quickFixMap.put(FixableCheck.METHOD_PARAM_PAD_CHECK.toString(), new MethodParamPadQuickFix()); } public IQuickFix getQuickFix(String sourceName) { diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/MethodParamPadQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/MethodParamPadQuickFix.java new file mode 100644 index 0000000..2a3cda7 --- /dev/null +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/MethodParamPadQuickFix.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) jdneo + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.shengchen.checkstyle.quickfix.whitepace; + +import com.shengchen.checkstyle.quickfix.BaseEditQuickFix; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IRegion; +import org.eclipse.text.edits.DeleteEdit; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.TextEdit; + +/** + * Quick fix for + * https://checkstyle.org/apidocs/com/puppycrawl/tools/checkstyle/checks/whitespace/MethodParamPadCheck.html + */ +public class MethodParamPadQuickFix extends BaseEditQuickFix { + + @Override + public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { + try { + final int fromStartOfLine = markerStartOffset - lineInfo.getOffset(); + final String string = doc.get(lineInfo.getOffset(), lineInfo.getLength()); + + if ("ws.notPreceded".equals(violationKey)) { + return new InsertEdit(markerStartOffset, " "); + } else if ("ws.preceded".equals(violationKey)) { + final int tokenLength = measureTokenBackwards(string, fromStartOfLine - 1, Character::isWhitespace); + if (tokenLength > 0) { + return new DeleteEdit(markerStartOffset - tokenLength, tokenLength); + } + } + + return null; + } catch (BadLocationException e) { + return null; + } + } + +} diff --git a/src/constants/quickFix.ts b/src/constants/quickFix.ts index ace0244..c9a168a 100644 --- a/src/constants/quickFix.ts +++ b/src/constants/quickFix.ts @@ -33,6 +33,7 @@ export enum FixableCheck { NoWhitespaceBeforeCheck = 'NoWhitespaceBeforeCheck', NewlineAtEndOfFileCheck = 'NewlineAtEndOfFileCheck', GenericWhitespaceCheck = 'GenericWhitespaceCheck', + MethodParamPadCheck = 'MethodParamPadCheck', // Misc FinalParametersCheck = 'FinalParametersCheck', From 35274440704800a54a89b81e1f9f3136be62ffcc Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Tue, 9 Feb 2021 19:07:50 +1300 Subject: [PATCH 17/18] Check whether a quickfix exists early --- .../com/shengchen/checkstyle/quickfix/QuickFixService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java index d738532..9d39496 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/QuickFixService.java @@ -126,9 +126,13 @@ public WorkspaceEdit quickFix( final List textEdits = new ArrayList<>(); for (int i = 0; i < offsets.size(); i++) { + final IQuickFix quickFix = getQuickFix(sourceNames.get(i)); + if (quickFix == null) { + continue; + } + final int offset = offsets.get(i).intValue(); final IRegion lineInfo = document.getLineInformationOfOffset(offset); - final IQuickFix quickFix = getQuickFix(sourceNames.get(i)); final String violationKey = violationKeys.get(i); if (quickFix instanceof BaseQuickFix) { astRoot.accept(((BaseQuickFix) quickFix).getCorrectingASTVisitor(lineInfo, offset)); From 5ba919b4cd7e17c79e7c11f0f7d3211e737257e0 Mon Sep 17 00:00:00 2001 From: Karl von Randow Date: Tue, 9 Feb 2021 19:19:55 +1300 Subject: [PATCH 18/18] NewlineAtEndOfFileQuickFix: match defaults of NewlineAtEndOfFileCheck --- .../quickfix/whitepace/NewlineAtEndOfFileQuickFix.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java index 05e18f6..95254e7 100644 --- a/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java +++ b/jdtls.ext/com.shengchen.checkstyle.runner/src/main/java/com/shengchen/checkstyle/quickfix/whitepace/NewlineAtEndOfFileQuickFix.java @@ -31,9 +31,11 @@ public class NewlineAtEndOfFileQuickFix extends BaseEditQuickFix { public TextEdit createTextEdit(IRegion lineInfo, int markerStartOffset, String violationKey, Document doc) { try { final String lastChar = doc.getLength() > 0 ? doc.get(doc.getLength() - 1, 1) : ""; - - if (lastChar.isEmpty() || !"\n".equals(lastChar)) { - return new InsertEdit(doc.getLength(), "\n"); + + /* By default NewlineAtEndOfFileCheck looks for any of CR LF or CRLF */ + if (!"\n".equals(lastChar) && !"\r".equals(lastChar)) { + /* By default we add the platform-specific line separator. */ + return new InsertEdit(doc.getLength(), System.getProperty("line.separator")); } return null;