"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeErrorProvider = void 0; const vscode = __importStar(require("vscode")); // 代码错误检测提供者类 class CodeErrorProvider { // 提供代码诊断信息 static async provideDiagnostics(document, diagnostics) { const diagnosticList = []; let isInBlockComment = false; // 文档级别的块注释状态 // 全文档检查,支持多行结构 const documentText = document.getText(); const lines = documentText.split('\n'); // 检查未闭合的字符串(支持多行) diagnosticList.push(...this.checkForUnclosedStrings(document)); // 检查未闭合的括号(支持多行) diagnosticList.push(...this.checkForUnclosedBrackets(document)); // 逐行检查其他错误,传递块注释状态 for (let i = 0; i < document.lineCount; i++) { const line = document.lineAt(i); const result = this.checkLineForErrors(line, i, isInBlockComment); diagnosticList.push(...result.diagnostics); isInBlockComment = result.isInBlockComment; // 更新块注释状态 } // 发布诊断信息 diagnostics.set(document.uri, diagnosticList); } // 检查单行代码错误,支持块注释状态跟踪 static checkLineForErrors(line, lineIndex, isInBlockComment) { const diagnostics = []; const lineText = line.text; // 处理行注释和块注释状态 const commentInfo = this.processCommentsAndGetValidText(lineText, isInBlockComment); // 如果整行都在注释中,直接返回 if (commentInfo.skipEntireLine) { return { diagnostics, isInBlockComment: commentInfo.newBlockCommentState }; } // 只对非注释部分进行错误检测 if (commentInfo.validText.trim().length > 0) { // 检查常见的语法错误 diagnostics.push(...this.checkForCommonSyntaxErrorsWithValidText(lineText, commentInfo.validText, commentInfo.validRange, lineIndex)); // 检查可能的拼写错误 diagnostics.push(...this.checkForPossibleTyposWithValidText(lineText, commentInfo.validText, commentInfo.validRange, lineIndex)); } return { diagnostics, isInBlockComment: commentInfo.newBlockCommentState }; } // 处理注释并获取有效的代码文本 static processCommentsAndGetValidText(lineText, isInBlockComment) { let currentBlockCommentState = isInBlockComment; // 如果整行都在块注释中,先检查是否有结束标记 if (currentBlockCommentState) { const blockCommentEnd = lineText.indexOf('*/'); if (blockCommentEnd !== -1) { // 找到块注释结束,从结束位置后开始处理 currentBlockCommentState = false; const remainingLine = lineText.substring(blockCommentEnd + 2); // 递归处理剩余部分 const remainingResult = this.processCommentsAndGetValidText(remainingLine, false); return { validText: remainingResult.validText, validRange: { start: blockCommentEnd + 2 + remainingResult.validRange.start, end: blockCommentEnd + 2 + remainingResult.validRange.end }, skipEntireLine: remainingResult.skipEntireLine, newBlockCommentState: remainingResult.newBlockCommentState }; } else { // 整行都在块注释中 return { validText: '', validRange: { start: 0, end: 0 }, skipEntireLine: true, newBlockCommentState: true }; } } // 现在处理这一行,移除所有注释,只保留有效代码部分 let result = ''; let validRanges = []; let inString = false; let stringChar = ''; let escaped = false; let i = 0; let currentValidStart = 0; while (i < lineText.length) { const char = lineText[i]; const nextChar = i < lineText.length - 1 ? lineText[i + 1] : ''; // 处理字符串状态 if (!inString) { if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; } } else { if (escaped) { escaped = false; i++; continue; } if (char === '\\') { escaped = true; i++; continue; } if (char === stringChar) { inString = false; stringChar = ''; i++; continue; } i++; continue; } // 只有在非字符串状态下才检查注释 if (!inString) { // 检查行注释 // (优先级最高) if (char === '/' && nextChar === '/') { // 遇到行注释,保存当前有效部分,后续全部跳过 if (i > currentValidStart) { validRanges.push({ start: currentValidStart, end: i }); result += lineText.substring(currentValidStart, i); } break; // 行注释后面的内容全部跳过 } // 检查块注释开始 /* if (char === '/' && nextChar === '*') { // 保存块注释前的有效部分 if (i > currentValidStart) { validRanges.push({ start: currentValidStart, end: i }); result += lineText.substring(currentValidStart, i); } // 寻找块注释结束 const blockCommentEnd = lineText.indexOf('*/', i + 2); if (blockCommentEnd !== -1) { // 同行找到块注释结束,跳过整个块注释 i = blockCommentEnd + 2; currentValidStart = i; continue; } else { // 没有找到结束标记,块注释延续到下一行 currentBlockCommentState = true; break; } } } i++; } // 添加最后的有效部分 if (!currentBlockCommentState && currentValidStart < lineText.length) { validRanges.push({ start: currentValidStart, end: lineText.length }); result += lineText.substring(currentValidStart); } // 如果没有有效内容,返回空 if (validRanges.length === 0) { return { validText: '', validRange: { start: 0, end: 0 }, skipEntireLine: true, newBlockCommentState: currentBlockCommentState }; } // 返回第一个有效范围(简化处理,实际使用时会在所有有效范围中检查) return { validText: result, validRange: { start: validRanges[0].start, end: validRanges[validRanges.length - 1].end }, skipEntireLine: result.trim().length === 0, newBlockCommentState: currentBlockCommentState }; } // 检查指定位置是否在字符串中 static isInString(line, position) { let inString = false; let stringChar = ''; let escaped = false; for (let i = 0; i < position && i < line.length; i++) { const char = line[i]; if (!inString) { if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; } } else { if (escaped) { escaped = false; continue; } if (char === '\\') { escaped = true; continue; } if (char === stringChar) { inString = false; stringChar = ''; } } } return inString; } // 基于有效文本范围检查语法错误 static checkForCommonSyntaxErrorsWithValidText(originalLine, validText, validRange, lineIndex) { const diagnostics = []; // 跳过空行 if (validText.trim().length === 0) { return diagnostics; } // 由于validText可能是多个片段拼接的结果,我们需要直接在原始行中查找 // 但只检查那些不在注释和字符串中的位置 const typoPatterns = [ { pattern: /\bloacl\b/g, correct: 'local', message: '拼写错误:应该是 "local" 而不是 "loacl"' }, { pattern: /\bfunctoin\b/g, correct: 'function', message: '拼写错误:应该是 "function" 而不是 "functoin"' }, { pattern: /\bretun\b/g, correct: 'return', message: '拼写错误:应该是 "return" 而不是 "retun"' }, { pattern: /\bwhlie\b/g, correct: 'while', message: '拼写错误:应该是 "while" 而不是 "whlie"' }, { pattern: /\belsee\b/g, correct: 'else', message: '拼写错误:应该是 "else" 而不是 "elsee"' }, { pattern: /\bforech\b/g, correct: 'foreach', message: '拼写错误:应该是 "foreach" 而不是 "forech"' }, { pattern: /\bclas\b/g, correct: 'class', message: '拼写错误:应该是 "class" 而不是 "clas"' }, { pattern: /\bbreka\b/g, correct: 'break', message: '拼写错误:应该是 "break" 而不是 "breka"' }, { pattern: /\bcontineu\b/g, correct: 'continue', message: '拼写错误:应该是 "continue" 而不是 "contineu"' } ]; typoPatterns.forEach(({ pattern, correct, message }) => { let match; // 在原始行中查找所有匹配 while ((match = pattern.exec(originalLine)) !== null) { const matchPosition = match.index; // 检查这个位置是否在有效的代码区域(不在注释或字符串中) if (this.isPositionInValidCode(originalLine, matchPosition)) { const range = new vscode.Range(new vscode.Position(lineIndex, matchPosition), new vscode.Position(lineIndex, matchPosition + match[0].length)); const diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Error); diagnostic.tags = [vscode.DiagnosticTag.Deprecated]; diagnostics.push(diagnostic); } } }); return diagnostics; } // 检查指定位置是否在有效代码中(不在注释或字符串中) static isPositionInValidCode(line, position) { let inString = false; let stringChar = ''; let escaped = false; let inBlockComment = false; for (let i = 0; i < position && i < line.length; i++) { const char = line[i]; const nextChar = i < line.length - 1 ? line[i + 1] : ''; // 如果在块注释中,检查是否遇到结束标记 if (inBlockComment) { if (char === '*' && nextChar === '/') { inBlockComment = false; i++; // 跳过 '/' } continue; } // 处理字符串状态 if (!inString) { if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; } } else { if (escaped) { escaped = false; continue; } if (char === '\\') { escaped = true; continue; } if (char === stringChar) { inString = false; stringChar = ''; } continue; } // 只有在非字符串状态下才检查注释 if (!inString) { // 检查行注释 if (char === '/' && nextChar === '/') { return false; // 位置在行注释中 } // 检查块注释开始 if (char === '/' && nextChar === '*') { inBlockComment = true; i++; // 跳过 '*' continue; } } } // 如果到达目标位置时仍在字符串或块注释中,则该位置无效 return !inString && !inBlockComment; } // 基于有效文本范围检查可能的拼写错误 static checkForPossibleTyposWithValidText(originalLine, validText, validRange, lineIndex) { const diagnostics = []; // 暂时空实现,可以后续扩展 return diagnostics; } // 检查常见的语法错误 static checkForCommonSyntaxErrors(lineText, lineIndex) { const diagnostics = []; // 跳过空行 const trimmedLine = lineText.trim(); if (trimmedLine.length === 0) { return diagnostics; } // 检查是否使用了错误的关键字拼写(仅检查明显的拼写错误) const typoPatterns = [ { pattern: /\bloacl\b/g, correct: 'local', message: '拼写错误:应该是 "local" 而不是 "loacl"' }, { pattern: /\bfunctoin\b/g, correct: 'function', message: '拼写错误:应该是 "function" 而不是 "functoin"' }, { pattern: /\bretun\b/g, correct: 'return', message: '拼写错误:应该是 "return" 而不是 "retun"' }, { pattern: /\bwhlie\b/g, correct: 'while', message: '拼写错误:应该是 "while" 而不是 "whlie"' }, { pattern: /\belsee\b/g, correct: 'else', message: '拼写错误:应该是 "else" 而不是 "elsee"' }, { pattern: /\bforech\b/g, correct: 'foreach', message: '拼写错误:应该是 "foreach" 而不是 "forech"' }, { pattern: /\bclas\b/g, correct: 'class', message: '拼写错误:应该是 "class" 而不是 "clas"' }, { pattern: /\bbreka\b/g, correct: 'break', message: '拼写错误:应该是 "break" 而不是 "breka"' }, { pattern: /\bcontineu\b/g, correct: 'continue', message: '拼写错误:应该是 "continue" 而不是 "contineu"' } ]; typoPatterns.forEach(({ pattern, correct, message }) => { let match; while ((match = pattern.exec(lineText)) !== null) { // 检查这个匹配是否在注释或字符串中 if (this.isPositionInCommentOrString(lineText, match.index)) { continue; } const range = new vscode.Range(new vscode.Position(lineIndex, match.index), new vscode.Position(lineIndex, match.index + match[0].length)); const diagnostic = new vscode.Diagnostic(range, message, vscode.DiagnosticSeverity.Error); // 添加快速修复信息 diagnostic.tags = [vscode.DiagnosticTag.Deprecated]; diagnostics.push(diagnostic); } }); // 检查赋值操作符错误(使用 = 而不是 == 进行比较) // 更精确的正则表达式,避免误报 const assignmentPattern = /\b(if|while)\s*\(\s*[^=<>!]*\s=(?!=)\s*[^=][^)]*\)/g; let assignmentMatch; while ((assignmentMatch = assignmentPattern.exec(lineText)) !== null) { // 检查这个匹配是否在注释或字符串中 if (this.isPositionInCommentOrString(lineText, assignmentMatch.index)) { continue; } // 排除明显的合法赋值情况 const matchText = assignmentMatch[0]; // 检查是否是函数调用或其他合法语法 if (!matchText.includes('()') && !matchText.includes('new ')) { const range = new vscode.Range(new vscode.Position(lineIndex, assignmentMatch.index), new vscode.Position(lineIndex, assignmentMatch.index + assignmentMatch[0].length)); const diagnostic = new vscode.Diagnostic(range, '可能的逻辑错误:在条件语句中使用了赋值操作符 "=" 而不是比较操作符 "=="', vscode.DiagnosticSeverity.Warning); diagnostics.push(diagnostic); } } // 检查常见的语法结构错误 // 检查函数定义语法 if (lineText.includes('function') && !lineText.match(/function\s+[a-zA-Z_]\w*\s*\(/)) { const functionMatch = lineText.match(/function\s*\(/); if (functionMatch && !this.isPositionInCommentOrString(lineText, functionMatch.index)) { const range = new vscode.Range(new vscode.Position(lineIndex, functionMatch.index), new vscode.Position(lineIndex, functionMatch.index + functionMatch[0].length)); const diagnostic = new vscode.Diagnostic(range, '语法错误:函数定义缺少函数名', vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); } } // 检查缺少分号的语句(仅对明显需要分号的语句检查) const needsSemicolon = /\b(local|return|break|continue)\s+[^;\/]*[^;\s\/]$/; if (needsSemicolon.test(trimmedLine) && !trimmedLine.endsWith(';') && !trimmedLine.endsWith('{')) { // 确保这不是在注释中 const cleanLine = this.removeStringsAndComments(lineText); if (cleanLine.trim()) { const range = new vscode.Range(new vscode.Position(lineIndex, lineText.length - 1), new vscode.Position(lineIndex, lineText.length)); const diagnostic = new vscode.Diagnostic(range, '可能缺少分号', vscode.DiagnosticSeverity.Information); diagnostics.push(diagnostic); } } return diagnostics; } // 检查未闭合的字符串(支持多行文档检查) static checkForUnclosedStrings(document) { const diagnostics = []; const text = document.getText(); // 使用状态机来正确解析字符串 let inString = false; let stringStartPos = null; let stringChar = ''; let escaped = false; let inLineComment = false; let inBlockComment = false; const lines = text.split('\n'); for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { const line = lines[lineIndex]; // 检查是否整行都是注释(以 // 开头) const trimmedLine = line.trim(); if (trimmedLine.startsWith('//')) { inLineComment = true; } for (let charIndex = 0; charIndex < line.length; charIndex++) { const char = line[charIndex]; const nextChar = charIndex < line.length - 1 ? line[charIndex + 1] : ''; // 处理注释 if (!inString) { if (!inBlockComment && char === '/' && nextChar === '/') { inLineComment = true; charIndex++; // 跳过下一个字符 continue; } if (!inLineComment && char === '/' && nextChar === '*') { inBlockComment = true; charIndex++; // 跳过下一个字符 continue; } if (inBlockComment && char === '*' && nextChar === '/') { inBlockComment = false; charIndex++; // 跳过下一个字符 continue; } } // 如果在注释中,跳过所有处理 if (inLineComment || inBlockComment) { continue; } if (!inString) { // 检查字符串开始 if (char === '"' || char === "'") { inString = true; stringChar = char; stringStartPos = new vscode.Position(lineIndex, charIndex); escaped = false; } } else { // 在字符串中 if (escaped) { escaped = false; continue; } if (char === '\\') { escaped = true; continue; } if (char === stringChar) { // 字符串结束 inString = false; stringStartPos = null; stringChar = ''; } } } // 行结束处理 inLineComment = false; // 行注释在行末结束 // 只有在非注释行且有未闭合字符串时才报告错误 if (inString && stringStartPos && stringStartPos.line === lineIndex && !trimmedLine.startsWith('//')) { // 如果字符串在当前行开始但没有结束,报告错误 const range = new vscode.Range(stringStartPos, new vscode.Position(lineIndex, line.length)); const diagnostic = new vscode.Diagnostic(range, `字符串未正确闭合:缺少结束${stringChar === '"' ? '双' : '单'}引号`, vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); // 重置状态,避免后续行都报错 inString = false; stringStartPos = null; } } // 如果文档结束时还有未闭合的字符串,并且不在注释中 if (inString && stringStartPos) { const lastLine = lines.length - 1; const lastLineTrimmed = lines[lastLine].trim(); if (!lastLineTrimmed.startsWith('//')) { const range = new vscode.Range(stringStartPos, new vscode.Position(lastLine, lines[lastLine].length)); const diagnostic = new vscode.Diagnostic(range, `字符串未正确闭合:缺少结束${stringChar === '"' ? '双' : '单'}引号`, vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); } } return diagnostics; } // 检查未闭合的括号(支持多行文档检查) static checkForUnclosedBrackets(document) { const diagnostics = []; const text = document.getText(); // 括号栈,记录每个开括号的位置和类型 const bracketStack = []; const bracketPairs = [ { open: '(', close: ')', name: '圆括号' }, { open: '[', close: ']', name: '方括号' }, { open: '{', close: '}', name: '花括号' } ]; // 状态追踪 let inString = false; let stringChar = ''; let escaped = false; let inLineComment = false; let inBlockComment = false; const lines = text.split('\n'); for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { const line = lines[lineIndex]; // 检查是否整行都是注释(以 // 开头) const trimmedLine = line.trim(); const isCommentLine = trimmedLine.startsWith('//'); for (let charIndex = 0; charIndex < line.length; charIndex++) { const char = line[charIndex]; const nextChar = charIndex < line.length - 1 ? line[charIndex + 1] : ''; // 处理注释 if (!inString) { if (!inBlockComment && char === '/' && nextChar === '/') { inLineComment = true; charIndex++; // 跳过下一个字符 continue; } if (!inLineComment && char === '/' && nextChar === '*') { inBlockComment = true; charIndex++; // 跳过下一个字符 continue; } if (inBlockComment && char === '*' && nextChar === '/') { inBlockComment = false; charIndex++; // 跳过下一个字符 continue; } } // 如果在注释中,跳过所有处理 if (inLineComment || inBlockComment || isCommentLine) { continue; } // 处理字符串状态 if (!inString) { if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; } } else { if (escaped) { escaped = false; continue; } if (char === '\\') { escaped = true; continue; } if (char === stringChar) { inString = false; stringChar = ''; } continue; // 在字符串中,跳过括号检查 } // 检查括号(只在非字符串、非注释中) if (!inString && !inLineComment && !inBlockComment && !isCommentLine) { const openBracket = bracketPairs.find(bp => bp.open === char); if (openBracket) { bracketStack.push({ char: char, position: new vscode.Position(lineIndex, charIndex), name: openBracket.name, inComment: false }); } else { const closeBracket = bracketPairs.find(bp => bp.close === char); if (closeBracket) { if (bracketStack.length === 0) { // 多余的闭合括号 const range = new vscode.Range(new vscode.Position(lineIndex, charIndex), new vscode.Position(lineIndex, charIndex + 1)); const diagnostic = new vscode.Diagnostic(range, `多余的${closeBracket.name}闭合符`, vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); } else { const lastOpen = bracketStack.pop(); const expectedClose = bracketPairs.find(bp => bp.open === lastOpen.char)?.close; if (expectedClose !== char) { // 括号不匹配 const range = new vscode.Range(new vscode.Position(lineIndex, charIndex), new vscode.Position(lineIndex, charIndex + 1)); const diagnostic = new vscode.Diagnostic(range, `括号不匹配:期望 "${expectedClose}" 但找到 "${char}"`, vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); // 也标记未匹配的开括号 const openRange = new vscode.Range(lastOpen.position, new vscode.Position(lastOpen.position.line, lastOpen.position.character + 1)); const openDiagnostic = new vscode.Diagnostic(openRange, `未匹配的${lastOpen.name}`, vscode.DiagnosticSeverity.Error); diagnostics.push(openDiagnostic); } } } } } } // 行结束处理 inLineComment = false; // 行注释在行末结束 } // 检查未闭合的开括号(排除在注释中的括号) bracketStack.forEach(bracket => { if (!bracket.inComment) { const range = new vscode.Range(bracket.position, new vscode.Position(bracket.position.line, bracket.position.character + 1)); const diagnostic = new vscode.Diagnostic(range, `未闭合的${bracket.name}`, vscode.DiagnosticSeverity.Error); diagnostics.push(diagnostic); } }); return diagnostics; } // 检查可能的拼写错误 static checkForPossibleTypos(lineText, lineIndex) { const diagnostics = []; // 跳过空行 const trimmedLine = lineText.trim(); if (trimmedLine.length === 0) { return diagnostics; } // 更完整的Squirrel关键字列表 const squirrelKeywords = [ 'function', 'local', 'if', 'else', 'while', 'for', 'foreach', 'in', 'return', 'break', 'continue', 'class', 'extends', 'constructor', 'null', 'true', 'false', 'try', 'catch', 'throw', 'const', 'enum', 'switch', 'case', 'default', 'delete', 'typeof', 'clone', 'resume', 'yield', 'static', 'this', 'base' ]; // 提取标识符(避免数字、操作符等) const wordPattern = /\b[a-zA-Z_]\w{2,}\b/g; let match; while ((match = wordPattern.exec(lineText)) !== null) { const word = match[0]; const wordLower = word.toLowerCase(); const startIndex = match.index; // 检查这个单词是否在注释或字符串中 if (this.isPositionInCommentOrString(lineText, startIndex)) { continue; } // 跳过已知的关键字(正确拼写) if (squirrelKeywords.includes(wordLower)) { continue; } // 跳过常见的标识符模式(避免误报) if (this.isLikelyValidIdentifier(word)) { continue; } // 检查是否与关键字相似 const similarKeyword = squirrelKeywords.find(keyword => { const distance = this.editDistance(wordLower, keyword); // 只对编辑距离为1-2且长度相近的单词提示 return distance >= 1 && distance <= 2 && Math.abs(word.length - keyword.length) <= 2; }); if (similarKeyword) { const range = new vscode.Range(new vscode.Position(lineIndex, startIndex), new vscode.Position(lineIndex, startIndex + word.length)); const diagnostic = new vscode.Diagnostic(range, `可能的拼写错误:您是否想输入 "${similarKeyword}"?`, vscode.DiagnosticSeverity.Hint); diagnostics.push(diagnostic); } } return diagnostics; } // 检查指定位置是否在注释或字符串中 static isPositionInCommentOrString(line, position) { let inString = false; let stringChar = ''; let escaped = false; let inBlockComment = false; for (let i = 0; i < position && i < line.length; i++) { const char = line[i]; const nextChar = i < line.length - 1 ? line[i + 1] : ''; if (inBlockComment) { if (char === '*' && nextChar === '/') { inBlockComment = false; i++; // 跳过 '/' } continue; } // 检查行注释 if (char === '/' && nextChar === '/') { return true; // 位置在行注释中 } // 检查块注释开始 if (char === '/' && nextChar === '*') { inBlockComment = true; i++; // 跳过 '*' continue; } if (!inString) { if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; } } else { if (escaped) { escaped = false; continue; } if (char === '\\') { escaped = true; continue; } if (char === stringChar) { inString = false; stringChar = ''; } } } return inString || inBlockComment; } // 移除字符串和注释内容,避免对其中的内容进行拼写检查 static removeStringsAndComments(line) { let result = ''; let inString = false; let stringChar = ''; let escaped = false; let inLineComment = false; let inBlockComment = false; for (let i = 0; i < line.length; i++) { const char = line[i]; const nextChar = i < line.length - 1 ? line[i + 1] : ''; // 如果已经在行注释中,所有后续字符都用空格替换 if (inLineComment) { result += ' '; continue; } // 如果已经在块注释中,检查结束标记 if (inBlockComment) { if (char === '*' && nextChar === '/') { inBlockComment = false; result += ' '; // 用空格替换 */ i++; // 跳过下一个字符 } else { result += ' '; // 用空格替换块注释内容 } continue; } if (!inString) { // 检查行注释开始 if (char === '/' && nextChar === '/') { inLineComment = true; result += ' '; // 用空格替换 // i++; // 跳过下一个字符 continue; } // 检查块注释开始 if (char === '/' && nextChar === '*') { inBlockComment = true; result += ' '; // 用空格替换 /* i++; // 跳过下一个字符 continue; } // 检查字符串开始 if (char === '"' || char === "'") { inString = true; stringChar = char; escaped = false; result += ' '; // 用空格替换字符串内容 continue; } } else { // 在字符串中处理转义和结束 if (escaped) { escaped = false; result += ' '; continue; } if (char === '\\') { escaped = true; result += ' '; continue; } if (char === stringChar) { inString = false; stringChar = ''; result += ' '; continue; } result += ' '; // 用空格替换字符串内容 continue; } // 保留非字符串、非注释的字符 result += char; } return result; } // 判断是否是可能的有效标识符(减少误报) static isLikelyValidIdentifier(word) { // 常见的有效标识符模式 const validPatterns = [ /^[A-Z][A-Z_0-9]+$/, // 常量名(全大写) /^[a-z][a-zA-Z0-9]*$/, // 驼峰命名 /^[a-z]+_[a-z0-9_]*$/, // 下划线命名 /^[A-Z][a-zA-Z0-9]*$/, // 帕斯卡命名 /^\w+\d+$/, // 带数字结尾 /^get[A-Z]/, // getter方法 /^set[A-Z]/, // setter方法 /^is[A-Z]/, // 布尔方法 /^has[A-Z]/, // 检查方法 ]; return validPatterns.some(pattern => pattern.test(word)); } // 计算两个字符串之间的编辑距离(Levenshtein距离) static editDistance(str1, str2) { const matrix = []; // 初始化矩阵 for (let i = 0; i <= str2.length; i++) { matrix[i] = [i]; } for (let j = 0; j <= str1.length; j++) { matrix[0][j] = j; } // 填充矩阵 for (let i = 1; i <= str2.length; i++) { for (let j = 1; j <= str1.length; j++) { if (str2.charAt(i - 1) === str1.charAt(j - 1)) { matrix[i][j] = matrix[i - 1][j - 1]; } else { matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // 替换 matrix[i][j - 1] + 1, // 插入 matrix[i - 1][j] + 1 // 删除 ); } } } return matrix[str2.length][str1.length]; } // 实现CodeActionProvider接口 async provideCodeActions(document, range, context, token) { const actions = []; // 为诊断问题提供快速修复 for (const diagnostic of context.diagnostics) { // 拼写错误快速修复 if (diagnostic.message.includes('可能的拼写错误:您是否想输入')) { const match = diagnostic.message.match(/您是否想输入 "([^"]+)"\?/); if (match) { const correctWord = match[1]; const action = new vscode.CodeAction(`将 "${document.getText(diagnostic.range)}" 更正为 "${correctWord}"`, vscode.CodeActionKind.QuickFix); action.edit = new vscode.WorkspaceEdit(); action.edit.replace(document.uri, diagnostic.range, correctWord); action.isPreferred = true; actions.push(action); } } // 明显拼写错误快速修复 else if (diagnostic.message.includes('拼写错误:应该是')) { const match = diagnostic.message.match(/应该是 "([^"]+)" 而不是 "[^"]+"/); if (match) { const correctWord = match[1]; const action = new vscode.CodeAction(`更正拼写为 "${correctWord}"`, vscode.CodeActionKind.QuickFix); action.edit = new vscode.WorkspaceEdit(); action.edit.replace(document.uri, diagnostic.range, correctWord); action.isPreferred = true; actions.push(action); } } // 添加分号快速修复 else if (diagnostic.message.includes('可能缺少分号')) { const action = new vscode.CodeAction('添加分号', vscode.CodeActionKind.QuickFix); action.edit = new vscode.WorkspaceEdit(); const line = document.lineAt(diagnostic.range.start.line); const endPos = new vscode.Position(line.lineNumber, line.text.length); action.edit.insert(document.uri, endPos, ';'); actions.push(action); } // 修复赋值操作符错误 else if (diagnostic.message.includes('使用了赋值操作符 "=" 而不是比较操作符')) { const action = new vscode.CodeAction('将 "=" 更改为 "=="', vscode.CodeActionKind.QuickFix); action.edit = new vscode.WorkspaceEdit(); const text = document.getText(diagnostic.range); const fixedText = text.replace(/([^=])=([^=])/g, '$1==$2'); action.edit.replace(document.uri, diagnostic.range, fixedText); actions.push(action); } } return actions; } } exports.CodeErrorProvider = CodeErrorProvider; //# sourceMappingURL=codeErrorProvider.js.map