From 6638b2ffa7b3df7e0cb01e38ff3d587ce9cdeb60 Mon Sep 17 00:00:00 2001 From: "Vitaly V. Pinchuk" Date: Thu, 7 Jul 2022 23:29:03 +0300 Subject: [PATCH] Add ending line and column to Location.kt (#5032) * Add ending line and column to Location.kt * Revert changes to detekt-api.api * Add tests for Location.kt * Add new line to comply with format Co-authored-by: schalkms <30376729+schalkms@users.noreply.github.com> --- detekt-api/api/detekt-api.api | 2 + .../gitlab/arturbosch/detekt/api/Location.kt | 41 +++++++++++++++---- .../arturbosch/detekt/api/LocationSpec.kt | 35 ++++++++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) create mode 100644 detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/LocationSpec.kt diff --git a/detekt-api/api/detekt-api.api b/detekt-api/api/detekt-api.api index 8405d730980..665e3f51d90 100644 --- a/detekt-api/api/detekt-api.api +++ b/detekt-api/api/detekt-api.api @@ -353,6 +353,7 @@ public final class io/gitlab/arturbosch/detekt/api/LazyRegex : kotlin/properties public final class io/gitlab/arturbosch/detekt/api/Location : io/gitlab/arturbosch/detekt/api/Compactable { public static final field Companion Lio/gitlab/arturbosch/detekt/api/Location$Companion; + public fun (Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Lio/github/detekt/psi/FilePath;)V public fun (Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Lio/github/detekt/psi/FilePath;)V public fun (Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Ljava/lang/String;)V public fun (Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Ljava/lang/String;Lio/github/detekt/psi/FilePath;)V @@ -367,6 +368,7 @@ public final class io/gitlab/arturbosch/detekt/api/Location : io/gitlab/arturbos public final fun copy (Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Ljava/lang/String;Lio/github/detekt/psi/FilePath;)Lio/gitlab/arturbosch/detekt/api/Location; public static synthetic fun copy$default (Lio/gitlab/arturbosch/detekt/api/Location;Lio/gitlab/arturbosch/detekt/api/SourceLocation;Lio/gitlab/arturbosch/detekt/api/TextLocation;Ljava/lang/String;Lio/github/detekt/psi/FilePath;ILjava/lang/Object;)Lio/gitlab/arturbosch/detekt/api/Location; public fun equals (Ljava/lang/Object;)Z + public final fun getEndSource ()Lio/gitlab/arturbosch/detekt/api/SourceLocation; public final fun getFile ()Ljava/lang/String; public final fun getFilePath ()Lio/github/detekt/psi/FilePath; public final fun getSource ()Lio/gitlab/arturbosch/detekt/api/SourceLocation; diff --git a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Location.kt b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Location.kt index 5f7fccd6186..a95648addb8 100644 --- a/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Location.kt +++ b/detekt-api/src/main/kotlin/io/gitlab/arturbosch/detekt/api/Location.kt @@ -26,6 +26,8 @@ data class Location @Deprecated("Consider relative path by passing a [FilePath]" val file: String, val filePath: FilePath = FilePath.fromAbsolute(Paths.get(file)) ) : Compactable { + var endSource: SourceLocation = source + private set @Suppress("DEPRECATION") constructor( @@ -34,6 +36,16 @@ data class Location @Deprecated("Consider relative path by passing a [FilePath]" filePath: FilePath ) : this(source, text, filePath.absolutePath.toString(), filePath) + @Suppress("DEPRECATION") + constructor( + source: SourceLocation, + endSource: SourceLocation, + text: TextLocation, + filePath: FilePath, + ) : this(source, text, filePath.absolutePath.toString(), filePath) { + this.endSource = endSource + } + @Suppress("DEPRECATION") @Deprecated( """ @@ -62,20 +74,33 @@ data class Location @Deprecated("Consider relative path by passing a [FilePath]" fun from(element: PsiElement, offset: Int = 0): Location { val start = startLineAndColumn(element, offset) val sourceLocation = SourceLocation(start.line, start.column) + val end = endLineAndColumn(element, offset) + val endSourceLocation = SourceLocation(end.line, end.column) val textLocation = TextLocation(element.startOffset + offset, element.endOffset + offset) - return Location(sourceLocation, textLocation, element.containingFile.toFilePath()) + return Location(sourceLocation, endSourceLocation, textLocation, element.containingFile.toFilePath()) } /** - * Determines the line and column of a [PsiElement] in the source file. + * Determines the start line and column of a [PsiElement] in the source file. */ - fun startLineAndColumn(element: PsiElement, offset: Int = 0): PsiDiagnosticUtils.LineAndColumn { + fun startLineAndColumn(element: PsiElement, offset: Int = 0): PsiDiagnosticUtils.LineAndColumn = + lineAndColumn( + element, + TextRange(element.textRange.startOffset + offset, element.textRange.endOffset + offset) + ) + + /** + * Determines the end line and column of a [PsiElement] in the source file. + */ + private fun endLineAndColumn(element: PsiElement, offset: Int = 0): PsiDiagnosticUtils.LineAndColumn = + lineAndColumn( + element, + TextRange(element.textRange.endOffset + offset, element.textRange.endOffset + offset) + ) + + private fun lineAndColumn(element: PsiElement, range: TextRange): PsiDiagnosticUtils.LineAndColumn { return try { - val range = element.textRange - DiagnosticUtils.getLineAndColumnInPsiFile( - element.containingFile, - TextRange(range.startOffset + offset, range.endOffset + offset) - ) + 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) diff --git a/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/LocationSpec.kt b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/LocationSpec.kt new file mode 100644 index 00000000000..b55dda3392b --- /dev/null +++ b/detekt-api/src/test/kotlin/io/gitlab/arturbosch/detekt/api/LocationSpec.kt @@ -0,0 +1,35 @@ +package io.gitlab.arturbosch.detekt.api + +import io.github.detekt.test.utils.compileContentForTest +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.junit.jupiter.api.Test + +class LocationSpec { + + @Test + fun `start and end positions of block`() { + val code = """ + fun data(): Int { + return 0 + } + """.trimIndent() + val psiElement = compileContentForTest(code).findChildByClass(KtNamedFunction::class.java)!! + val location = Location.from(psiElement) + + assertThat("${location.source} - ${location.endSource}").isEqualTo("1:1 - 3:2") + } + + @Test + fun `start and end positions of fun keyword`() { + val code = """ + fun data(): Int { + return 0 + } + """.trimIndent() + val psiElement = compileContentForTest(code).findChildByClass(KtNamedFunction::class.java)!! + val location = Location.from(psiElement.funKeyword!!) + + assertThat("${location.source} - ${location.endSource}").isEqualTo("1:1 - 1:4") + } +}