summaryrefslogtreecommitdiff
path: root/lint/src
diff options
context:
space:
mode:
authorMatthew Gharrity <gharrma@google.com>2021-06-01 14:34:57 -0400
committerTreeHugger Robot <treehugger-gerrit@google.com>2021-06-01 23:58:50 +0000
commit4972efc377739e0bc7ae6b9636dffe97e34f0acd (patch)
treee48e1949240a418874f215df9601dc01151e4a08 /lint/src
parent1e1637b4704924b5ae734ea24f38cc2dc8c1e8f2 (diff)
downloadidea-4972efc377739e0bc7ae6b9636dffe97e34f0acd.tar.gz
Convert LintExternalAnnotator to Kotlin
Change-Id: I99324ecd9589c5f8eca544b67035075ef1b37abd
Diffstat (limited to 'lint/src')
-rw-r--r--lint/src/com/android/tools/idea/lint/common/LintExternalAnnotator.kt654
-rw-r--r--lint/src/com/android/tools/idea/lint/common/LintGlobalInspectionContext.java2
2 files changed, 272 insertions, 384 deletions
diff --git a/lint/src/com/android/tools/idea/lint/common/LintExternalAnnotator.kt b/lint/src/com/android/tools/idea/lint/common/LintExternalAnnotator.kt
index 14690f5766b..00f306ba36a 100644
--- a/lint/src/com/android/tools/idea/lint/common/LintExternalAnnotator.kt
+++ b/lint/src/com/android/tools/idea/lint/common/LintExternalAnnotator.kt
@@ -13,456 +13,344 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.tools.idea.lint.common;
-
-import static com.android.SdkConstants.ANDROID_MANIFEST_XML;
-import static com.android.SdkConstants.DOT_KTS;
-import static com.android.SdkConstants.DOT_XML;
-import static com.android.SdkConstants.FN_PROJECT_PROGUARD_FILE;
-import static com.android.SdkConstants.OLD_PROGUARD_FILE;
-import static com.android.tools.lint.detector.api.TextFormat.HTML;
-import static com.android.tools.lint.detector.api.TextFormat.RAW;
+package com.android.tools.idea.lint.common
+
+import com.android.SdkConstants.ANDROID_MANIFEST_XML
+import com.android.SdkConstants.DOT_KTS
+import com.android.SdkConstants.DOT_XML
+import com.android.SdkConstants.FN_PROJECT_PROGUARD_FILE
+import com.android.SdkConstants.OLD_PROGUARD_FILE
+import com.android.tools.lint.checks.DeprecationDetector
+import com.android.tools.lint.checks.GradleDetector
+import com.android.tools.lint.checks.WrongIdDetector
+import com.android.tools.lint.client.api.LintClient
+import com.android.tools.lint.client.api.LintRequest
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.TextFormat.HTML
+import com.android.tools.lint.detector.api.TextFormat.RAW
+import com.google.common.collect.Sets
+import com.intellij.codeHighlighting.HighlightDisplayLevel
+import com.intellij.codeInsight.daemon.HighlightDisplayKey
+import com.intellij.codeInsight.daemon.impl.HighlightInfo
+import com.intellij.codeInsight.intention.HighPriorityAction
+import com.intellij.codeInsight.intention.IntentionAction
+import com.intellij.codeInspection.InspectionManager
+import com.intellij.codeInspection.InspectionProfile
+import com.intellij.codeInspection.LocalQuickFix
+import com.intellij.codeInspection.ProblemHighlightType
+import com.intellij.codeInspection.ex.CustomEditInspectionToolsSettingsAction
+import com.intellij.codeInspection.ex.DisableInspectionToolAction
+import com.intellij.ide.highlighter.JavaFileType
+import com.intellij.ide.highlighter.XmlFileType
+import com.intellij.lang.annotation.AnnotationHolder
+import com.intellij.lang.annotation.ExternalAnnotator
+import com.intellij.lang.annotation.HighlightSeverity
+import com.intellij.lang.properties.PropertiesFileType
+import com.intellij.openapi.editor.Editor
+import com.intellij.openapi.module.Module
+import com.intellij.openapi.module.ModuleUtilCore
+import com.intellij.openapi.project.DumbService
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.Computable
+import com.intellij.openapi.util.Disposer
+import com.intellij.openapi.util.Iconable
+import com.intellij.openapi.util.Iconable.IconFlags
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.util.IncorrectOperationException
+import com.intellij.xml.util.XmlStringUtil
+import org.jetbrains.kotlin.idea.KotlinFileType
+import org.jetbrains.plugins.groovy.GroovyFileType
+import java.util.EnumSet
+import javax.swing.Icon
+
+class LintExternalAnnotator : ExternalAnnotator<LintEditorResult, LintEditorResult>() {
+
+ companion object {
+ const val LINK_PREFIX = "#lint/" // Should match the codeInsight.linkHandler prefix specified in lint-plugin.xml.
+ const val INCLUDE_IDEA_SUPPRESS_ACTIONS = false
+
+ init {
+ LintClient.clientName = LintClient.CLIENT_STUDIO
+ }
-import com.android.tools.lint.checks.DeprecationDetector;
-import com.android.tools.lint.checks.GradleDetector;
-import com.android.tools.lint.checks.WrongIdDetector;
-import com.android.tools.lint.client.api.IssueRegistry;
-import com.android.tools.lint.client.api.LintClient;
-import com.android.tools.lint.client.api.LintDriver;
-import com.android.tools.lint.client.api.LintRequest;
-import com.android.tools.lint.detector.api.Issue;
-import com.android.tools.lint.detector.api.LintFix;
-import com.android.tools.lint.detector.api.Scope;
-import com.google.common.collect.Sets;
-import com.intellij.codeHighlighting.HighlightDisplayLevel;
-import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.codeInsight.intention.HighPriorityAction;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ProblemHighlightType;
-import com.intellij.codeInspection.SuppressQuickFix;
-import com.intellij.codeInspection.ex.CustomEditInspectionToolsSettingsAction;
-import com.intellij.codeInspection.ex.DisableInspectionToolAction;
-import com.intellij.ide.highlighter.JavaFileType;
-import com.intellij.ide.highlighter.XmlFileType;
-import com.intellij.lang.annotation.AnnotationBuilder;
-import com.intellij.lang.annotation.AnnotationHolder;
-import com.intellij.lang.annotation.ExternalAnnotator;
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.lang.properties.PropertiesFileType;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtilCore;
-import com.intellij.openapi.project.DumbService;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Iconable;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.xml.util.XmlStringUtil;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Set;
-import javax.swing.Icon;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.kotlin.idea.KotlinFileType;
-import org.jetbrains.plugins.groovy.GroovyFileType;
+ fun getIssuesFromInspections(project: Project, context: PsiElement?): Set<Issue> {
+ val fullRegistry = LintIdeIssueRegistry.get()
+ val issueList = fullRegistry.issues
+ val result = Sets.newHashSetWithExpectedSize<Issue>(issueList.size + 10)
+ for (issue in issueList) {
+ val inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue) ?: continue
+ val key = HighlightDisplayKey.find(inspectionShortName) ?: continue
+ val profile: InspectionProfile = InspectionProjectProfileManager.getInstance(project).currentProfile
+ val enabled = if (context != null) profile.isToolEnabled(key, context) else profile.isToolEnabled(key)
+ if (!enabled) continue
+ if (!issue.isEnabledByDefault()) {
+ // If an issue is marked as not enabled by default, lint won't run it, even if it's in the set
+ // of issues provided by an issue registry. Since in the IDE we're enforcing the enabled-state via
+ // inspection profiles, mark the issue as enabled to allow users to turn on a lint check directly
+ // via the inspections UI.
+ issue.setEnabledByDefault(true)
+ }
+ result.add(issue)
+ }
+ return result
+ }
-public class LintExternalAnnotator extends ExternalAnnotator<LintEditorResult, LintEditorResult> {
- static {
- LintClient.setClientName(LintClient.CLIENT_STUDIO);
+ fun getHighlightLevelAndInspection(
+ project: Project,
+ issue: Issue,
+ context: PsiElement
+ ): Pair<AndroidLintInspectionBase, HighlightDisplayLevel>? {
+ val inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue) ?: return null
+ val key = HighlightDisplayKey.find(inspectionShortName) ?: return null
+ val profile: InspectionProfile = InspectionProjectProfileManager.getInstance(context.project).currentProfile
+ if (!profile.isToolEnabled(key, context)) {
+ if (!issue.isEnabledByDefault()) {
+ // Lint will skip issues (and not report them) for issues that have been disabled,
+ // except for those issues that are explicitly enabled via Gradle. Therefore, if
+ // we get this far, lint has found this issue to be explicitly enabled, so we let
+ // that setting override a local enabled/disabled state in the IDE profile.
+ } else {
+ return null
+ }
+ }
+ val inspection = profile.getUnwrappedTool(inspectionShortName, context) as AndroidLintInspectionBase? ?: return null
+ val errorLevel = profile.getErrorLevel(key, context)
+ return Pair(inspection, errorLevel)
+ }
}
- static final String LINK_PREFIX = "#lint/"; // Should match the codeInsight.linkHandler prefix specified in lint-plugin.xml.
- static final boolean INCLUDE_IDEA_SUPPRESS_ACTIONS = false;
-
- @Nullable
- @Override
- public LintEditorResult collectInformation(@NotNull PsiFile file, @NotNull Editor editor, boolean hasErrors) {
- return collectInformation(file);
+ override fun collectInformation(file: PsiFile, editor: Editor, hasErrors: Boolean): LintEditorResult? {
+ return collectInformation(file)
}
- @Override
- public LintEditorResult collectInformation(@NotNull PsiFile file) {
- final Module module = ModuleUtilCore.findModuleForPsiElement(file);
- if (module == null) {
- return null;
- }
-
- return collectInformation(file, module);
+ override fun collectInformation(file: PsiFile): LintEditorResult? {
+ val module = ModuleUtilCore.findModuleForPsiElement(file) ?: return null
+ return collectInformation(file, module)
}
- protected boolean isRelevant(@NotNull PsiFile file, @NotNull Module module) {
- return LintIdeSupport.get().canAnnotate(file, module);
+ private fun isRelevant(file: PsiFile, module: Module): Boolean {
+ return LintIdeSupport.get().canAnnotate(file, module)
}
- @Nullable
- protected LintEditorResult collectInformation(@NotNull PsiFile file, @NotNull Module module) {
- final VirtualFile vFile = file.getVirtualFile();
- if (vFile == null) {
- return null;
- }
-
+ private fun collectInformation(file: PsiFile, module: Module): LintEditorResult? {
+ val vFile = file.virtualFile ?: return null
if (!isRelevant(file, module)) {
- return null;
+ return null
}
-
- final Set<Issue> issues = getIssuesFromInspections(file.getProject(), file);
- return new LintEditorResult(module, vFile, file.getText(), issues);
+ val issues = getIssuesFromInspections(file.project, file)
+ return LintEditorResult(module, vFile, file.text, issues)
}
- @Override
- public LintEditorResult doAnnotate(final LintEditorResult lintResult) {
- long startTime = System.currentTimeMillis();
-
- final LintIdeClient client = LintIdeSupport.get().createEditorClient(lintResult);
+ override fun doAnnotate(lintResult: LintEditorResult): LintEditorResult {
+ val startTime = System.currentTimeMillis()
+ val client = LintIdeSupport.get().createEditorClient(lintResult)
try {
- EnumSet<Scope> scope;
- VirtualFile mainFile = lintResult.getMainFile();
- final FileType fileType = mainFile.getFileType();
- String name = mainFile.getName();
- if (fileType == XmlFileType.INSTANCE) {
- if (name.equals(ANDROID_MANIFEST_XML)) {
- scope = Scope.MANIFEST_SCOPE;
- }
- else if (name.endsWith(DOT_XML)) {
- scope = Scope.RESOURCE_FILE_SCOPE;
- }
- else {
+ var scope: EnumSet<Scope>
+ val mainFile = lintResult.mainFile
+ val fileType = mainFile.fileType
+ val name = mainFile.name
+ if (fileType === XmlFileType.INSTANCE) {
+ if (name == ANDROID_MANIFEST_XML) {
+ scope = Scope.MANIFEST_SCOPE
+ } else if (name.endsWith(DOT_XML)) {
+ scope = Scope.RESOURCE_FILE_SCOPE
+ } else {
// Something else, like svg
- return lintResult;
+ return lintResult
}
- }
- else if (fileType == JavaFileType.INSTANCE || fileType == KotlinFileType.INSTANCE) {
- scope = Scope.JAVA_FILE_SCOPE;
+ } else if (fileType === JavaFileType.INSTANCE || fileType === KotlinFileType.INSTANCE) {
+ scope = Scope.JAVA_FILE_SCOPE
if (name.endsWith(DOT_KTS)) {
- scope = EnumSet.of(Scope.GRADLE_FILE, Scope.JAVA_FILE);
+ scope = EnumSet.of(Scope.GRADLE_FILE, Scope.JAVA_FILE)
}
- }
- else if (name.equals(OLD_PROGUARD_FILE) || name.equals(FN_PROJECT_PROGUARD_FILE)) {
- scope = EnumSet.of(Scope.PROGUARD_FILE);
- }
- else if (fileType == GroovyFileType.GROOVY_FILE_TYPE) {
- scope = Scope.GRADLE_SCOPE;
- }
- else if (fileType == PropertiesFileType.INSTANCE) {
- scope = Scope.PROPERTY_SCOPE;
- }
- else {
+ } else if (name == OLD_PROGUARD_FILE || name == FN_PROJECT_PROGUARD_FILE) {
+ scope = EnumSet.of(Scope.PROGUARD_FILE)
+ } else if (fileType === GroovyFileType.GROOVY_FILE_TYPE) {
+ scope = Scope.GRADLE_SCOPE
+ } else if (fileType === PropertiesFileType.INSTANCE) {
+ scope = Scope.PROPERTY_SCOPE
+ } else {
// #collectionInformation above should have prevented this
- assert false : fileType;
- return lintResult;
+ assert(false) { fileType }
+ return lintResult
}
-
- Project project = lintResult.getModule().getProject();
- if (project.isDisposed()) {
- return lintResult;
+ val project = lintResult.getModule().project
+ if (project.isDisposed) {
+ return lintResult
}
if (DumbService.isDumb(project)) {
- return lintResult; // Lint cannot run in dumb mode.
+ return lintResult // Lint cannot run without indices.
}
-
- List<VirtualFile> files = Collections.singletonList(mainFile);
- LintRequest request = new LintIdeRequest(client, project, files,
- Collections.singletonList(lintResult.getModule()), true /* incremental */);
- request.setScope(scope);
-
- LintDriver lint = client.createDriver(request);
- lint.analyze();
-
- lint.setAnalysisStartTime(startTime);
- LintIdeSupport.get().logSession(lint, lintResult);
- }
- finally {
- Disposer.dispose(client);
+ val files = listOf(mainFile)
+ val request: LintRequest = LintIdeRequest(client, project, files, listOf(lintResult.getModule()), true /* incremental */)
+ request.setScope(scope)
+ val lint = client.createDriver(request)
+ lint.analyze()
+ lint.analysisStartTime = startTime
+ LintIdeSupport.get().logSession(lint, lintResult)
+ } finally {
+ Disposer.dispose(client)
}
- return lintResult;
+ return lintResult
}
- @NotNull
- static Set<Issue> getIssuesFromInspections(@NotNull Project project, @Nullable PsiElement context) {
- final IssueRegistry fullRegistry = LintIdeIssueRegistry.get();
-
- final List<Issue> issueList = fullRegistry.getIssues();
- final Set<Issue> result = Sets.newHashSetWithExpectedSize(issueList.size() + 10);
- for (Issue issue : issueList) {
- final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue);
- if (inspectionShortName == null) {
- continue;
+ override fun apply(file: PsiFile, lintResult: LintEditorResult, holder: AnnotationHolder) {
+ if (lintResult.isDirty) {
+ return
+ }
+ val project = file.project
+ if (DumbService.isDumb(project)) return
+ val fixProviders = LintIdeQuickFixProvider.EP_NAME.extensions
+ val ideSupport = LintIdeSupport.get()
+ for (problemData in lintResult.problems) {
+ val issue = problemData.issue
+ val message = problemData.message
+ val range = problemData.textRange
+ val quickfixData = problemData.quickfixData
+ if (range.startOffset == range.endOffset) {
+ continue
}
- final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName);
- if (key == null) {
- continue;
+
+ var (inspection, displayLevel) = getHighlightLevelAndInspection(project, issue, file) ?: continue
+ val key = HighlightDisplayKey.find(inspection.shortName) ?: continue
+ val startElement = file.findElementAt(range.startOffset)
+ val endElement = file.findElementAt(range.endOffset - 1)
+ if (startElement == null || endElement == null || inspection.isSuppressedFor(startElement)) {
+ continue
}
- final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getCurrentProfile();
- final boolean enabled = context != null ? profile.isToolEnabled(key, context) : profile.isToolEnabled(key);
+ val configuredSeverity = problemData.configuredSeverity
+ if (configuredSeverity != null) {
+ val configuredLevel = AndroidLintInspectionBase.toHighlightDisplayLevel(configuredSeverity)
+ if (configuredLevel != null) {
+ displayLevel = configuredLevel
+ }
+ }
+ val severity = displayLevel.severity
+ val type: ProblemHighlightType =
+ if (issue === DeprecationDetector.ISSUE || issue === GradleDetector.DEPRECATED || issue === GradleDetector.DEPRECATED_CONFIGURATION) {
+ ProblemHighlightType.LIKE_DEPRECATED
+ } else if (issue === WrongIdDetector.UNKNOWN_ID || issue === WrongIdDetector.UNKNOWN_ID_LAYOUT) {
+ ProblemHighlightType.ERROR // like unknown symbol
+ } else if (severity === HighlightSeverity.ERROR) {
+ // In recent versions of IntelliJ, HighlightInfo.convertSeverityToProblemHighlight
+ // maps HighlightSeverity.ERROR to ProblemHighlightType.ERROR which is now documented
+ // to be like ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, which gives the wrong
+ // impression for most errors; see https://issuetracker.google.com/159532832
+ ProblemHighlightType.GENERIC_ERROR
+ } else {
+ HighlightInfo.convertSeverityToProblemHighlight(severity)
+ }
- if (!enabled) {
- continue;
+ // This description link is not displayed. It is parsed by IDEA to
+ // populate the "Show Inspection Description" action.
+ val descriptionLink = "<a href=\"" + LINK_PREFIX + issue.id + "\"></a>"
+ val tooltip = XmlStringUtil.wrapInHtml(descriptionLink + RAW.convertTo(message, HTML))
+ var builder = holder
+ .newAnnotation(severity, message)
+ .highlightType(type)
+ .range(range)
+ .tooltip(tooltip)
+ val fixes = inspection.getAllFixes(startElement, endElement, message, quickfixData, fixProviders, issue)
+ for (fix in fixes) {
+ if (fix.isApplicable(startElement, endElement, AndroidQuickfixContexts.EditorContext.TYPE)) {
+ builder = builder.withFix(MyFixingIntention(fix, startElement, endElement))
+ }
}
- else if (!issue.isEnabledByDefault()) {
- // If an issue is marked as not enabled by default, lint won't run it, even if it's in the set
- // of issues provided by an issue registry. Since in the IDE we're enforcing the enabled-state via
- // inspection profiles, mark the issue as enabled to allow users to turn on a lint check directly
- // via the inspections UI.
- issue.setEnabledByDefault(true);
+ for (intention in inspection.getIntentions(startElement, endElement)) {
+ builder = builder.withFix(intention)
}
- result.add(issue);
- }
- return result;
- }
-
- @Override
- public void apply(@NotNull PsiFile file, LintEditorResult lintResult, @NotNull AnnotationHolder holder) {
- if (lintResult.isDirty()) {
- return;
- }
- final Project project = file.getProject();
- if (DumbService.isDumb(project)) return;
- LintIdeQuickFixProvider[] fixProviders = LintIdeQuickFixProvider.EP_NAME.getExtensions();
- LintIdeSupport ideSupport = LintIdeSupport.get();
-
- for (LintProblemData problemData : lintResult.getProblems()) {
- final Issue issue = problemData.getIssue();
- final String message = problemData.getMessage();
- final TextRange range = problemData.getTextRange();
- final LintFix quickfixData = problemData.getQuickfixData();
-
- if (range.getStartOffset() == range.getEndOffset()) {
- continue;
+ if (ideSupport.canRequestFeedback()) {
+ builder = builder.withFix(ideSupport.requestFeedbackIntentionAction(issue))
}
-
- final Pair<AndroidLintInspectionBase, HighlightDisplayLevel> pair = getHighlightLevelAndInspection(project, issue, file);
- if (pair == null) {
- continue;
+ val id = key.id
+ builder = builder.withFix(SuppressLintIntentionAction(id, startElement))
+ if (INCLUDE_IDEA_SUPPRESS_ACTIONS) {
+ builder = builder.withFix(MyDisableInspectionFix(key))
+ builder = builder.withFix(MyEditInspectionToolsSettingsAction(key, inspection))
}
- final AndroidLintInspectionBase inspection = pair.getFirst();
- HighlightDisplayLevel displayLevel = pair.getSecond();
-
- if (inspection != null) {
- final HighlightDisplayKey key = HighlightDisplayKey.find(inspection.getShortName());
-
- if (key != null) {
- final PsiElement startElement = file.findElementAt(range.getStartOffset());
- final PsiElement endElement = file.findElementAt(range.getEndOffset() - 1);
-
- if (startElement != null && endElement != null && !inspection.isSuppressedFor(startElement)) {
- if (problemData.getConfiguredSeverity() != null) {
- HighlightDisplayLevel configuredLevel =
- AndroidLintInspectionBase.toHighlightDisplayLevel(problemData.getConfiguredSeverity());
- if (configuredLevel != null) {
- displayLevel = configuredLevel;
- }
- }
-
- HighlightSeverity severity = displayLevel.getSeverity();
- ProblemHighlightType type;
- if (issue == DeprecationDetector.ISSUE ||
- issue == GradleDetector.DEPRECATED ||
- issue == GradleDetector.DEPRECATED_CONFIGURATION) {
- type = ProblemHighlightType.LIKE_DEPRECATED;
- } else if (issue == WrongIdDetector.UNKNOWN_ID || issue == WrongIdDetector.UNKNOWN_ID_LAYOUT) {
- type = ProblemHighlightType.ERROR; // like unknown symbol
- } else if (severity == HighlightSeverity.ERROR) {
- // In recent versions of IntelliJ, HighlightInfo.convertSeverityToProblemHighlight
- // maps HighlightSeverity.ERROR to ProblemHighlightType.ERROR which is now documented
- // to be like ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, which gives the wrong
- // impression for most errors; see https://issuetracker.google.com/159532832
- type = ProblemHighlightType.GENERIC_ERROR;
- } else {
- type = HighlightInfo.convertSeverityToProblemHighlight(severity);
- }
-
- // This description link is not displayed. It is parsed by IDEA to
- // populate the "Show Inspection Description" action.
- String descriptionLink = "<a href=\"" + LINK_PREFIX + issue.getId() + "\"></a>";
- String tooltip = XmlStringUtil.wrapInHtml(descriptionLink + RAW.convertTo(message, HTML));
-
- AnnotationBuilder builder = holder
- .newAnnotation(severity, message)
- .highlightType(type)
- .range(range)
- .tooltip(tooltip);
-
- LintIdeQuickFix[] fixes = inspection.getAllFixes(startElement, endElement, message, quickfixData, fixProviders, issue);
- for (LintIdeQuickFix fix : fixes) {
- if (fix.isApplicable(startElement, endElement, AndroidQuickfixContexts.EditorContext.TYPE)) {
- builder = builder.withFix(new MyFixingIntention(fix, startElement, endElement));
- }
- }
-
- for (IntentionAction intention : inspection.getIntentions(startElement, endElement)) {
- builder = builder.withFix(intention);
- }
-
- if (ideSupport.canRequestFeedback()) {
- builder = builder.withFix(ideSupport.requestFeedbackIntentionAction(issue));
- }
-
- String id = key.getID();
- builder = builder.withFix(new SuppressLintIntentionAction(id, startElement));
- if (INCLUDE_IDEA_SUPPRESS_ACTIONS) {
- builder = builder.withFix(new MyDisableInspectionFix(key));
- builder = builder.withFix(new MyEditInspectionToolsSettingsAction(key, inspection));
- }
-
- if (INCLUDE_IDEA_SUPPRESS_ACTIONS) {
- final SuppressQuickFix[] suppressActions = inspection.getBatchSuppressActions(startElement);
- for (SuppressQuickFix action : suppressActions) {
- if (action.isAvailable(project, startElement)) {
- ProblemDescriptor descriptor = InspectionManager.getInstance(project).createProblemDescriptor(
- startElement, endElement, message, type, true, LocalQuickFix.EMPTY_ARRAY);
- builder = builder.newLocalQuickFix(action, descriptor).key(key).registerFix();
- }
- }
- }
-
- builder.create();
+ if (INCLUDE_IDEA_SUPPRESS_ACTIONS) {
+ val suppressActions = inspection.getBatchSuppressActions(startElement)
+ for (action in suppressActions) {
+ if (action.isAvailable(project, startElement)) {
+ val descriptor = InspectionManager.getInstance(project).createProblemDescriptor(
+ startElement, endElement, message, type, true, *LocalQuickFix.EMPTY_ARRAY
+ )
+ builder = builder.newLocalQuickFix(action, descriptor).key(key).registerFix()
}
}
}
+ builder.create()
}
}
- @Nullable
- public static Pair<AndroidLintInspectionBase, HighlightDisplayLevel> getHighlightLevelAndInspection(@NotNull Project project,
- @NotNull Issue issue,
- @NotNull PsiElement context) {
- final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(project, issue);
- if (inspectionShortName == null) {
- return null;
- }
+ private class MyDisableInspectionFix(key: HighlightDisplayKey) : IntentionAction, Iconable {
+ private val myDisableInspectionToolAction = DisableInspectionToolAction(key)
- final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName);
- if (key == null) {
- return null;
+ override fun getText(): String {
+ return "Disable inspection"
}
- final InspectionProfile profile = InspectionProjectProfileManager.getInstance(context.getProject()).getCurrentProfile();
- if (!profile.isToolEnabled(key, context)) {
- if (!issue.isEnabledByDefault()) {
- // Lint will skip issues (and not report them) for issues that have been disabled,
- // except for those issues that are explicitly enabled via Gradle. Therefore, if
- // we get this far, lint has found this issue to be explicitly enabled, so we let
- // that setting override a local enabled/disabled state in the IDE profile.
- }
- else {
- return null;
- }
+ override fun getFamilyName(): String {
+ return text
}
- final AndroidLintInspectionBase inspection = (AndroidLintInspectionBase)profile.getUnwrappedTool(inspectionShortName, context);
- if (inspection == null) return null;
- final HighlightDisplayLevel errorLevel = profile.getErrorLevel(key, context);
- return Pair.create(inspection, errorLevel);
- }
-
- private static class MyDisableInspectionFix implements IntentionAction, Iconable {
- private final DisableInspectionToolAction myDisableInspectionToolAction;
-
- private MyDisableInspectionFix(@NotNull HighlightDisplayKey key) {
- myDisableInspectionToolAction = new DisableInspectionToolAction(key);
- }
-
- @NotNull
- @Override
- public String getText() {
- return "Disable inspection";
+ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean {
+ return true
}
- @NotNull
- @Override
- public String getFamilyName() {
- return getText();
+ @Throws(IncorrectOperationException::class)
+ override fun invoke(project: Project, editor: Editor, file: PsiFile) {
+ myDisableInspectionToolAction.invoke(project, editor, file)
}
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
+ override fun startInWriteAction(): Boolean {
+ return myDisableInspectionToolAction.startInWriteAction()
}
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- myDisableInspectionToolAction.invoke(project, editor, file);
+ override fun getElementToMakeWritable(file: PsiFile): PsiElement? {
+ return myDisableInspectionToolAction.getElementToMakeWritable(file)
}
- @Override
- public boolean startInWriteAction() {
- return myDisableInspectionToolAction.startInWriteAction();
- }
-
- @Nullable
- @Override
- public PsiElement getElementToMakeWritable(@NotNull PsiFile file) {
- return myDisableInspectionToolAction.getElementToMakeWritable(file);
- }
-
- @Override
- public Icon getIcon(@IconFlags int flags) {
- return myDisableInspectionToolAction.getIcon(flags);
+ override fun getIcon(@IconFlags flags: Int): Icon {
+ return myDisableInspectionToolAction.getIcon(flags)
}
}
- public static class MyFixingIntention implements IntentionAction, HighPriorityAction {
- private final LintIdeQuickFix myQuickFix;
- private final PsiElement myStartElement;
- private final PsiElement myEndElement;
-
- public MyFixingIntention(@NotNull LintIdeQuickFix quickFix, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
- myQuickFix = quickFix;
- myStartElement = startElement;
- myEndElement = endElement;
+ class MyFixingIntention(
+ private val myQuickFix: LintIdeQuickFix,
+ private val myStartElement: PsiElement,
+ private val myEndElement: PsiElement
+ ) : IntentionAction, HighPriorityAction {
+ override fun getText(): String {
+ return myQuickFix.name
}
- @NotNull
- @Override
- public String getText() {
- return myQuickFix.getName();
+ override fun getFamilyName(): String {
+ return LintBundle.message("android.lint.quickfixes.family")
}
- @NotNull
- @Override
- public String getFamilyName() {
- return LintBundle.message("android.lint.quickfixes.family");
+ override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean {
+ return true
}
- @Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return true;
+ @Throws(IncorrectOperationException::class)
+ override fun invoke(project: Project, editor: Editor, file: PsiFile) {
+ myQuickFix.apply(myStartElement, myEndElement, AndroidQuickfixContexts.EditorContext.getInstance(editor))
}
- @Override
- public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
- myQuickFix.apply(myStartElement, myEndElement, AndroidQuickfixContexts.EditorContext.getInstance(editor));
+ override fun startInWriteAction(): Boolean {
+ return myQuickFix.startInWriteAction()
}
- @Override
- public boolean startInWriteAction() {
- return myQuickFix.startInWriteAction();
- }
-
- @Override
- public String toString() {
- return getText();
+ override fun toString(): String {
+ return text
}
}
- private static class MyEditInspectionToolsSettingsAction extends CustomEditInspectionToolsSettingsAction {
- private MyEditInspectionToolsSettingsAction(@NotNull HighlightDisplayKey key, @NotNull final AndroidLintInspectionBase inspection) {
- super(key, () -> "Edit '" + inspection.getDisplayName() + "' inspection settings");
- }
- }
-}
+ private class MyEditInspectionToolsSettingsAction(key: HighlightDisplayKey, inspection: AndroidLintInspectionBase) :
+ CustomEditInspectionToolsSettingsAction(key, Computable { "Edit '" + inspection.displayName + "' inspection settings" })
+} \ No newline at end of file
diff --git a/lint/src/com/android/tools/idea/lint/common/LintGlobalInspectionContext.java b/lint/src/com/android/tools/idea/lint/common/LintGlobalInspectionContext.java
index acfccc8279d..2febd37498e 100644
--- a/lint/src/com/android/tools/idea/lint/common/LintGlobalInspectionContext.java
+++ b/lint/src/com/android/tools/idea/lint/common/LintGlobalInspectionContext.java
@@ -94,7 +94,7 @@ public class LintGlobalInspectionContext implements GlobalInspectionContextExten
}
}
- Set<Issue> issues = LintExternalAnnotator.getIssuesFromInspections(project, null);
+ Set<Issue> issues = LintExternalAnnotator.Companion.getIssuesFromInspections(project, null);
if (issues.isEmpty()) {
return;
}