Skip to content

Commit 98b2699

Browse files
authored
Merge pull request #2890 from continuedev/tomasz/python-context
Python context (extend + test)
2 parents d2fa937 + d5a0782 commit 98b2699

File tree

8 files changed

+101
-47
lines changed

8 files changed

+101
-47
lines changed

core/autocomplete/context/root-path-context/RootPathContextService.ts

+3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ export class RootPathContextService {
2626
private static TYPES_TO_USE = new Set([
2727
"program",
2828
"function_declaration",
29+
"function_definition",
2930
"method_definition",
3031
"class_declaration",
32+
"class_definition",
3133
]);
3234

3335
/**
@@ -97,6 +99,7 @@ export class RootPathContextService {
9799
contents: await this.ide.readRangeInFile(def.filepath, def.range),
98100
})),
99101
);
102+
100103
return newSnippets;
101104
}
102105

core/autocomplete/context/root-path-context/test/RootPathContextService.test.ts

+41-20
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,62 @@ import { testRootPathContext } from "./testUtils";
22

33
const TEST_CASES = [
44
{
5-
description: "function",
5+
nodeType: "function_declaration",
66
fileName: "file1.ts",
7-
range: {
8-
start: { line: 10, character: 2 },
9-
end: { line: 10, character: 24 },
10-
},
11-
positions: [
7+
language: "TypeScript",
8+
cursorPosition: { line: 10, character: 24 },
9+
definitionPositions: [
1210
{ row: 9, column: 34 }, // Person
1311
{ row: 9, column: 44 }, // Address
1412
],
1513
},
1614
{
17-
description: "class method",
15+
nodeType: "method_declaration",
1816
fileName: "file1.ts",
19-
range: {
20-
start: { line: 22, character: 4 },
21-
end: { line: 22, character: 30 },
22-
},
23-
positions: [
17+
language: "TypeScript",
18+
cursorPosition: { line: 22, character: 30 },
19+
definitionPositions: [
2420
{ row: 13, column: 29 }, // BaseClass
2521
{ row: 13, column: 55 }, // FirstInterface
2622
{ row: 13, column: 72 }, // SecondInterface
2723
{ row: 21, column: 33 }, // Person
2824
{ row: 21, column: 43 }, // Address
2925
],
3026
},
27+
{
28+
nodeType: "function_definition",
29+
fileName: "file1.py",
30+
language: "Python",
31+
cursorPosition: { line: 4, character: 25 },
32+
definitionPositions: [
33+
{ row: 3, column: 30 }, // Person
34+
{ row: 3, column: 42 }, // Address
35+
],
36+
},
37+
{
38+
nodeType: "function_definition (inside a class)",
39+
fileName: "file1.py",
40+
language: "Python",
41+
cursorPosition: { line: 12, character: 33 },
42+
definitionPositions: [
43+
{ row: 6, column: 21 }, // BaseClass
44+
{ row: 6, column: 33 }, // Collection
45+
{ row: 11, column: 47 }, // Person
46+
{ row: 11, column: 59 }, // Address
47+
],
48+
},
3149
];
3250

3351
describe("RootPathContextService", () => {
34-
describe("TypeScript should return expected snippets when editing inside a:", () => {
35-
test.each(TEST_CASES)(
36-
"should look for correct type definitions when editing inside a $description",
37-
async ({ fileName, range, positions }) => {
38-
await testRootPathContext("typescript", fileName, range, positions);
39-
},
40-
);
41-
});
52+
test.each(TEST_CASES)(
53+
"Should look for correct type definitions when editing inside a $nodeType in $language",
54+
async ({ fileName, cursorPosition, definitionPositions }) => {
55+
await testRootPathContext(
56+
"files",
57+
fileName,
58+
cursorPosition,
59+
definitionPositions,
60+
);
61+
},
62+
);
4263
});

core/autocomplete/context/root-path-context/test/files/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# File: base_module.py
2+
3+
class BaseClass:
4+
def __init__(self):
5+
print("BaseClass initialized")
6+
7+
class Collection:
8+
def __init__(self):
9+
print("Collection initialized")
10+
11+
class Address:
12+
def __init__(self, street: str, city: str, zip_code: str):
13+
self.street = street
14+
self.city = city
15+
self.zip_code = zip_code
16+
17+
def __str__(self):
18+
return f"{self.street}, {self.city}, {self.zip_code}"
19+
20+
class Person:
21+
def __init__(self, name: str, address: Address):
22+
self.name = name
23+
self.address = address
24+
25+
def __str__(self):
26+
return f"{self.name} lives at {self.address}"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from .base_module import BaseClass, Collection, Person, Address
2+
from typing import List
3+
4+
def get_address(person: Person) -> Address:
5+
return person.address
6+
7+
class Group(BaseClass, Collection):
8+
def __init__(self, people: List[Person]) -> None:
9+
super().__init__()
10+
self.people = people
11+
12+
def get_person_address(self, person: Person) -> Address:
13+
return get_address(person)

core/autocomplete/context/root-path-context/test/testUtils.ts

+13-27
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,32 @@ import fs from "fs";
33
import path from "path";
44

55
import Parser from "web-tree-sitter";
6-
import { Range } from "../../../..";
6+
import { Position } from "../../../..";
77
import { testIde } from "../../../../test/util/fixtures";
88
import { getAst, getTreePathAtCursor } from "../../../util/ast";
99
import { ImportDefinitionsService } from "../../ImportDefinitionsService";
1010
import { RootPathContextService } from "../RootPathContextService";
1111

12-
function splitTextAtRange(fileContent: string, range: Range): [string, string] {
12+
function splitTextAtPosition(
13+
fileContent: string,
14+
position: Position,
15+
): [string, string] {
1316
const lines = fileContent.split("\n");
1417
let currentPos = 0;
1518

16-
if (range.start.line === range.end.line) {
17-
// If range is on the same line, calculate position once
18-
for (let i = 0; i < range.start.line; i++) {
19-
currentPos += lines[i].length + 1; // +1 for the newline character
20-
}
21-
const startPos = currentPos + range.start.character;
22-
const endPos = currentPos + range.end.character;
23-
return [fileContent.slice(0, startPos), fileContent.slice(endPos)];
19+
// Calculate position based on the provided line and character
20+
for (let i = 0; i < position.line; i++) {
21+
currentPos += lines[i].length + 1; // +1 for the newline character
2422
}
23+
const splitPos = currentPos + position.character;
2524

26-
// Calculate position of range start
27-
for (let i = 0; i < range.start.line; i++) {
28-
currentPos += lines[i].length + 1;
29-
}
30-
const startPos = currentPos + range.start.character;
31-
32-
// Calculate position of range end
33-
currentPos = 0;
34-
for (let i = 0; i < range.end.line; i++) {
35-
currentPos += lines[i].length + 1;
36-
}
37-
const endPos = currentPos + range.end.character;
38-
39-
return [fileContent.slice(0, startPos), fileContent.slice(endPos)];
25+
return [fileContent.slice(0, splitPos), fileContent.slice(splitPos)];
4026
}
4127

4228
export async function testRootPathContext(
4329
folderName: string,
4430
relativeFilepath: string,
45-
rangeToFill: Range,
31+
position: Position,
4632
expectedDefinitionPositions: Parser.Point[],
4733
) {
4834
// Create a mocked instance of RootPathContextService
@@ -76,9 +62,9 @@ export async function testRootPathContext(
7662

7763
// Get results of root path context
7864
const startPath = path.join(testFolderPath, relativeFilepath);
79-
const [prefix, suffix] = splitTextAtRange(
65+
const [prefix, suffix] = splitTextAtPosition(
8066
fs.readFileSync(startPath, "utf8"),
81-
rangeToFill,
67+
position,
8268
);
8369
const fileContents = prefix + suffix;
8470
const ast = await getAst(startPath, fileContents);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(
2+
(class_definition
3+
superclasses: (argument_list
4+
(identifier) @superclass))
5+
)

0 commit comments

Comments
 (0)