-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathutils.ts
More file actions
328 lines (278 loc) · 10.1 KB
/
utils.ts
File metadata and controls
328 lines (278 loc) · 10.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
import * as vscode from 'vscode';
import { assert } from 'console';
import { getOuterSymbols } from './symbol';
import { getConfigInstance } from '../config';
import { activate } from './helper';
import path from 'path';
import { VscodeRequestManager } from './vscodeRequestManager';
// patterns.ts
export async function constructSourceCodeWithRelatedInfo(
document: vscode.TextDocument,
functionSymbol: vscode.DocumentSymbol
): Promise<string> {
// Get the source code of the function
const sourceCode = document.getText(functionSymbol.range);
// Get the file name and relative path
const absolutePath = document.uri.fsPath;
const workspaceRoot = getConfigInstance().workspace || '';
const relativePath = path.relative(workspaceRoot, absolutePath);
const fileName = path.basename(absolutePath);
// Get class name if the function is a method
let className = '';
if (functionSymbol.kind === vscode.SymbolKind.Method) {
// Find the parent class symbol
const parentClass = await findParentClass(document, functionSymbol);
if (parentClass) {
className = parentClass.name;
}
}
// Add the information to functionInfo map
let result = "";
result += `File: ${fileName}\n`;
result += `Relative Path: ${relativePath}\n`;
if (className) {
result += `Class Name: ${className}\n`;
}
result += `\n${sourceCode}`;
return result;
}
// Helper function to find parent class of a method
async function findParentClass(document: vscode.TextDocument, symbol: vscode.DocumentSymbol): Promise<vscode.DocumentSymbol | undefined> {
// Get all symbols in the document
const symbols = await getOuterSymbols(document.uri);
// Find the parent class by checking if the method's range is within the class's range
for (const sym of symbols) {
if (sym.kind === vscode.SymbolKind.Class &&
sym.range.contains(symbol.range)) {
return sym;
}
}
return undefined;
}
export function testFunc() {
console.log('checking test');
}
export interface LanguagePatterns {
[language: string]: string[];
}
export const languageStandardPatterns: LanguagePatterns = {
java: [
'/java.',
'/javax.',
'/javafx.',
'/jdk.',
'/sun.',
'src.zip',
'/mockito-core', // For locating the Mockito core library in Maven/Gradle builds
'/libs/mockito', // If you're storing the mockito jars in a libs folder (adjust based on your project structure)
'/test/mockito', // If you have test folders that contain mockito-related code
],
python: [
'/lib/python',
'/site-packages/',
'/python3.',
'/dist-packages/'
],
typescript: [
'/node_modules/',
'/typescript/',
'/@types/'
],
go: [
'/pkg/',
'/src/',
'/vendor/'
],
// Add more languages and their patterns here
};
/**
* Checks if a given URI corresponds to a standard class/module based on the programming language.
* @param uri - The URI to check.
* @param language - The programming language identifier (e.g., 'java', 'python').
* @returns A boolean indicating whether the URI is a standard class/module.
*/
export function isStandardClass(uri: string, language: string): boolean {
const decodedUri = decodeURIComponent(uri);
const patterns: string[] | undefined = languageStandardPatterns[language.toLowerCase()];
if (!patterns) {
console.warn(`No standard patterns defined for language: ${language}`);
return false;
}
return patterns.some(pattern => decodedUri.includes(pattern));
}
export function parseCode(response: string): string {
// Regular expression to match code block wrapped by triple backticks, optional `~~`, and language tag
const regex = /```(?:\w+)?(?:~~)?\s*([\s\S]*?)\s*```/g;
// Match the response against the regular expression
const matches = Array.from(response.matchAll(regex));
// If a match is found, return the extracted code
if (matches.length > 0) {
return matches[matches.length - 1][1].trim();
}
// If no code block is found, return the original response
return response.trim();
}
export async function getHover(document: vscode.TextDocument, symbol: vscode.DocumentSymbol): Promise<vscode.Hover | undefined> {
const hover = await VscodeRequestManager.hover(document.uri, symbol.selectionRange.start);
if (hover && hover.length > 0) {
return hover[0];
}
}
export function extractHoverText(hover: vscode.Hover | undefined): string | null {
if (!hover) {
return null;
}
const parts = hover.contents.map(content => {
if (typeof content === 'string') {
return content;
}
if (content instanceof vscode.MarkdownString) {
return content.value;
}
return content.value;
}).filter(text => text && text.trim().length > 0);
if (parts.length === 0) {
return null;
}
return parts.join('\n').trim();
}
export function removeComments(code: string): string {
const commentRegex = [
/\/\/[^\n]*\n/g,
/\/\*[\s\S]*?\*\//g,
/'''[\s\S]*?'''/g,
/"""[\s\S]*?"""/g,
/#.*$/gm
];
const withoutComments = commentRegex.reduce((codeWithoutComments, regex) => {
return codeWithoutComments.replace(regex, '');
}, code);
// Remove empty lines (including those with only whitespace)
return withoutComments
.split('\n')
.filter(line => line.trim().length > 0)
.join('\n');
}
export function commentizeCode(code: string, language: string): string {
// it will first remove the comments inside the code, and wrap the code with the comment symbol of the language
// Regular expression to match comments in Go, Java, and Python
let result;
switch (language) {
case 'java':
result = "/*" + removeComments(code) + "*/";
break;
case 'python':
result = "''' " + removeComments(code) + " '''";
break;
case 'go':
result = "/* " + removeComments(code) + " */";
break;
default:
result = code;
break;
}
return result;
}
/**
* Extracts detailed information for a constructor symbol.
* @param document - The text document containing the constructor.
* @param constructorSymbol - The Constructor DocumentSymbol.
* @returns A string detailing the constructor's signature.
*/
export function getConstructorDetail(document: vscode.TextDocument, constructorSymbol: vscode.DocumentSymbol): string | null {
// Retrieve the line text where the constructor is defined
return document.getText(constructorSymbol.range);
if (constructorSymbol.name){
return constructorSymbol.name;
} else {
return document.lineAt(constructorSymbol.selectionRange.start.line).text.trim();
}
}
/**
* Extracts detailed information for a constructor symbol.
* @param document - The text document containing the constructor.
* @param constructorSymbol - The Constructor DocumentSymbol.
* @returns A string detailing the constructor's signature.
*/
export function getFieldDetail(document: vscode.TextDocument, fieldSymbol: vscode.DocumentSymbol): string | null {
// Retrieve the line text where the constructor is defined
return document.getText(fieldSymbol.range);
}
export function isValidFunctionSymbol(functionSymbol: vscode.DocumentSymbol): boolean {
if (!functionSymbol.name) {
vscode.window.showErrorMessage('Function symbol has no name!');
return false;
}
if (!functionSymbol.range) {
vscode.window.showErrorMessage('Function symbol has no range!');
return false;
}
return true;
}
function extractCodeBetweenBackticks(text: string): string[] {
const codeBlocks: string[] = [];
const regex = /```(?:\w+)?\n([\s\S]*?)```/g;
let match;
while ((match = regex.exec(text)) !== null) {
codeBlocks.push(match[1].trim());
}
return codeBlocks;
}
export function formatToJSON(input: string): any {
// Remove any leading/trailing whitespace
const codeBlocks = extractCodeBetweenBackticks(input);
if (codeBlocks.length > 0) {
return JSON.parse(codeBlocks[0]);
}
let cleanInput = input.trim();
// If the input is wrapped in markdown code blocks, remove them
cleanInput = cleanInput.replace(/^```[a-z]*\n|\n```$/g, '');
// Handle escaped characters
const unescapeString = (str: string): string => {
return str
.replace(/\\n/g, '\n')
.replace(/\\"/g, '"')
.replace(/\\t/g, '\t')
.replace(/\\r/g, '\r')
.replace(/\\\\/g, '\\');
};
try {
// First attempt: direct JSON parse
return JSON.parse(cleanInput);
} catch (e) {
try {
// Second attempt: Handle escaped JSON strings
return JSON.parse(unescapeString(cleanInput));
} catch (e2) {
return null;
}
}
}
export function extractArrayFromJSON(jsonContent: any): any[] {
// If it's already an array, return it
if (Array.isArray(jsonContent)) {
return jsonContent;
}
// If it's an object with a single key containing an array
if (typeof jsonContent === 'object' && jsonContent !== null) {
const values = Object.values(jsonContent);
if (values.length === 1 && Array.isArray(values[0])) {
return values[0];
}
}
// If neither format matches, return empty array
return [];
}
// function findParametersOfFunction(defMap: DefMap): Array<vscode.DocumentSymbol> {
// const parameters: Array<vscode.DocumentSymbol> = [];
// for (const [symbol, definition] of defMap) {
// if (definition === null) {
// parameters.push(symbol);
// }
// }
// return parameters;
// }
function isPublic(symbol: vscode.DocumentSymbol, document: vscode.TextDocument): boolean {
const funcDefinition = document.lineAt(symbol.selectionRange.start.line).text;
return funcDefinition.includes('public') || false;
}