mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Add "Reformat commit message" action and quick fix
This commit is contained in:
@@ -239,6 +239,7 @@
|
||||
use-shortcut-of="Diff.ShowDiff" icon="AllIcons.Actions.Diff"/>
|
||||
</group>
|
||||
|
||||
<action id="Vcs.ReformatCommitMessage" class="com.intellij.vcs.commit.ReformatCommitMessageAction" use-shortcut-of="ReformatCode"/>
|
||||
<group id="Vcs.MessageActionGroup">
|
||||
<action id="Vcs.ShowMessageHistory"
|
||||
class="com.intellij.openapi.vcs.actions.ShowMessageHistoryAction"
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInsight.daemon.impl.IntentionActionFilter;
|
||||
import com.intellij.codeInsight.intention.EmptyIntentionAction;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.longLine.LongLineInspection;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -34,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.codeInspection.ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
|
||||
import static com.intellij.openapi.vcs.ui.CommitMessage.isCommitMessage;
|
||||
import static com.intellij.util.ArrayUtil.isEmpty;
|
||||
|
||||
public abstract class BaseCommitMessageInspection extends LocalInspectionTool {
|
||||
|
||||
@@ -99,6 +101,19 @@ public abstract class BaseCommitMessageInspection extends LocalInspectionTool {
|
||||
.createProblemDescriptor(file, exceedingRange, problemText, GENERIC_ERROR_OR_WARNING, isOnTheFly, fixes) : null;
|
||||
}
|
||||
|
||||
public boolean canReformat(@NotNull Project project, @NotNull Document document) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reformat(@NotNull Project project, @NotNull Document document) {
|
||||
}
|
||||
|
||||
protected boolean hasProblems(@NotNull Project project, @NotNull Document document) {
|
||||
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
|
||||
return file != null && !isEmpty(checkFile(file, document, InspectionManager.getInstance(project), false));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Document getDocument(@NotNull PsiElement element) {
|
||||
return PsiDocumentManager.getInstance(element.getProject()).getDocument(element.getContainingFile());
|
||||
@@ -125,6 +140,17 @@ public abstract class BaseCommitMessageInspection extends LocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void doApplyFix(@NotNull Project project, @NotNull Document document, @NotNull ProblemDescriptor descriptor);
|
||||
public abstract void doApplyFix(@NotNull Project project, @NotNull Document document, @Nullable ProblemDescriptor descriptor);
|
||||
}
|
||||
|
||||
protected static class ReformatCommitMessageQuickFix extends BaseCommitMessageQuickFix implements LowPriorityAction {
|
||||
protected ReformatCommitMessageQuickFix() {
|
||||
super(ReformatCommitMessageAction.NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doApplyFix(@NotNull Project project, @NotNull Document document, @Nullable ProblemDescriptor descriptor) {
|
||||
ReformatCommitMessageAction.reformat(project, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,22 +65,35 @@ public class BodyLimitInspection extends BaseCommitMessageInspection {
|
||||
boolean isOnTheFly) {
|
||||
return range(1, document.getLineCount())
|
||||
.mapToObj(line -> checkRightMargin(file, document, manager, isOnTheFly, line, RIGHT_MARGIN,
|
||||
format("Body lines should not exceed %d characters", RIGHT_MARGIN), new WrapLineQuickFix()))
|
||||
format("Body lines should not exceed %d characters", RIGHT_MARGIN), new WrapLineQuickFix(),
|
||||
new ReformatCommitMessageQuickFix()))
|
||||
.filter(Objects::nonNull)
|
||||
.toArray(ProblemDescriptor[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReformat(@NotNull Project project, @NotNull Document document) {
|
||||
return hasProblems(project, document);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reformat(@NotNull Project project, @NotNull Document document) {
|
||||
new WrapLineQuickFix().doApplyFix(project, document, null);
|
||||
}
|
||||
|
||||
protected class WrapLineQuickFix extends BaseCommitMessageQuickFix {
|
||||
protected WrapLineQuickFix() {
|
||||
super("Wrap line");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doApplyFix(@NotNull Project project, @NotNull Document document, @NotNull ProblemDescriptor descriptor) {
|
||||
public void doApplyFix(@NotNull Project project, @NotNull Document document, @Nullable ProblemDescriptor descriptor) {
|
||||
Editor editor = CommitMessage.getEditor(document);
|
||||
|
||||
if (editor != null) {
|
||||
TextRange range = descriptor.getLineNumber() >= 0 ? getLineTextRange(document, descriptor.getLineNumber()) : EMPTY_RANGE;
|
||||
TextRange range = descriptor != null && descriptor.getLineNumber() >= 0
|
||||
? getLineTextRange(document, descriptor.getLineNumber())
|
||||
: getBodyRange(document);
|
||||
|
||||
if (!range.isEmpty()) {
|
||||
wrapLines(project, editor, document, RIGHT_MARGIN, range);
|
||||
@@ -88,6 +101,11 @@ public class BodyLimitInspection extends BaseCommitMessageInspection {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TextRange getBodyRange(@NotNull Document document) {
|
||||
return document.getLineCount() > 1 ? TextRange.create(document.getLineStartOffset(1), document.getTextLength()) : EMPTY_RANGE;
|
||||
}
|
||||
|
||||
private void wrapLines(@NotNull Project project,
|
||||
@NotNull Editor editor,
|
||||
@NotNull Document document,
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.vcs.commit;
|
||||
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper;
|
||||
import com.intellij.codeInspection.ex.Tools;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsDataKeys;
|
||||
import com.intellij.openapi.vcs.ui.CommitMessage;
|
||||
import org.jetbrains.annotations.CalledWithWriteLock;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.notNull;
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
public class ReformatCommitMessageAction extends DumbAwareAction {
|
||||
|
||||
public static final String NAME = "Reformat commit message";
|
||||
|
||||
public ReformatCommitMessageAction() {
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
Project project = e.getProject();
|
||||
Document document = getCommitMessage(e);
|
||||
|
||||
e.getPresentation().setEnabled(project != null &&
|
||||
document != null &&
|
||||
getEnabledInspections(project).anyMatch(inspection -> inspection.canReformat(project, document)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
Project project = notNull(e.getProject());
|
||||
Document document = notNull(getCommitMessage(e));
|
||||
|
||||
CommandProcessor.getInstance().executeCommand(project, () ->
|
||||
WriteAction.run(() -> reformat(project, document)), NAME, null);
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
public static void reformat(@NotNull Project project, @NotNull Document document) {
|
||||
List<BaseCommitMessageInspection> inspections = getEnabledInspections(project).collect(toList());
|
||||
|
||||
inspections.forEach(inspection -> inspection.reformat(project, document));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Document getCommitMessage(@NotNull AnActionEvent e) {
|
||||
CommitMessage commitMessage = tryCast(e.getData(VcsDataKeys.COMMIT_MESSAGE_CONTROL), CommitMessage.class);
|
||||
Editor editor = commitMessage != null ? commitMessage.getEditorField().getEditor() : null;
|
||||
|
||||
return editor != null ? editor.getDocument() : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Stream<BaseCommitMessageInspection> getEnabledInspections(@NotNull Project project) {
|
||||
return CommitMessageInspectionProfile.getInstance(project).getAllEnabledInspectionTools(project).stream()
|
||||
.map(Tools::getTool)
|
||||
.map(InspectionToolWrapper::getTool)
|
||||
.filter(BaseCommitMessageInspection.class::isInstance)
|
||||
.map(BaseCommitMessageInspection.class::cast);
|
||||
}
|
||||
}
|
||||
@@ -44,26 +44,43 @@ public class SubjectBodySeparationInspection extends BaseCommitMessageInspection
|
||||
boolean isOnTheFly) {
|
||||
ProblemDescriptor descriptor = document.getLineCount() > 1
|
||||
? checkRightMargin(file, document, manager, isOnTheFly, 1, 0,
|
||||
"Missing blank line between subject and body", new AddBlankLineQuickFix())
|
||||
"Missing blank line between subject and body", new AddBlankLineQuickFix(),
|
||||
new ReformatCommitMessageQuickFix())
|
||||
: null;
|
||||
|
||||
return descriptor != null ? ar(descriptor) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canReformat(@NotNull Project project, @NotNull Document document) {
|
||||
return hasProblems(project, document);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reformat(@NotNull Project project, @NotNull Document document) {
|
||||
new AddBlankLineQuickFix().doApplyFix(project, document, null);
|
||||
}
|
||||
|
||||
protected static class AddBlankLineQuickFix extends BaseCommitMessageQuickFix {
|
||||
protected AddBlankLineQuickFix() {
|
||||
super("Add blank line");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doApplyFix(@NotNull Project project, @NotNull Document document, @NotNull ProblemDescriptor descriptor) {
|
||||
if (descriptor.getLineNumber() >= 0) {
|
||||
TextRange lineRange = getLineTextRange(document, descriptor.getLineNumber());
|
||||
public void doApplyFix(@NotNull Project project, @NotNull Document document, @Nullable ProblemDescriptor descriptor) {
|
||||
int line = descriptor != null && descriptor.getLineNumber() >= 0 ? descriptor.getLineNumber() : getFirstLine(document);
|
||||
|
||||
if (line >= 0) {
|
||||
TextRange lineRange = getLineTextRange(document, line);
|
||||
|
||||
if (!lineRange.isEmpty()) {
|
||||
document.insertString(lineRange.getStartOffset(), "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int getFirstLine(@NotNull Document document) {
|
||||
return document.getLineCount() > 1 ? 1 : -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user