Skip to content

Commit

Permalink
telemetry(amazonq): Add metrics utility to instrument generated patch…
Browse files Browse the repository at this point in the history
…es applied to existing code.
  • Loading branch information
C Tidd committed Nov 15, 2024
1 parent e225cdc commit 81dd90e
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util

import com.intellij.diff.comparison.ComparisonManager
import com.intellij.diff.comparison.ComparisonPolicy
import com.intellij.diff.fragments.LineFragment
import com.intellij.openapi.progress.EmptyProgressIndicator

data class DiffMetrics(
val insertedLines: Int,
val insertedCharacters: Int
)

fun lineEnding(content: String, curr: Int, end: Int): Int {
require (curr <= end) { "curr must be within end of range" }
require (end <= content.length) { "end must be within content" }

return if (curr == end) {
-1
} else if (content[curr] == '\r') {
if ((curr + 1 < end) && (content[curr + 1] == '\n')) {
2
} else {
1
}
} else if (content[curr] == '\n') {
1
} else {
-1
}
}

fun getDiffMetrics(before: String, after: String): DiffMetrics {
val comparisonManager = ComparisonManager.getInstance()
val fragments = comparisonManager.compareLines(
before,
after,
ComparisonPolicy.DEFAULT,
EmptyProgressIndicator()
)

var accLineCount = 0
var accCharCount = 0

fragments.forEach { fragment: LineFragment ->
var curr = fragment.startOffset2
val end = fragment.endOffset2

while (curr < end) {
accLineCount += 1

// Consume leading whitespace:
while (curr < end && lineEnding(after, curr, end) == -1 && after[curr].isWhitespace()) curr++

// Consume through EOL:
val lineContentStart = curr
while (curr < end && lineEnding(after, curr, end) == -1) curr++
var lineContentEnd = curr
curr += maxOf(lineEnding(after, curr, end), 0)

// Walk back trailing whitespace and record character count before continuing to next line:
while (lineContentEnd > lineContentStart && after[lineContentEnd - 1].isWhitespace()) lineContentEnd--
accCharCount += lineContentEnd - lineContentStart
}
}

return DiffMetrics(
insertedLines = accLineCount,
insertedCharacters = accCharCount,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonqFeatureDev.util

import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.testFramework.TestApplicationManager
import kotlin.test.assertNotEquals

class DiffMetricsTest : LightPlatformTestCase() {
override fun setUp() {
super.setUp()
TestApplicationManager.getInstance()
}

fun `test empty input`() {
val metrics = getDiffMetrics("", "")
assertEquals(0, metrics.insertedLines)
assertEquals(0, metrics.insertedCharacters)
}

fun `test insertions are counted`() {
val before = """
line1
line2
""".trimIndent()

val after = """
line1
inserted
line2
""".trimIndent()

val metrics = getDiffMetrics(before, after)
assertEquals(1, metrics.insertedLines)
assertEquals(8, metrics.insertedCharacters)
}

fun `test modifications are counted`() {
val before = """
line1
line2
line3
""".trimIndent()

val after = """
line1
modified
line3
""".trimIndent()

val metrics = getDiffMetrics(before, after)
assertEquals(1, metrics.insertedLines)
assertEquals(8, metrics.insertedCharacters)
}

fun `test deletions are counted`() {
val before = """
line1
line2
line3
""".trimIndent()

val after = """
line1
line3
""".trimIndent()

val metrics = getDiffMetrics(before, after)
assertEquals(0, metrics.insertedLines)
assertEquals(0, metrics.insertedCharacters)
}

fun `test multiline and multiple hunks are counted`() {
val before = """
line1
line2
line3
""".trimIndent()

val after = """
inserted1
line1
inserted2
inserted3
line3
inserted4
""".trimIndent()

val metrics = getDiffMetrics(before, after)
assertEquals(4, metrics.insertedLines)
assertEquals(36, metrics.insertedCharacters)
}

fun `test empty lines are counted`() {
val before = "line1"
val after = "line1\n\nline2"
val metrics = getDiffMetrics(before, after)
assertEquals(2, metrics.insertedLines)
assertEquals(5, metrics.insertedCharacters)
}

fun `test trailing newline is not counted`() {
val before = "line1"
val after = "line1\nline2\n"
val metrics = getDiffMetrics(before, after)
assertEquals(1, metrics.insertedLines)
assertEquals(5, metrics.insertedCharacters)
}

fun `test newline sequences are counted`() {
val before = "line1"
val after = "line1\nline2\rline3\r\nline4"
val metrics = getDiffMetrics(before, after)
assertEquals(3, metrics.insertedLines)
assertEquals(15, metrics.insertedCharacters)
}

fun `test leading and trailing whitespace are not counted as characters`() {
val before = "line1\nline2"
val after = "line1\n line2"

val metrics = getDiffMetrics(before, after)
assertEquals(1, metrics.insertedLines)
assertEquals(5, metrics.insertedCharacters)
assertNotEquals(9, metrics.insertedCharacters)
}
}

0 comments on commit 81dd90e

Please sign in to comment.