From 376154328995d385a29b5c91ded0dc52580a210b Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 4 Dec 2017 16:30:33 +0300 Subject: [PATCH] project configuration: highlight errors in 'Convert Module Groups' dialog Spellchecker is disabled because module names will often include the name of organization and we can get many false positives because of that. --- .../project/ModuleNamesListInspection.kt | 59 +++++++++++++++++++ .../convertModuleGroupsToQualifiedNames.kt | 26 +++++++- ...llCheckingEditorCustomizationProvider.java | 10 ++++ .../src/messages/ProjectBundle.properties | 5 ++ .../ui/SpellCheckingEditorCustomization.java | 6 ++ ...eckingEditorCustomizationProviderImpl.java | 7 +++ 6 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 platform/platform-impl/src/com/intellij/ide/actions/project/ModuleNamesListInspection.kt diff --git a/platform/platform-impl/src/com/intellij/ide/actions/project/ModuleNamesListInspection.kt b/platform/platform-impl/src/com/intellij/ide/actions/project/ModuleNamesListInspection.kt new file mode 100644 index 000000000000..de58741297dd --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/project/ModuleNamesListInspection.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. + */ +package com.intellij.ide.actions.project + +import com.intellij.codeHighlighting.HighlightDisplayLevel +import com.intellij.codeInspection.* +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.ProjectBundle +import com.intellij.openapi.util.TextRange +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiFile + +internal class ModuleNamesListInspection : LocalInspectionTool() { + override fun checkFile(file: PsiFile, manager: InspectionManager, isOnTheFly: Boolean): Array? { + val document = PsiDocumentManager.getInstance(manager.project).getDocument(file) ?: return null + + val lines = file.text.lines() + val counts = lines.fold(HashMap(), { map, s -> map[s] = map.getOrDefault(s, 0) + 1; map }) + val problems = ArrayList() + + fun addProblem(line: Int, message: String) { + val range = if (line < document.lineCount) { + TextRange(document.getLineStartOffset(line), document.getLineEndOffset(line)) + } + else { + TextRange(document.textLength, document.textLength) + } + val afterEnd = range.isEmpty + problems += ProblemDescriptorBase(file, file, message, emptyArray(), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, afterEnd, range, true, isOnTheFly) + } + + val modulesCount = ModuleManager.getInstance(manager.project).modules.size + lines.forEachIndexed { line, s -> + if (s.isEmpty()) { + addProblem(line, ProjectBundle.message("module.name.inspection.empty.name.is.not.allowed")) + } + else if (counts[s]!! > 1) { + addProblem(line, ProjectBundle.message("module.name.inspection.duplicate.module.name", s)) + } + if (line >= modulesCount) { + addProblem(line, ProjectBundle.message("module.name.inspection.too.many.lines", modulesCount, line+1)) + } + } + if (lines.size < modulesCount) { + addProblem(lines.size, ProjectBundle.message("module.name.inspection.too.few.lines", modulesCount, lines.size)) + } + + return problems.toTypedArray() + } + + override fun getDisplayName() = ProjectBundle.message("module.name.inspection.display.name") + + override fun getStaticDescription() = "" + + override fun isEnabledByDefault() = true + + override fun getDefaultLevel(): HighlightDisplayLevel = HighlightDisplayLevel.ERROR +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/actions/project/convertModuleGroupsToQualifiedNames.kt b/platform/platform-impl/src/com/intellij/ide/actions/project/convertModuleGroupsToQualifiedNames.kt index 9195057ecf52..69a39fc148d5 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/project/convertModuleGroupsToQualifiedNames.kt +++ b/platform/platform-impl/src/com/intellij/ide/actions/project/convertModuleGroupsToQualifiedNames.kt @@ -3,11 +3,17 @@ package com.intellij.ide.actions.project import com.intellij.CommonBundle import com.intellij.codeInsight.intention.IntentionManager +import com.intellij.codeInspection.ex.InspectionProfileImpl +import com.intellij.codeInspection.ex.InspectionProfileWrapper +import com.intellij.codeInspection.ex.InspectionToolWrapper +import com.intellij.codeInspection.ex.LocalInspectionToolWrapper import com.intellij.lang.StdLanguages import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.editor.Document +import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.LineExtensionInfo +import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider import com.intellij.openapi.editor.impl.EditorImpl import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.DumbAwareAction @@ -15,6 +21,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.project.ProjectBundle import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.Messages +import com.intellij.psi.PsiDocumentManager import com.intellij.ui.* import com.intellij.ui.components.JBLabel import com.intellij.util.ui.JBUI @@ -22,6 +29,8 @@ import com.intellij.util.ui.UIUtil import com.intellij.xml.util.XmlStringUtil import java.awt.Color import java.awt.Font +import java.util.function.Function +import java.util.function.Supplier import javax.swing.Action import javax.swing.JPanel @@ -45,13 +54,28 @@ class ConvertModuleGroupsToQualifiedNamesDialog(val project: Project) : DialogWr isAdditionalPageAtBottom = false isShowIntentionBulb = false } - it.putUserData(IntentionManager.SHOW_INTENTION_OPTIONS_KEY, false) (it as? EditorImpl)?.registerLineExtensionPainter(this::generateLineExtension) + setupHighlighting(it) }, MonospaceEditorCustomization.getInstance())) editorArea.text = generateInitialText() init() } + private fun setupHighlighting(editor: Editor) { + editor.putUserData(IntentionManager.SHOW_INTENTION_OPTIONS_KEY, false) + val inspections = Supplier>> { + listOf(LocalInspectionToolWrapper(ModuleNamesListInspection())) + } + val file = PsiDocumentManager.getInstance(project).getPsiFile(document) + file?.putUserData(InspectionProfileWrapper.CUSTOMIZATION_KEY, Function { + val profile = InspectionProfileImpl("Module names", inspections, null) + for (spellCheckingToolName in SpellCheckingEditorCustomizationProvider.getInstance().spellCheckingToolNames) { + profile.getToolsOrNull(spellCheckingToolName, project)?.isEnabled = false + } + InspectionProfileWrapper(profile) + }) + } + override fun createCenterPanel(): JPanel { val text = XmlStringUtil.wrapInHtml(ProjectBundle.message("convert.module.groups.description.text")) return JBUI.Panels.simplePanel(0, UIUtil.DEFAULT_VGAP).addToCenter(editorArea).addToTop(JBLabel(text)) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/SpellCheckingEditorCustomizationProvider.java b/platform/platform-impl/src/com/intellij/openapi/editor/SpellCheckingEditorCustomizationProvider.java index a8ed0ea52241..0fcc1426ebad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/SpellCheckingEditorCustomizationProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/SpellCheckingEditorCustomizationProvider.java @@ -20,6 +20,9 @@ import com.intellij.ui.EditorCustomization; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; +import java.util.Set; + /** * @author nik */ @@ -43,4 +46,11 @@ public class SpellCheckingEditorCustomizationProvider { public EditorCustomization getDisabledCustomization() { return null; } + + /** + * @return set containing {@link com.intellij.codeInspection.InspectionProfileEntry#getShortName()} values for spell checking inspections + */ + public Set getSpellCheckingToolNames() { + return Collections.emptySet(); + } } diff --git a/platform/projectModel-impl/src/messages/ProjectBundle.properties b/platform/projectModel-impl/src/messages/ProjectBundle.properties index f2b686f808e4..5afb61867dfd 100644 --- a/platform/projectModel-impl/src/messages/ProjectBundle.properties +++ b/platform/projectModel-impl/src/messages/ProjectBundle.properties @@ -153,6 +153,11 @@ convert.module.groups.description.text=Each line in the text below corresponds t rename modules and discard module groups. module.name.mapping.load.button.text=&Load... module.name.mapping.save.button.text=&Save... +module.name.inspection.display.name=Module names validation +module.name.inspection.empty.name.is.not.allowed=Empty module names aren't allowed +module.name.inspection.duplicate.module.name=Duplicate module name ''{0}'' +module.name.inspection.too.many.lines=There are {0} modules in the project so line {1} doesn't correspond to a module +module.name.inspection.too.few.lines=There are {0} modules in the project but only {1} lines here button.text.attach.files=Attach &Files or Directories... library.attach.files.action=Attach Files or Directories diff --git a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java index bf06c62e3ebb..ee4c4b2ee687 100644 --- a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java +++ b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java @@ -34,8 +34,10 @@ import com.intellij.ui.SimpleEditorCustomization; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.function.Function; /** @@ -127,6 +129,10 @@ public class SpellCheckingEditorCustomization extends SimpleEditorCustomization } } + public static Set getSpellCheckingToolNames() { + return Collections.unmodifiableSet(SPELL_CHECK_TOOLS.keySet()); + } + private static class MyInspectionProfileStrategy implements Function { private final Map myWrappers = ContainerUtil.createWeakMap(); private boolean myUseSpellCheck; diff --git a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationProviderImpl.java b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationProviderImpl.java index e48fe863a2ad..8131b9bf3fe8 100644 --- a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationProviderImpl.java +++ b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationProviderImpl.java @@ -19,6 +19,8 @@ import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; import com.intellij.ui.EditorCustomization; import org.jetbrains.annotations.Nullable; +import java.util.Set; + /** * @author nik */ @@ -37,4 +39,9 @@ public class SpellCheckingEditorCustomizationProviderImpl extends SpellCheckingE public EditorCustomization getDisabledCustomization() { return DISABLED; } + + @Override + public Set getSpellCheckingToolNames() { + return SpellCheckingEditorCustomization.getSpellCheckingToolNames(); + } }