opencode / opencode.js
tanbushi's picture
update
e1847c0
class OpenCodeAI {
constructor() {
this.supportedLanguages = [
'javascript', 'python', 'java', 'cpp', 'c', 'csharp',
'go', 'rust', 'php', 'typescript', 'html', 'css'
];
}
// 分析代码质量
async analyzeCode(code, language) {
const analysis = {
language: this.detectLanguage(code, language),
issues: [],
suggestions: [],
metrics: this.calculateMetrics(code)
};
// 基本语法检查
analysis.issues = this.checkSyntax(code, analysis.language);
// 生成改进建议
analysis.suggestions = this.generateSuggestions(code, analysis.language);
return analysis;
}
// 检测编程语言
detectLanguage(code, hintedLanguage) {
if (hintedLanguage && this.supportedLanguages.includes(hintedLanguage)) {
return hintedLanguage;
}
// 简单的语言检测
if (code.includes('def ') && code.includes(':')) return 'python';
if (code.includes('function ') || code.includes('const ')) return 'javascript';
if (code.includes('public class ')) return 'java';
if (code.includes('#include')) return 'cpp';
if (code.includes('<!DOCTYPE')) return 'html';
if (code.includes('{') && code.includes('}')) return 'css';
return 'javascript'; // 默认
}
// 检查语法问题
checkSyntax(code, language) {
const issues = [];
// 通用检查
const lines = code.split('\n');
lines.forEach((line, index) => {
// 检查未闭合的括号
if (line.includes('{') || line.includes('(') || line.includes('[')) {
const openBrackets = (line.match(/[({[]/g) || []).length;
const closeBrackets = (line.match(/[)}\]]/g) || []).length;
if (openBrackets !== closeBrackets) {
issues.push({
line: index + 1,
type: 'syntax',
message: '可能存在未闭合的括号',
severity: 'warning'
});
}
}
// 检查过长的行
if (line.length > 120) {
issues.push({
line: index + 1,
type: 'style',
message: '行长度过长 (>120字符)',
severity: 'info'
});
}
});
// 语言特定检查
switch (language) {
case 'javascript':
issues.push(...this.checkJavaScript(code));
break;
case 'python':
issues.push(...this.checkPython(code));
break;
case 'java':
issues.push(...this.checkJava(code));
break;
}
return issues;
}
// JavaScript 特定检查
checkJavaScript(code) {
const issues = [];
// 检查var关键字
if (code.includes('var ')) {
issues.push({
line: null,
type: 'style',
message: '建议使用 let 或 const 替代 var',
severity: 'warning'
});
}
// 检查分号缺失
const statements = code.split('\n').filter(line =>
line.trim() && !line.trim().startsWith('//') &&
!line.trim().startsWith('/*') &&
!line.includes('{') && !line.includes('}') &&
!line.endsWith(';') && !line.endsWith(',') &&
!line.includes('if ') && !line.includes('for ') &&
!line.includes('while ') && !line.includes('function ')
);
if (statements.length > 0) {
issues.push({
line: null,
type: 'style',
message: '可能缺少分号',
severity: 'info'
});
}
return issues;
}
// Python 特定检查
checkPython(code) {
const issues = [];
// 检查PEP 8缩进
const lines = code.split('\n');
lines.forEach((line, index) => {
const trimmed = line.trim();
if (trimmed && !trimmed.startsWith('#')) {
const leadingSpaces = line.length - line.trimStart().length;
if (leadingSpaces % 4 !== 0) {
issues.push({
line: index + 1,
type: 'style',
message: '缩进应该使用4个空格',
severity: 'warning'
});
}
}
});
return issues;
}
// Java 特定检查
checkJava(code) {
const issues = [];
// 检查类名
const classMatch = code.match(/class\s+(\w+)/);
if (classMatch && !/^[A-Z]/.test(classMatch[1])) {
issues.push({
line: null,
type: 'style',
message: '类名应该以大写字母开头',
severity: 'warning'
});
}
return issues;
}
// 生成代码改进建议
generateSuggestions(code, language) {
const suggestions = [];
// 性能建议
if (code.includes('for (')) {
suggestions.push({
type: 'performance',
message: '考虑使用更高效的循环方式,如 forEach 或 map',
code_example: '// 替代方案\narray.forEach(item => { /* ... */ });'
});
}
// 可读性建议
if (code.includes('TODO') || code.includes('FIXME')) {
suggestions.push({
type: 'maintenance',
message: '发现待办事项,建议及时处理'
});
}
// 安全建议
if (code.includes('eval(')) {
suggestions.push({
type: 'security',
message: '避免使用 eval(),存在安全风险',
severity: 'high'
});
}
return suggestions;
}
// 计算代码指标
calculateMetrics(code) {
const lines = code.split('\n');
const totalLines = lines.length;
const codeLines = lines.filter(line =>
line.trim() && !line.trim().startsWith('//') &&
!line.trim().startsWith('#') && !line.trim().startsWith('/*')
).length;
return {
total_lines: totalLines,
code_lines: codeLines,
comment_lines: totalLines - codeLines,
complexity: this.calculateComplexity(code)
};
}
// 计算圈复杂度
calculateComplexity(code) {
let complexity = 1; // 基础复杂度
const complexityKeywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'catch', '&&', '||'];
complexityKeywords.forEach(keyword => {
const regex = new RegExp(`\\b${keyword}\\b`, 'g');
const matches = code.match(regex);
if (matches) complexity += matches.length;
});
return complexity;
}
// 代码补全
async getCodeCompletion(partialCode, position) {
// 简单的代码补全逻辑
const suggestions = [];
const line = partialCode.split('\n')[position.line - 1] || '';
const currentWord = line.substring(0, position.character).split(' ').pop();
const language = this.detectLanguage(partialCode);
switch (language) {
case 'javascript':
suggestions.push(...this.getJavaScriptCompletions(currentWord));
break;
case 'python':
suggestions.push(...this.getPythonCompletions(currentWord));
break;
default:
suggestions.push(...this.getGenericCompletions(currentWord));
}
return suggestions;
}
getJavaScriptCompletions(currentWord) {
const jsKeywords = [
'function', 'const', 'let', 'var', 'if', 'else', 'for', 'while',
'return', 'class', 'extends', 'import', 'export', 'async', 'await',
'map', 'filter', 'reduce', 'forEach', 'find', 'some', 'every'
];
return jsKeywords
.filter(keyword => keyword.startsWith(currentWord))
.map(keyword => ({
text: keyword,
type: 'keyword',
description: `JavaScript keyword: ${keyword}`
}));
}
getPythonCompletions(currentWord) {
const pythonKeywords = [
'def', 'class', 'if', 'elif', 'else', 'for', 'while',
'return', 'import', 'from', 'as', 'try', 'except', 'with',
'len', 'range', 'list', 'dict', 'set', 'tuple', 'str'
];
return pythonKeywords
.filter(keyword => keyword.startsWith(currentWord))
.map(keyword => ({
text: keyword,
type: 'keyword',
description: `Python keyword: ${keyword}`
}));
}
getGenericCompletions(currentWord) {
return [
{ text: currentWord, type: 'variable', description: 'Current variable' }
];
}
}
export default OpenCodeAI;