Skip to content

Commit e7e36d7

Browse files
committed
feat: 增加Java补全支持
扩展了代码编辑器的功能,添加了对Java语言的自动补全支持。此改动涉及修改index.ts文件,包括导入和初始化Java补全功能。
1 parent 163c34e commit e7e36d7

File tree

6 files changed

+264
-0
lines changed

6 files changed

+264
-0
lines changed

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { initCppCompletion } from './cpp';
2+
import { initJavaCompletion } from './java';
23
import * as monaco from 'monaco-editor';
34
function waitForMonaco(): Promise<typeof monaco> {
45
return new Promise((resolve) => {
@@ -15,6 +16,8 @@ function waitForMonaco(): Promise<typeof monaco> {
1516
async function init() {
1617
const monaco = await waitForMonaco();
1718
initCppCompletion(monaco);
19+
initJavaCompletion(monaco);
20+
1821
}
1922

2023
window.addEventListener('load', init);

src/java/arrayList.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
export function getArrayListSuggestions(monaco: typeof import('monaco-editor'), range: any) {
3+
return [
4+
{
5+
label: 'add',
6+
kind: monaco.languages.CompletionItemKind.Method,
7+
insertText: 'add(${1:element});',
8+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
9+
documentation: 'Adds an element to the ArrayList.',
10+
range: range
11+
},
12+
{
13+
label: 'remove',
14+
kind: monaco.languages.CompletionItemKind.Method,
15+
insertText: 'remove(${1:index});',
16+
documentation: 'Removes the element at the specified index.',
17+
range: range
18+
},
19+
{
20+
label: 'get',
21+
kind: monaco.languages.CompletionItemKind.Method,
22+
insertText: 'get(${1:index});',
23+
documentation: 'Returns the element at the specified index.',
24+
range: range
25+
},
26+
{
27+
label: 'size',
28+
kind: monaco.languages.CompletionItemKind.Method,
29+
insertText: 'size();',
30+
documentation: 'Returns the number of elements in the ArrayList.',
31+
range: range
32+
}
33+
// 其他 ArrayList 方法
34+
];
35+
}

src/java/getGeneralSuggestions.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import type { languages } from 'monaco-editor';
2+
3+
export function getGeneralSuggestions(monaco: typeof import('monaco-editor'), range: any) {
4+
return [
5+
{
6+
label: 'System.out.println',
7+
kind: monaco.languages.CompletionItemKind.Snippet,
8+
insertText: 'System.out.println(${1:message});',
9+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
10+
documentation: 'Prints a message to the standard output',
11+
range: range
12+
},
13+
{
14+
label: 'for (int i = 0; i < n; i++)',
15+
kind: monaco.languages.CompletionItemKind.Snippet,
16+
insertText: 'for (int ${1:i} = 0; ${1:i} < ${2:n}; ${1:i}++) {\n\t$0\n}',
17+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
18+
documentation: 'Basic for loop',
19+
range: range
20+
},
21+
{
22+
label: 'while',
23+
kind: monaco.languages.CompletionItemKind.Snippet,
24+
insertText: 'while (${1:condition}) {\n\t$0\n}',
25+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
26+
documentation: 'While loop',
27+
range: range
28+
},
29+
{
30+
label: 'if',
31+
kind: monaco.languages.CompletionItemKind.Snippet,
32+
insertText: 'if (${1:condition}) {\n\t$0\n}',
33+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
34+
documentation: 'If statement',
35+
range: range
36+
},
37+
{
38+
label: 'ArrayList',
39+
kind: monaco.languages.CompletionItemKind.Snippet,
40+
insertText: 'ArrayList<${1:type}> ${2:list} = new ArrayList<>();',
41+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
42+
documentation: 'Creates an ArrayList',
43+
range: range
44+
},
45+
{
46+
label: 'HashMap',
47+
kind: monaco.languages.CompletionItemKind.Snippet,
48+
insertText: 'HashMap<${1:K}, ${2:V}> ${3:map} = new HashMap<>();',
49+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
50+
documentation: 'Creates a HashMap',
51+
range: range
52+
},
53+
{
54+
label: 'HashSet',
55+
kind: monaco.languages.CompletionItemKind.Snippet,
56+
insertText: 'HashSet<${1:type}> ${2:set} = new HashSet<>();',
57+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
58+
documentation: 'Creates a HashSet',
59+
range: range
60+
},
61+
// 可以继续添加更多通用提示
62+
];
63+
}

src/java/hashMap.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
2+
export function getHashMapSuggestions(monaco: typeof import('monaco-editor'), range: any) {
3+
return [
4+
{
5+
label: 'put',
6+
kind: monaco.languages.CompletionItemKind.Method,
7+
insertText: 'put(${1:key}, ${2:value});',
8+
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
9+
documentation: 'Associates the specified value with the specified key in this map.',
10+
range: range
11+
},
12+
{
13+
label: 'get',
14+
kind: monaco.languages.CompletionItemKind.Method,
15+
insertText: 'get(${1:key});',
16+
documentation: 'Returns the value to which the specified key is mapped.',
17+
range: range
18+
},
19+
{
20+
label: 'remove',
21+
kind: monaco.languages.CompletionItemKind.Method,
22+
insertText: 'remove(${1:key});',
23+
documentation: 'Removes the mapping for the specified key from this map if present.',
24+
range: range
25+
},
26+
{
27+
label: 'containsKey',
28+
kind: monaco.languages.CompletionItemKind.Method,
29+
insertText: 'containsKey(${1:key});',
30+
documentation: 'Returns true if this map contains a mapping for the specified key.',
31+
range: range
32+
},
33+
{
34+
label: 'keySet',
35+
kind: monaco.languages.CompletionItemKind.Method,
36+
insertText: 'keySet();',
37+
documentation: 'Returns a Set view of the keys contained in this map.',
38+
range: range
39+
},
40+
// 可以继续添加更多方法提示
41+
];
42+
}

src/java/index.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import type { languages } from 'monaco-editor';
2+
import { getArrayListSuggestions } from './arrayList';
3+
import { getHashMapSuggestions } from './hashMap';
4+
import { getJavaRange, extractJavaVariables } from './utils';
5+
import { getGeneralSuggestions } from './getGeneralSuggestions';
6+
7+
export function initJavaCompletion(monaco: typeof import('monaco-editor')) {
8+
monaco.languages.register({ id: 'java' });
9+
10+
monaco.languages.registerCompletionItemProvider('java', {
11+
provideCompletionItems: (model, position) => {
12+
const word = model.getWordUntilPosition(position);
13+
const range = getJavaRange(position, word); // 获取光标位置的范围
14+
15+
const code = model.getValue(); // 获取整个代码
16+
const variables = extractJavaVariables(code, position); // 提取变量
17+
18+
// 提供变量补全提示
19+
const variableSuggestions: { label: string; kind: languages.CompletionItemKind; insertText: string; documentation: string; range: any; }[] = [];
20+
variables.forEach(({ type }, name) => {
21+
variableSuggestions.push({
22+
label: name,
23+
kind: monaco.languages.CompletionItemKind.Variable,
24+
insertText: name,
25+
documentation: `Variable of type ${type}`,
26+
range: range
27+
});
28+
});
29+
30+
// 获取当前行的内容并判断是否有“.”
31+
const lineContent = model.getLineContent(position.lineNumber);
32+
const textBeforeCursor = lineContent.substring(0, position.column - 1).trim();
33+
const lastDotIndex = textBeforeCursor.lastIndexOf('.');
34+
let methodSuggestions: { label: string; kind: languages.CompletionItemKind; insertText: string; documentation: string; range: any; }[] = [];
35+
let isDotAfterVariable = false;
36+
37+
// 检查是否有“.”和变量,并获取该变量类型的相应方法提示
38+
if (lastDotIndex !== -1) {
39+
const varName = textBeforeCursor.substring(0, lastDotIndex).trim();
40+
41+
if (variables.has(varName)) {
42+
const varInfo = variables.get(varName);
43+
isDotAfterVariable = true;
44+
// 根据变量类型返回相应的成员方法提示
45+
switch (varInfo.type) {
46+
case 'ArrayList':
47+
methodSuggestions = getArrayListSuggestions(monaco, range);
48+
break;
49+
case 'HashMap':
50+
methodSuggestions = getHashMapSuggestions(monaco, range);
51+
break;
52+
default:
53+
break;
54+
}
55+
}
56+
}
57+
58+
// 如果没有"."或者未识别出变量,返回通用的建议和变量提示
59+
if (!isDotAfterVariable) {
60+
const generalSuggestions = getGeneralSuggestions(monaco, range);
61+
return {
62+
suggestions: [...generalSuggestions, ...variableSuggestions]
63+
};
64+
} else {
65+
return {
66+
suggestions: [...methodSuggestions]
67+
};
68+
}
69+
}
70+
});
71+
}

src/java/utils.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export function extractJavaVariables(code: string, position: any) {
2+
// 改进正则表达式,匹配泛型声明 (如 ArrayList<int> list)
3+
const variableRegex = /\b(?:ArrayList|List|Set|Map|Queue|Stack|Deque|LinkedList|HashMap|HashSet|TreeMap|TreeSet|PriorityQueue)\s*<[^>]+>\s+(\w+)\s*=/g;
4+
const basicTypeRegex = /\b(?:int|float|double|char|boolean|String|byte|short|long)\s+(\w+)\s*;/g; // 基本类型匹配
5+
const funcParamRegex = /\(([^)]*)\)/g; // 提取函数参数列表
6+
7+
const variables = new Map<string, { type: string, kind: string }>();
8+
9+
// 仅解析光标之前的代码
10+
const lines = code.split('\n').slice(0, position.lineNumber - 1);
11+
let currentLine = code.split('\n')[position.lineNumber - 1].substring(0, position.column - 1);
12+
lines.push(currentLine);
13+
const codeBeforeCursor = lines.join('\n');
14+
15+
// 提取泛型类型变量(如 ArrayList<int> list = new ArrayList<>())
16+
let match;
17+
while ((match = variableRegex.exec(codeBeforeCursor)) !== null) {
18+
const varName = match[1]; // 获取变量名
19+
variables.set(varName, { type: "ArrayList", kind: "variable" }); // 设置为泛型类型
20+
}
21+
22+
// 提取基本类型变量
23+
while ((match = basicTypeRegex.exec(codeBeforeCursor)) !== null) {
24+
const varName = match[1]; // 获取变量名
25+
variables.set(varName, { type: "basic", kind: "variable" }); // 设置为基本类型
26+
}
27+
28+
// 提取函数形参
29+
const funcMatch = funcParamRegex.exec(codeBeforeCursor);
30+
if (funcMatch) {
31+
const params = funcMatch[1].split(',');
32+
params.forEach(param => {
33+
const parts = param.trim().split(/\s+/);
34+
const paramName = parts[parts.length - 1]; // 获取形参名
35+
variables.set(paramName, { type: "parameter", kind: "parameter" }); // 设置为形参
36+
});
37+
}
38+
39+
return variables;
40+
}
41+
42+
43+
export function getJavaRange(position: any, word: any) {
44+
return {
45+
startLineNumber: position.lineNumber,
46+
endLineNumber: position.lineNumber,
47+
startColumn: word.startColumn,
48+
endColumn: word.endColumn
49+
};
50+
}

0 commit comments

Comments
 (0)