Skip to content
New issue

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

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

Already on GitHub? # to your account

feat(intention): add initial implementation of "wrap to" with try, try-catch and repeat #165

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions server/src/e2e/suite/TestParser.ts
Original file line number Diff line number Diff line change
@@ -2,10 +2,11 @@ import * as fs from "node:fs"

export interface TestCase {
name: string
properties: Record<string, string>
properties: Map<string, string>
input: string
expected: string
result?: string
propertiesOrder: string[]
}

enum ParserState {
@@ -25,7 +26,10 @@ export class TestParser {
const lines = content.trim().replace(/\r\n/g, "\n").split("\n")

let state = ParserState.WaitingForTestStart
let currentTest: Partial<TestCase> = {}
let currentTest: Partial<TestCase & {propertiesOrder: string[]}> = {
properties: new Map(),
propertiesOrder: [],
}
let currentContent = ""

for (const l of lines) {
@@ -35,14 +39,29 @@ export class TestParser {
case ParserState.WaitingForTestStart:
if (line === SEPARATOR) {
state = ParserState.ReadingProperties
currentTest = {properties: {}}
currentTest = {
properties: new Map(),
propertiesOrder: [],
}
}
break

case ParserState.ReadingProperties:
if (line.startsWith("@") && currentTest.properties) {
const [key, value] = line.substring(1).split(" ")
currentTest.properties[key] = value
if (
line.startsWith("@") &&
currentTest.properties &&
currentTest.propertiesOrder
) {
const propertyLine = line.substring(1) // remove @
const spaceIndex = propertyLine.indexOf(" ")
if (spaceIndex !== -1) {
const key = propertyLine.substring(0, spaceIndex)
currentTest.properties.set(
key,
propertyLine.substring(spaceIndex + 1).trim(),
)
currentTest.propertiesOrder.push(key)
}
} else {
currentTest.name = line
state = ParserState.ReadingName
@@ -71,7 +90,10 @@ export class TestParser {
currentTest.expected = currentContent.trim()
tests.push(currentTest as TestCase)
state = ParserState.ReadingProperties
currentTest = {properties: {}}
currentTest = {
properties: new Map(),
propertiesOrder: [],
}
currentContent = ""
} else {
currentContent += line + "\n"
@@ -80,7 +102,6 @@ export class TestParser {
}
}

// Добавляем последний тест
if (currentTest.name && currentContent) {
currentTest.expected = currentContent.trim()
tests.push(currentTest as TestCase)
@@ -103,8 +124,8 @@ export class TestParser {

newContent.push(SEPARATOR)

for (const [key, value] of Object.entries(test.properties)) {
newContent.push(`@${key} ${value}`)
for (const key of test.propertiesOrder) {
newContent.push(`@${key} ${test.properties.get(key)}`)
}

newContent.push(test.name)
47 changes: 37 additions & 10 deletions server/src/e2e/suite/intentions.test.ts
Original file line number Diff line number Diff line change
@@ -6,16 +6,31 @@ import {TestCase} from "./TestParser"
suite("Intentions Test Suite", () => {
const testSuite = new (class extends BaseTestSuite {
async getCodeActions(input: string): Promise<vscode.CodeAction[]> {
const textWithoutCaret = input.replace("<caret>", "")
await this.replaceDocumentText(textWithoutCaret)
const selectionStart = input.indexOf("<selection>")
const selectionEnd = input.indexOf("</selection>")

const caretIndex = input.indexOf("<caret>")
if (caretIndex === -1) {
throw new Error("No <caret> marker found in input")
}
let range: vscode.Range
let textWithoutMarkers: string

if (selectionStart !== -1 && selectionEnd !== -1) {
textWithoutMarkers = input.replace("<selection>", "").replace("</selection>", "")
await this.replaceDocumentText(textWithoutMarkers)

const startPos = this.document.positionAt(selectionStart)
const endPos = this.document.positionAt(selectionEnd - "<selection>".length)
range = new vscode.Range(startPos, endPos)
} else {
textWithoutMarkers = input.replace("<caret>", "")
await this.replaceDocumentText(textWithoutMarkers)

const caretIndex = input.indexOf("<caret>")
if (caretIndex === -1) {
throw new Error("No <caret> or <selection> markers found in input")
}

const position = this.document.positionAt(caretIndex)
const range = new vscode.Range(position, position)
const position = this.document.positionAt(caretIndex)
range = new vscode.Range(position, position)
}

return vscode.commands.executeCommand<vscode.CodeAction[]>(
"vscode.executeCodeActionProvider",
@@ -41,9 +56,21 @@ suite("Intentions Test Suite", () => {
return
}

assert.ok(actions.length > 0, "No code actions available")
let selectedAction = actions[0]

const intentionName = testCase.properties.get("intention")
if (intentionName) {
const found = actions.find(action => action.title === intentionName)
assert.ok(
found,
`Intention "${intentionName}" not found. Available intentions: ${actions
.map(a => a.title)
.join(", ")}`,
)
selectedAction = found
}

const command = actions[0].command
const command = selectedAction.command
if (!command || !command.arguments) throw new Error("No intention command")

await vscode.commands.executeCommand(
242 changes: 242 additions & 0 deletions server/src/e2e/suite/testcases/intentions/WrapSelected..test
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
========================================================================
@intention Wrap selected to "try"
Wrap multiple statements in try
========================================================================
contract Test {
fun test() {
<selection>let a = 1;
let b = 2;
let c = 3;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
let a = 1;
let b = 2;
let c = 3;
}
}
}

========================================================================
@intention Wrap selected to "try-catch"
Wrap multiple statements in try-catch
========================================================================
contract Test {
fun test() {
<selection>let a = 1;
let b = 2;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
let a = 1;
let b = 2;
} catch(e) {

}
}
}

========================================================================
@intention Wrap selected to "repeat"
Wrap multiple statements in repeat
========================================================================
contract Test {
fun test() {
<selection>let a = 1;
let b = 2;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
repeat(10) {
let a = 1;
let b = 2;
}
}
}

========================================================================
No intentions on empty selection
========================================================================
contract Test {
fun test() {
<selection> </selection>
}
}
------------------------------------------------------------------------
No intentions

========================================================================
@intention Wrap selected to "repeat"
Wrap single statement in repeat
========================================================================
contract Test {
fun test() {
<selection>let a = 1;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
repeat(10) {
let a = 1;
}
}
}

========================================================================
@intention Wrap selected to "try"
Wrap single statement
========================================================================
contract Test {
fun test() {
<selection>let a = 1;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
let a = 1;
}
}
}

========================================================================
@intention Wrap selected to "try"
Wrap mixed statements
========================================================================
contract Test {
fun test() {
<selection>let a = 1;
return a + 1;
self.value = 10;
a += 1;
do {
a = 2;
} until (a > 10);</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
let a = 1;
return a + 1;
self.value = 10;
a += 1;
do {
a = 2;
} until (a > 10);
}
}
}

========================================================================
@intention Wrap selected to "try-catch"
Wrap complex control flow statements
========================================================================
contract Test {
fun test() {
<selection>if (true) {
let x = 1;
}
while (x < 10) {
x += 1;
}
repeat(5) {
x = x * 2;
}
foreach(k, v in map) {
sum += v;
}</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
if (true) {
let x = 1;
}
while (x < 10) {
x += 1;
}
repeat(5) {
x = x * 2;
}
foreach(k, v in map) {
sum += v;
}
} catch(e) {

}
}
}

========================================================================
@intention Wrap selected to "repeat"
Wrap nested control flow
========================================================================
contract Test {
fun test() {
<selection>try {
if (x > 0) {
while(true) {
x -= 1;
}
}
} catch(e) {
return 0;
}</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
repeat(10) {
try {
if (x > 0) {
while(true) {
x -= 1;
}
}
} catch(e) {
return 0;
}
}
}
}

========================================================================
@intention Wrap selected to "try"
Wrap expressions and assignments
========================================================================
contract Test {
fun test() {
<selection>send();
x = 1;
y += 2;
z *= 3;
w |= 4;</selection>
}
}
------------------------------------------------------------------------
contract Test {
fun test() {
try {
send();
x = 1;
y += 2;
z *= 3;
w |= 4;
}
}
}
Loading