FIR IDE: Move base part of highlighting to frontend-independent-module
This commit is contained in:
+10
-54
@@ -10,14 +10,11 @@ import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.xml.util.XmlStringUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
|
||||
|
||||
class AnnotationPresentationInfo(
|
||||
@@ -52,55 +49,14 @@ class AnnotationPresentationInfo(
|
||||
}
|
||||
}
|
||||
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
||||
val defaultMessage = nonDefaultMessage ?: getDefaultMessage(diagnostic)
|
||||
|
||||
val annotation = when (diagnostic.severity) {
|
||||
Severity.ERROR -> holder.createErrorAnnotation(range, defaultMessage)
|
||||
Severity.WARNING -> {
|
||||
if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
holder.createWeakWarningAnnotation(range, defaultMessage)
|
||||
} else {
|
||||
holder.createWarningAnnotation(range, defaultMessage)
|
||||
}
|
||||
}
|
||||
Severity.INFO -> holder.createInfoAnnotation(range, defaultMessage)
|
||||
}
|
||||
|
||||
annotation.tooltip = getMessage(diagnostic)
|
||||
|
||||
if (highlightType != null) {
|
||||
annotation.highlightType = highlightType
|
||||
}
|
||||
|
||||
if (textAttributes != null) {
|
||||
annotation.textAttributes = textAttributes
|
||||
}
|
||||
|
||||
return annotation
|
||||
}
|
||||
|
||||
private fun getMessage(diagnostic: Diagnostic): String {
|
||||
var message = IdeErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val factoryName = diagnostic.factory.name
|
||||
message = if (message.startsWith("<html>")) {
|
||||
"<html>[$factoryName] ${message.substring("<html>".length)}"
|
||||
} else {
|
||||
"[$factoryName] $message"
|
||||
}
|
||||
}
|
||||
if (!message.startsWith("<html>")) {
|
||||
message = "<html><body>${XmlStringUtil.escapeString(message)}</body></html>"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private fun getDefaultMessage(diagnostic: Diagnostic): String {
|
||||
val message = DefaultErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return "[${diagnostic.factory.name}] $message"
|
||||
}
|
||||
return message
|
||||
}
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation =
|
||||
Diagnostic2Annotation.createAnnotation(
|
||||
diagnostic,
|
||||
range,
|
||||
holder,
|
||||
nonDefaultMessage,
|
||||
textAttributes,
|
||||
highlightType,
|
||||
IdeErrorMessages::render
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightRangeExtension
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||
@@ -17,7 +15,6 @@ import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.MultiRangeReference
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
|
||||
@@ -27,36 +24,23 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||
import org.jetbrains.kotlin.idea.fir.FirResolution
|
||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirWithDiagnostics
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.module
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.lang.reflect.*
|
||||
import java.util.*
|
||||
|
||||
open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
open class KotlinPsiChecker : AbstractKotlinPsiChecker() {
|
||||
override fun shouldHighlight(file: KtFile): Boolean = KotlinHighlightingUtil.shouldHighlight(file)
|
||||
|
||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||
val file = element.containingFile as? KtFile ?: return
|
||||
|
||||
if (!KotlinHighlightingUtil.shouldHighlight(file)) return
|
||||
|
||||
//todo move all fir stuff to fir plugin
|
||||
if (FirResolution.enabled) {
|
||||
annotateElementUsingFrontendIR(element, file, holder)
|
||||
} else {
|
||||
annotateElement(element, file, holder)
|
||||
}
|
||||
}
|
||||
|
||||
private fun annotateElement(
|
||||
override fun annotateElement(
|
||||
element: PsiElement,
|
||||
containingFile: KtFile,
|
||||
holder: AnnotationHolder
|
||||
@@ -73,29 +57,6 @@ open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
annotateElement(element, holder, bindingContext.diagnostics)
|
||||
}
|
||||
|
||||
private fun annotateElementUsingFrontendIR(
|
||||
element: PsiElement,
|
||||
containingFile: KtFile,
|
||||
holder: AnnotationHolder
|
||||
) {
|
||||
if (element !is KtElement) return
|
||||
val state = containingFile.firResolveState()
|
||||
containingFile.getOrBuildFirWithDiagnostics(state)
|
||||
|
||||
val diagnostics = state.getDiagnostics(element)
|
||||
if (diagnostics.isEmpty()) return
|
||||
|
||||
if (KotlinHighlightingUtil.shouldHighlightErrors(element)) {
|
||||
ElementAnnotator(element, holder) { param ->
|
||||
shouldSuppressUnusedParameter(param)
|
||||
}.registerDiagnosticsAnnotations(diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isForceHighlightParents(file: PsiFile): Boolean {
|
||||
return file is KtFile
|
||||
}
|
||||
|
||||
protected open fun shouldSuppressUnusedParameter(parameter: KtParameter): Boolean = false
|
||||
|
||||
fun annotateElement(element: PsiElement, holder: AnnotationHolder, diagnostics: Diagnostics) {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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 org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
object NameHighlighter {
|
||||
var namesHighlightingEnabled = true
|
||||
@TestOnly set
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirWithDiagnostics
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class KotlinFirPsiChecker : AbstractKotlinPsiChecker() {
|
||||
override fun shouldHighlight(file: KtFile): Boolean {
|
||||
return true // todo
|
||||
}
|
||||
|
||||
override fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder) {
|
||||
if (element !is KtElement) return
|
||||
val state = containingFile.firResolveState()
|
||||
containingFile.getOrBuildFirWithDiagnostics(state)
|
||||
|
||||
val diagnostics = state.getDiagnostics(element)
|
||||
if (diagnostics.isEmpty()) return
|
||||
|
||||
if (shouldHighlightErrors(element)) {
|
||||
highlightDiagnostics(diagnostics, holder)
|
||||
}
|
||||
}
|
||||
|
||||
private fun highlightDiagnostics(diagnostics: Collection<Diagnostic>, holder: AnnotationHolder) {
|
||||
diagnostics.groupBy { it.factory }.forEach { group -> registerDiagnosticAnnotations(group.value, holder) }
|
||||
}
|
||||
|
||||
private fun registerDiagnosticAnnotations(diagnostics: List<Diagnostic>, holder: AnnotationHolder) {
|
||||
assert(diagnostics.isNotEmpty())
|
||||
val diagnostic = diagnostics.first()
|
||||
|
||||
val ranges = diagnostic.textRanges
|
||||
|
||||
ranges.forEach { range ->
|
||||
diagnostics.forEach { diagnostic ->
|
||||
Diagnostic2Annotation.createAnnotation(
|
||||
diagnostic,
|
||||
range,
|
||||
holder,
|
||||
nonDefaultMessage = null,
|
||||
textAttributes = null,
|
||||
highlightType = null,
|
||||
renderMessage = IdeErrorMessages::render
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun shouldHighlightErrors(element: KtElement): Boolean {
|
||||
return true // todo
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ dependencies {
|
||||
*/
|
||||
|
||||
compileOnly(project(":compiler:frontend")) // we need caches form here to work with ModuleInfo :(
|
||||
compileOnly(project(":idea:idea-jps-common"))
|
||||
|
||||
compileOnly(project(":compiler:psi"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightRangeExtension
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractKotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||
val file = element.containingFile as? KtFile ?: return
|
||||
|
||||
if (!shouldHighlight(file)) return
|
||||
annotateElement(element, file, holder)
|
||||
}
|
||||
|
||||
override fun isForceHighlightParents(file: PsiFile): Boolean {
|
||||
return file is KtFile
|
||||
}
|
||||
|
||||
protected abstract fun shouldHighlight(file: KtFile): Boolean
|
||||
protected abstract fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder)
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.xml.util.XmlStringUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
|
||||
object Diagnostic2Annotation {
|
||||
fun getHtmlMessage(diagnostic: Diagnostic, renderMessage: (Diagnostic) -> String): String {
|
||||
var message = renderMessage(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val factoryName = diagnostic.factory.name
|
||||
message = if (message.startsWith("<html>")) {
|
||||
"<html>[$factoryName] ${message.substring("<html>".length)}"
|
||||
} else {
|
||||
"[$factoryName] $message"
|
||||
}
|
||||
}
|
||||
if (!message.startsWith("<html>")) {
|
||||
message = "<html><body>${XmlStringUtil.escapeString(message)}</body></html>"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
fun getDefaultMessage(diagnostic: Diagnostic): String {
|
||||
val message = DefaultErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return "[${diagnostic.factory.name}] $message"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
fun createAnnotation(
|
||||
diagnostic: Diagnostic,
|
||||
range: TextRange,
|
||||
holder: AnnotationHolder,
|
||||
nonDefaultMessage: String?,
|
||||
textAttributes: TextAttributesKey?,
|
||||
highlightType: ProblemHighlightType?,
|
||||
renderMessage: (Diagnostic) -> String
|
||||
): Annotation {
|
||||
val defaultMessage = nonDefaultMessage ?: getDefaultMessage(diagnostic)
|
||||
|
||||
val annotation = when (diagnostic.severity) {
|
||||
Severity.ERROR -> holder.createErrorAnnotation(range, defaultMessage)
|
||||
Severity.WARNING -> {
|
||||
if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
holder.createWeakWarningAnnotation(range, defaultMessage)
|
||||
} else {
|
||||
holder.createWarningAnnotation(range, defaultMessage)
|
||||
}
|
||||
}
|
||||
Severity.INFO -> holder.createInfoAnnotation(range, defaultMessage)
|
||||
}
|
||||
|
||||
annotation.tooltip = getHtmlMessage(diagnostic, renderMessage)
|
||||
|
||||
if (highlightType != null) {
|
||||
annotation.highlightType = highlightType
|
||||
}
|
||||
|
||||
if (textAttributes != null) {
|
||||
annotation.textAttributes = textAttributes
|
||||
}
|
||||
|
||||
return annotation
|
||||
}
|
||||
}
|
||||
+2
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
+8
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,8 @@ import com.intellij.codeInsight.daemon.impl.UpdateHighlightersUtil
|
||||
import com.intellij.lang.annotation.AnnotationSession
|
||||
import com.intellij.openapi.editor.Document
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.progress.ProgressIndicator
|
||||
import com.intellij.openapi.project.DumbAware
|
||||
import com.intellij.openapi.project.Project
|
||||
@@ -19,6 +21,7 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiRecursiveElementVisitor
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
|
||||
class KotlinBeforeResolveHighlightingPass(
|
||||
private val file: KtFile,
|
||||
@@ -67,4 +70,8 @@ class KotlinBeforeResolveHighlightingPass(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// companion object {
|
||||
// val EP_NAME = ExtensionPointName.create<HighlightingVisitor>("org.jetbrains.kotlin.beforeResolveHighlightingVisitor")
|
||||
// }
|
||||
}
|
||||
+2
-13
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter;
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.highlighter
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
object NameHighlighter {
|
||||
var namesHighlightingEnabled = true
|
||||
@TestOnly set
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user