Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forbid usage of DiagnosticUtils.getLineAndColumnInPsiFile #5109

Merged
merged 2 commits into from Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions config/detekt/detekt.yml
Expand Up @@ -195,6 +195,7 @@ style:
- 'java.net.URL.openStream'
- 'java.lang.Class.getResourceAsStream'
- 'java.lang.ClassLoader.getResourceAsStream'
- 'org.jetbrains.kotlin.diagnostics.DiagnosticUtils.getLineAndColumnInPsiFile'
ForbiddenVoid:
active: true
LibraryCodeMustSpecifyReturnType:
Expand Down
@@ -1,10 +1,10 @@
package io.gitlab.arturbosch.detekt.api

import io.github.detekt.psi.FilePath
import io.github.detekt.psi.getLineAndColumnInPsiFile
import io.github.detekt.psi.toFilePath
import org.jetbrains.kotlin.com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.endOffset
Expand Down Expand Up @@ -102,12 +102,8 @@ constructor(
)

private fun lineAndColumn(element: PsiElement, range: TextRange): PsiDiagnosticUtils.LineAndColumn {
return try {
DiagnosticUtils.getLineAndColumnInPsiFile(element.containingFile, range)
} catch (@Suppress("SwallowedException", "TooGenericExceptionCaught") e: IndexOutOfBoundsException) {
// #3317 If any rule mutates the PsiElement, searching the original PsiElement may throw exception.
PsiDiagnosticUtils.LineAndColumn(-1, -1, null)
}
return getLineAndColumnInPsiFile(element.containingFile, range)
?: PsiDiagnosticUtils.LineAndColumn(-1, -1, null)
}
}
}
Expand Down
Expand Up @@ -2,6 +2,7 @@

package io.github.detekt.metrics

import io.github.detekt.psi.getLineAndColumnInPsiFile
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
import org.jetbrains.kotlin.com.intellij.psi.PsiComment
import org.jetbrains.kotlin.com.intellij.psi.PsiElement
Expand All @@ -10,7 +11,6 @@ import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.LeafElement
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiCommentImpl
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiCoreCommentImpl
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.PsiWhiteSpaceImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.kdoc.psi.api.KDoc
import org.jetbrains.kotlin.kdoc.psi.api.KDocElement
import org.jetbrains.kotlin.kdoc.psi.impl.KDocElementImpl
Expand Down Expand Up @@ -44,16 +44,7 @@ fun KtElement.linesOfCode(inFile: KtFile = this.containingKtFile): Int =
.distinct()
.count()

fun ASTNode.line(inFile: KtFile): Int = try {
DiagnosticUtils.getLineAndColumnInPsiFile(inFile, this.textRange).line
} catch (@Suppress("SwallowedException", "TooGenericExceptionCaught") e: IndexOutOfBoundsException) {
// When auto-correctable rules performs actual mutation, KtFile.text is updated but
// KtFile.viewProvider.document is not updated. This will cause crash in subsequent rules
// if they are using any function relying on the KtFile.viewProvider.document.
// The exception is silenced to return -1 while we should seek long-term solution for execution
// order of rules (#3445)
-1
}
fun ASTNode.line(inFile: KtFile): Int = getLineAndColumnInPsiFile(inFile, this.textRange)?.line ?: -1

private val comments: Set<Class<out PsiElement>> = setOf(
PsiWhiteSpace::class.java,
Expand Down
1 change: 1 addition & 0 deletions detekt-psi-utils/api/detekt-psi-utils.api
Expand Up @@ -33,6 +33,7 @@ public final class io/github/detekt/psi/KtFilesKt {
public static final fun basePath (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;)Ljava/nio/file/Path;
public static final fun fileNameWithoutSuffix (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;)Ljava/lang/String;
public static final fun getFileName (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;)Ljava/lang/String;
public static final fun getLineAndColumnInPsiFile (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;Lorg/jetbrains/kotlin/com/intellij/openapi/util/TextRange;)Lorg/jetbrains/kotlin/diagnostics/PsiDiagnosticUtils$LineAndColumn;
public static final fun relativePath (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;)Ljava/nio/file/Path;
public static final fun toFilePath (Lorg/jetbrains/kotlin/com/intellij/psi/PsiFile;)Lio/github/detekt/psi/FilePath;
public static final fun toUnifiedString (Ljava/nio/file/Path;)Ljava/lang/String;
Expand Down
11 changes: 11 additions & 0 deletions detekt-psi-utils/src/main/kotlin/io/github/detekt/psi/KtFiles.kt
@@ -1,6 +1,9 @@
package io.github.detekt.psi

import org.jetbrains.kotlin.com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.com.intellij.psi.PsiFile
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
Expand Down Expand Up @@ -68,6 +71,14 @@ fun PsiFile.toFilePath(): FilePath {
}
}

// #3317 If any rule mutates the PsiElement, searching the original PsiElement may throw an exception.
fun getLineAndColumnInPsiFile(file: PsiFile, range: TextRange): PsiDiagnosticUtils.LineAndColumn? {
return runCatching {
@Suppress("ForbiddenMethodCall")
DiagnosticUtils.getLineAndColumnInPsiFile(file, range)
}.getOrNull()
}

/**
* Returns a system-independent string with UNIX system file separator.
*/
Expand Down
@@ -1,5 +1,6 @@
package io.gitlab.arturbosch.detekt.rules.style

import io.github.detekt.psi.getLineAndColumnInPsiFile
import io.github.detekt.psi.toFilePath
import io.gitlab.arturbosch.detekt.api.CodeSmell
import io.gitlab.arturbosch.detekt.api.Config
Expand All @@ -13,7 +14,6 @@ import io.gitlab.arturbosch.detekt.api.SourceLocation
import io.gitlab.arturbosch.detekt.api.TextLocation
import io.gitlab.arturbosch.detekt.api.internal.ActiveByDefault
import org.jetbrains.kotlin.com.intellij.openapi.util.TextRange
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.psiUtil.endOffset

Expand All @@ -33,11 +33,11 @@ class NewLineAtEndOfFile(config: Config = Config.empty) : Rule(config) {
override fun visitKtFile(file: KtFile) {
val text = file.text
if (text.isNotEmpty() && !text.endsWith('\n')) {
val coords = DiagnosticUtils.getLineAndColumnInPsiFile(
val coords = getLineAndColumnInPsiFile(
file,
TextRange(file.endOffset, file.endOffset)
)
val sourceLocation = SourceLocation(coords.line, coords.column)
val sourceLocation = SourceLocation(coords?.line ?: 0, coords?.column ?: 0)
val textLocation = TextLocation(file.endOffset, file.endOffset)
val location = Location(sourceLocation, textLocation, file.containingFile.toFilePath())
report(
Expand Down