1.0.1 代码格式化移植新版
This commit is contained in:
34
copy-beautify-files.js
Normal file
34
copy-beautify-files.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
// 复制 js-beautify 相关文件到 dist 目录
|
||||
async function copyBeautifyFiles() {
|
||||
const srcDir = path.join(__dirname);
|
||||
const destDir = path.join(__dirname, 'dist');
|
||||
|
||||
// 确保目标目录存在
|
||||
await fs.ensureDir(destDir);
|
||||
|
||||
// 复制 js-beautify.js 和包装器
|
||||
const filesToCopy = [
|
||||
'js-beautify.js',
|
||||
'js-beautify-wrapper.js'
|
||||
];
|
||||
|
||||
for (const file of filesToCopy) {
|
||||
const srcPath = path.join(srcDir, file);
|
||||
const destPath = path.join(destDir, file);
|
||||
|
||||
if (await fs.pathExists(srcPath)) {
|
||||
await fs.copy(srcPath, destPath);
|
||||
console.log(`已复制 ${file} 到 dist 目录`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果直接运行此脚本,则执行复制操作
|
||||
if (require.main === module) {
|
||||
copyBeautifyFiles().catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = { copyBeautifyFiles };
|
||||
97
dist/providers/documentFormattingProvider.js
vendored
97
dist/providers/documentFormattingProvider.js
vendored
@@ -35,82 +35,39 @@ var __importStar = (this && this.__importStar) || (function () {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DocumentFormattingProvider = void 0;
|
||||
const vscode = __importStar(require("vscode"));
|
||||
// 文档格式化提供者类
|
||||
const beautifyHelper_1 = require("../utils/beautifyHelper");
|
||||
/**
|
||||
* 文档格式化提供者类 - 使用 js-beautify.js
|
||||
*/
|
||||
class DocumentFormattingProvider {
|
||||
// 提供整个文档的代码格式化功能
|
||||
/**
|
||||
* 提供整个文档的代码格式化功能
|
||||
*/
|
||||
async provideDocumentFormattingEdits(document, options, token) {
|
||||
const edits = [];
|
||||
const lines = [];
|
||||
// 逐行处理文档内容
|
||||
for (let i = 0; i < document.lineCount; i++) {
|
||||
const line = document.lineAt(i);
|
||||
lines.push(line.text);
|
||||
try {
|
||||
// 获取文档全文
|
||||
const fullText = document.getText();
|
||||
// 检查是否是 Squirrel 代码
|
||||
if (!(0, beautifyHelper_1.isSquirrelCode)(fullText)) {
|
||||
return edits; // 如果不是 Squirrel 代码,不应用格式化
|
||||
}
|
||||
// 使用 js-beautify 格式化代码
|
||||
const formattedText = (0, beautifyHelper_1.beautifyCode)(fullText, options);
|
||||
// 如果格式化后的代码与原代码相同,不需要修改
|
||||
if (formattedText === fullText) {
|
||||
return edits;
|
||||
}
|
||||
// 创建编辑操作,替换整个文档
|
||||
const fullRange = new vscode.Range(document.positionAt(0), document.positionAt(fullText.length));
|
||||
edits.push(vscode.TextEdit.replace(fullRange, formattedText));
|
||||
}
|
||||
catch (error) {
|
||||
console.error('文档格式化失败:', error);
|
||||
// 如果格式化失败,返回空编辑数组,保持原代码不变
|
||||
}
|
||||
// 格式化文档
|
||||
const formattedLines = this.formatDocument(lines, options);
|
||||
// 创建编辑操作
|
||||
const fullRange = new vscode.Range(document.positionAt(0), document.positionAt(document.getText().length));
|
||||
edits.push(vscode.TextEdit.replace(fullRange, formattedLines.join('\n')));
|
||||
return edits;
|
||||
}
|
||||
// 格式化文档
|
||||
formatDocument(lines, options) {
|
||||
const formattedLines = [];
|
||||
let indentLevel = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
const trimmedLine = line.trim();
|
||||
if (trimmedLine.length === 0) {
|
||||
// 空行保持原样或删除
|
||||
formattedLines.push('');
|
||||
continue;
|
||||
}
|
||||
// 检查是否需要减少缩进(遇到右大括号等)
|
||||
if (trimmedLine.startsWith('}') || trimmedLine.startsWith(')') || trimmedLine.startsWith(']')) {
|
||||
indentLevel = Math.max(0, indentLevel - 1);
|
||||
}
|
||||
// 添加适当的缩进
|
||||
const indent = this.createIndent(indentLevel, options);
|
||||
const formattedLine = indent + trimmedLine;
|
||||
formattedLines.push(formattedLine);
|
||||
// 检查是否需要增加缩进(遇到左大括号等)
|
||||
if (trimmedLine.endsWith('{') || trimmedLine.endsWith('(') || trimmedLine.endsWith('[')) {
|
||||
indentLevel++;
|
||||
}
|
||||
// 特殊处理else、catch等关键字,它们应该与前面的右大括号在同一行
|
||||
if (trimmedLine.startsWith('else') || trimmedLine.startsWith('catch') || trimmedLine.startsWith('elif')) {
|
||||
if (formattedLines.length > 1) {
|
||||
const prevLine = formattedLines[formattedLines.length - 2];
|
||||
if (prevLine.trim().endsWith('}')) {
|
||||
// 将else等关键字与前面的右大括号放在同一行
|
||||
formattedLines[formattedLines.length - 2] = prevLine.trim() + ' ' + trimmedLine;
|
||||
formattedLines.pop(); // 移除当前行
|
||||
indentLevel--; // 修正缩进级别
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 规范化空格(在操作符周围添加适当空格)
|
||||
return formattedLines.map(line => this.normalizeSpaces(line));
|
||||
}
|
||||
// 在操作符周围添加适当空格
|
||||
normalizeSpaces(line) {
|
||||
// 在常见的操作符周围添加空格
|
||||
return line
|
||||
.replace(/([^\s])(==|!=|<=|>=|<|>|=|\+|-|\*|\/|%)([^\s])/g, '$1 $2 $3')
|
||||
.replace(/([^\s])(,)([^\s])/g, '$1$2 $3')
|
||||
.replace(/\s+/g, ' ') // 将多个空格替换为单个空格
|
||||
.trim();
|
||||
}
|
||||
// 创建指定级别的缩进
|
||||
createIndent(level, options) {
|
||||
if (options.insertSpaces) {
|
||||
return ' '.repeat(level * options.tabSize);
|
||||
}
|
||||
else {
|
||||
return '\t'.repeat(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.DocumentFormattingProvider = DocumentFormattingProvider;
|
||||
//# sourceMappingURL=documentFormattingProvider.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"documentFormattingProvider.js","sourceRoot":"","sources":["../../src/providers/documentFormattingProvider.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"documentFormattingProvider.js","sourceRoot":"","sources":["../../src/providers/documentFormattingProvider.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AACjC,4DAAuE;AAEvE;;GAEG;AACH,MAAa,0BAA0B;IACnC;;OAEG;IACH,KAAK,CAAC,8BAA8B,CAChC,QAA6B,EAC7B,OAAiC,EACjC,KAA+B;QAE/B,MAAM,KAAK,GAAsB,EAAE,CAAC;QAEpC,IAAI,CAAC;YACD,SAAS;YACT,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;YAEpC,oBAAoB;YACpB,IAAI,CAAC,IAAA,+BAAc,EAAC,QAAQ,CAAC,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC,CAAC,0BAA0B;YAC5C,CAAC;YAED,uBAAuB;YACvB,MAAM,aAAa,GAAG,IAAA,6BAAY,EAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAEtD,wBAAwB;YACxB,IAAI,aAAa,KAAK,QAAQ,EAAE,CAAC;gBAC7B,OAAO,KAAK,CAAC;YACjB,CAAC;YAED,gBAAgB;YAChB,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,KAAK,CAC9B,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EACtB,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,CACvC,CAAC;YAEF,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;QAElE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACjC,0BAA0B;QAC9B,CAAC;QAED,OAAO,KAAK,CAAC;IACjB,CAAC;CACJ;AA3CD,gEA2CC"}
|
||||
191
dist/providers/onTypeFormattingProvider.js
vendored
191
dist/providers/onTypeFormattingProvider.js
vendored
@@ -35,115 +35,130 @@ var __importStar = (this && this.__importStar) || (function () {
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OnTypeFormattingProvider = void 0;
|
||||
const vscode = __importStar(require("vscode"));
|
||||
// 输入时格式化提供者类
|
||||
const beautifyHelper_1 = require("../utils/beautifyHelper");
|
||||
/**
|
||||
* 输入时格式化提供者类 - 使用 js-beautify.js
|
||||
*/
|
||||
class OnTypeFormattingProvider {
|
||||
// 在用户输入特定字符时自动格式化代码
|
||||
/**
|
||||
* 在用户输入特定字符时自动格式化代码
|
||||
*/
|
||||
async provideOnTypeFormattingEdits(document, position, ch, options, token) {
|
||||
const edits = [];
|
||||
// 根据输入的字符执行不同的格式化操作
|
||||
switch (ch) {
|
||||
case ')':
|
||||
// 输入右括号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case ';':
|
||||
// 输入分号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case '}':
|
||||
// 输入右大括号时格式化整个代码块
|
||||
edits.push(...this.formatCodeBlock(document, position, options));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
try {
|
||||
// 检查是否是 Squirrel 代码
|
||||
const textBefore = document.getText(new vscode.Range(new vscode.Position(0, 0), position));
|
||||
if (!(0, beautifyHelper_1.isSquirrelCode)(textBefore)) {
|
||||
return edits;
|
||||
}
|
||||
// 根据输入的字符执行不同的格式化操作
|
||||
switch (ch) {
|
||||
case ')':
|
||||
// 输入右括号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case ';':
|
||||
// 输入分号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case '}':
|
||||
// 输入右大括号时格式化整个代码块
|
||||
edits.push(...this.formatCodeBlock(document, position, options));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('输入时格式化失败:', error);
|
||||
}
|
||||
return edits;
|
||||
}
|
||||
// 格式化当前行
|
||||
/**
|
||||
* 使用 js-beautify 格式化当前行
|
||||
*/
|
||||
formatCurrentLine(document, position, options) {
|
||||
const line = document.lineAt(position.line);
|
||||
const trimmedLine = line.text.trim();
|
||||
if (trimmedLine.length === 0) {
|
||||
return [];
|
||||
const edits = [];
|
||||
try {
|
||||
// 获取当前行
|
||||
const line = document.lineAt(position.line);
|
||||
const lineText = line.text;
|
||||
// 获取当前行的上下文(向前几行,向后几行)
|
||||
const startLine = Math.max(0, position.line - 2);
|
||||
const endLine = Math.min(document.lineCount - 1, position.line + 2);
|
||||
const contextText = document.getText(new vscode.Range(new vscode.Position(startLine, 0), new vscode.Position(endLine, document.lineAt(endLine).text.length)));
|
||||
// 使用 js-beautify 格式化代码块
|
||||
const formattedContext = (0, beautifyHelper_1.beautifyCode)(contextText, options);
|
||||
// 比较原始文本和格式化后的文本
|
||||
if (formattedContext === contextText) {
|
||||
return edits; // 没有变化,不需要编辑
|
||||
}
|
||||
// 应用格式化结果
|
||||
const originalLines = contextText.split('\n');
|
||||
const formattedLines = formattedContext.split('\n');
|
||||
for (let i = 0; i < originalLines.length && i < formattedLines.length; i++) {
|
||||
const original = originalLines[i];
|
||||
const formatted = formattedLines[i];
|
||||
if (original !== formatted) {
|
||||
const lineNumber = startLine + i;
|
||||
const range = new vscode.Range(new vscode.Position(lineNumber, 0), new vscode.Position(lineNumber, document.lineAt(lineNumber).text.length));
|
||||
edits.push(vscode.TextEdit.replace(range, formatted));
|
||||
}
|
||||
}
|
||||
}
|
||||
// 简单的格式化:确保行尾没有多余空格
|
||||
if (line.text !== trimmedLine && !line.text.endsWith(' ')) {
|
||||
const range = new vscode.Range(new vscode.Position(position.line, 0), new vscode.Position(position.line, line.text.length));
|
||||
return [vscode.TextEdit.replace(range, trimmedLine)];
|
||||
catch (error) {
|
||||
console.error('格式化当前行失败:', error);
|
||||
}
|
||||
return [];
|
||||
return edits;
|
||||
}
|
||||
// 格式化代码块
|
||||
/**
|
||||
* 使用 js-beautify 格式化代码块
|
||||
*/
|
||||
formatCodeBlock(document, position, options) {
|
||||
const edits = [];
|
||||
const line = document.lineAt(position.line);
|
||||
// 查找匹配的左大括号
|
||||
let braceCount = 1;
|
||||
let blockStartLine = -1;
|
||||
for (let i = position.line - 1; i >= 0; i--) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const lineText = currentLine.text;
|
||||
for (let j = lineText.length - 1; j >= 0; j--) {
|
||||
if (lineText[j] === '}') {
|
||||
braceCount++;
|
||||
}
|
||||
else if (lineText[j] === '{') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
blockStartLine = i;
|
||||
break;
|
||||
try {
|
||||
// 查找匹配的左大括号
|
||||
let braceCount = 1;
|
||||
let blockStartLine = -1;
|
||||
for (let i = position.line - 1; i >= 0; i--) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const lineText = currentLine.text;
|
||||
for (let j = lineText.length - 1; j >= 0; j--) {
|
||||
if (lineText[j] === '}') {
|
||||
braceCount++;
|
||||
}
|
||||
else if (lineText[j] === '{') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
blockStartLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (blockStartLine !== -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (blockStartLine !== -1) {
|
||||
break;
|
||||
// 获取代码块的范围
|
||||
const endLine = position.line;
|
||||
const blockText = document.getText(new vscode.Range(new vscode.Position(blockStartLine, 0), new vscode.Position(endLine + 1, 0) // 包含右大括号行
|
||||
));
|
||||
// 使用 js-beautify 格式化代码块
|
||||
const formattedBlock = (0, beautifyHelper_1.beautifyCode)(blockText, options);
|
||||
if (formattedBlock === blockText) {
|
||||
return edits; // 没有变化
|
||||
}
|
||||
// 应用格式化结果
|
||||
const range = new vscode.Range(new vscode.Position(blockStartLine, 0), new vscode.Position(endLine + 1, 0));
|
||||
edits.push(vscode.TextEdit.replace(range, formattedBlock));
|
||||
}
|
||||
}
|
||||
if (blockStartLine !== -1) {
|
||||
// 调整代码块的缩进
|
||||
const startLine = document.lineAt(blockStartLine);
|
||||
const startIndent = this.getIndentLevel(startLine.text);
|
||||
for (let i = blockStartLine + 1; i < position.line; i++) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const currentIndent = this.getIndentLevel(currentLine.text);
|
||||
if (currentIndent < startIndent + 1) {
|
||||
const newIndent = this.createIndent(startIndent + 1, options);
|
||||
const range = new vscode.Range(new vscode.Position(i, 0), new vscode.Position(i, currentIndent));
|
||||
edits.push(vscode.TextEdit.replace(range, newIndent));
|
||||
}
|
||||
}
|
||||
// 调整右大括号的缩进
|
||||
const endIndent = this.createIndent(startIndent, options);
|
||||
const endRange = new vscode.Range(new vscode.Position(position.line, 0), new vscode.Position(position.line, this.getIndentLevel(line.text)));
|
||||
edits.push(vscode.TextEdit.replace(endRange, endIndent));
|
||||
catch (error) {
|
||||
console.error('格式化代码块失败:', error);
|
||||
}
|
||||
return edits;
|
||||
}
|
||||
// 获取行的缩进级别
|
||||
getIndentLevel(line) {
|
||||
let indent = 0;
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
if (line[i] === ' ') {
|
||||
indent++;
|
||||
}
|
||||
else if (line[i] === '\t') {
|
||||
indent += 4; // 假设一个tab等于4个空格
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return indent;
|
||||
}
|
||||
// 创建指定级别的缩进
|
||||
createIndent(level, options) {
|
||||
if (options.insertSpaces) {
|
||||
return ' '.repeat(level);
|
||||
}
|
||||
else {
|
||||
return '\t'.repeat(Math.floor(level / 4)); // 假设一个tab等于4个空格
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.OnTypeFormattingProvider = OnTypeFormattingProvider;
|
||||
//# sourceMappingURL=onTypeFormattingProvider.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"onTypeFormattingProvider.js","sourceRoot":"","sources":["../../src/providers/onTypeFormattingProvider.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"onTypeFormattingProvider.js","sourceRoot":"","sources":["../../src/providers/onTypeFormattingProvider.ts"],"names":[],"mappings":"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"}
|
||||
201
dist/utils/beautifyHelper.js
vendored
Normal file
201
dist/utils/beautifyHelper.js
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getSquirrelBeautifyOptions = getSquirrelBeautifyOptions;
|
||||
exports.beautifyCode = beautifyCode;
|
||||
exports.isSquirrelCode = isSquirrelCode;
|
||||
// 由于 js-beautify.js 文件体积较大且复杂,我们将创建专门的存根函数
|
||||
// 将使用原生的 js-beautify 功能
|
||||
let _jsBeauifyInstance = null;
|
||||
/**
|
||||
* 动态创建 js_beautify 函数
|
||||
*/
|
||||
function createJsBeautify() {
|
||||
if (_jsBeauifyInstance) {
|
||||
return _jsBeauifyInstance;
|
||||
}
|
||||
try {
|
||||
// 加载原始的 js-beautify.js 文件
|
||||
const beautifyModule = loadJsBeautify();
|
||||
_jsBeauifyInstance = beautifyModule;
|
||||
return _jsBeauifyInstance;
|
||||
}
|
||||
catch (error) {
|
||||
console.error('加载 js-beautify 失败,使用后备实现:', error);
|
||||
// 调用后备实现
|
||||
return createBasicJsBeautify();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 加载 js-beautify 模块
|
||||
*/
|
||||
function loadJsBeautify() {
|
||||
// 根据环境动态加载
|
||||
try {
|
||||
// 尝试 require 原始的 js-beautify.js 文件
|
||||
// 注意:TypeScript 会从 ./dist 目录运行,所以需要从正确的路径加载
|
||||
const beautifyPath = __dirname + '/../../js-beautify.js';
|
||||
const Module = require('module');
|
||||
const vm = require('vm');
|
||||
const fs = require('fs');
|
||||
// 读取文件内容
|
||||
const code = fs.readFileSync(beautifyPath, 'utf8');
|
||||
// 设置全局环境
|
||||
const sandbox = {
|
||||
window: {},
|
||||
global: {},
|
||||
console: console,
|
||||
String: String,
|
||||
Array: Array,
|
||||
Object: Object,
|
||||
Math: Math
|
||||
};
|
||||
// 在沙箱中执行代码
|
||||
const script = new vm.Script(code);
|
||||
const context = vm.createContext(sandbox);
|
||||
script.runInContext(context);
|
||||
// 获取 js_beautify 函数
|
||||
return context.window.js_beautify || context.js_beautify || sandbox.window.js_beautify;
|
||||
}
|
||||
catch (loadError) {
|
||||
console.error('无法加载原始 js-beautify, 错误:', loadError);
|
||||
throw loadError;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 基础的 js-beautify 实现(后备方案)
|
||||
*/
|
||||
function createBasicJsBeautify() {
|
||||
return function (code, options = {}) {
|
||||
// 默认选项
|
||||
const defaultOptions = {
|
||||
indent_size: 4,
|
||||
indent_char: ' ',
|
||||
preserve_newlines: true,
|
||||
brace_style: 'collapse',
|
||||
space_before_conditional: true,
|
||||
space_after_anon_function: false,
|
||||
wrap_line_length: 120,
|
||||
end_with_newline: false
|
||||
};
|
||||
// 合并选项
|
||||
const opts = { ...defaultOptions, ...options };
|
||||
// 简化的代码美化实现
|
||||
let formatted = code;
|
||||
// 清理缩进
|
||||
formatted = formatted.replace(/[\r\n]+/g, '\n');
|
||||
const lines = formatted.split('\n');
|
||||
const result = [];
|
||||
let indentLevel = 0;
|
||||
const indentStr = opts.indent_char.repeat(opts.indent_size);
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
// 跳过空行
|
||||
if (trimmed.length === 0) {
|
||||
result.push('');
|
||||
continue;
|
||||
}
|
||||
// 处理大括号
|
||||
if (trimmed.startsWith('}') || trimmed.startsWith(')') || trimmed.startsWith(']')) {
|
||||
indentLevel = Math.max(0, indentLevel - 1);
|
||||
}
|
||||
// 添加缩进
|
||||
const indentedLine = indentStr.repeat(indentLevel) + trimmed;
|
||||
result.push(indentedLine);
|
||||
// 增加缩进
|
||||
if (trimmed.endsWith('{') || trimmed.endsWith('(') || trimmed.endsWith('[')) {
|
||||
indentLevel++;
|
||||
}
|
||||
// 特殊处理 else、catch 等关键字
|
||||
if (trimmed.startsWith('else') || trimmed.startsWith('catch') || trimmed.startsWith('elif')) {
|
||||
// 检查前面一行是否以 } 结尾
|
||||
if (result.length > 1) {
|
||||
const prevLine = result[result.length - 2];
|
||||
const prevTrimmed = prevLine.trim();
|
||||
if (prevTrimmed.endsWith('}')) {
|
||||
// 移动到前一行的必要部分
|
||||
result[result.length - 2] = indentStr.repeat(indentLevel - 1) +
|
||||
prevTrimmed + ' ' + trimmed;
|
||||
result.pop(); // 移除当前行
|
||||
indentLevel--; // 修正缩进级别
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let finalResult = result.join('\n');
|
||||
// 处理空格 - 在操作符周围添加空格
|
||||
finalResult = finalResult
|
||||
.replace(/([a-zA-Z0-9_$])([=!<>+\-*/%])([a-zA-Z0-9_$])/g, '$1 $2 $3')
|
||||
.replace(/([a-zA-Z0-9_$])(,)([a-zA-Z0-9_$])/g, '$1$2 $3')
|
||||
.replace(/\s+/g, ' ') // 将多个空格替换为单个空格
|
||||
.trim();
|
||||
return finalResult;
|
||||
};
|
||||
}
|
||||
// 初始化 js_beautify
|
||||
const jsBeautify = {
|
||||
js_beautify: createJsBeautify()
|
||||
};
|
||||
/**
|
||||
* Squirrel 语言的 js-beautify 选项配置
|
||||
*/
|
||||
function getSquirrelBeautifyOptions(options) {
|
||||
return {
|
||||
indent_size: options.tabSize,
|
||||
indent_char: options.insertSpaces ? ' ' : '\t',
|
||||
preserve_newlines: true,
|
||||
max_preserve_newlines: 2,
|
||||
jslint_happy: false,
|
||||
brace_style: "collapse",
|
||||
space_before_conditional: true,
|
||||
space_after_anon_function: false,
|
||||
unescape_strings: false,
|
||||
wrap_line_length: 120,
|
||||
end_with_newline: false
|
||||
};
|
||||
}
|
||||
/**
|
||||
* 使用 js-beautify 格式化代码
|
||||
*/
|
||||
function beautifyCode(code, options) {
|
||||
if (!jsBeautify || !jsBeautify.js_beautify) {
|
||||
console.warn('js-beautify 不可用,返回原始代码');
|
||||
return code;
|
||||
}
|
||||
try {
|
||||
const beautifyOptions = getSquirrelBeautifyOptions(options);
|
||||
// 检查代码长度,处理大块代码
|
||||
const maxChunkSize = 50000; // 50KB 每块
|
||||
if (code.length > maxChunkSize) {
|
||||
// 分割代码并分块处理
|
||||
const chunks = code.split('\n');
|
||||
const resultChunks = [];
|
||||
for (const chunk of chunks) {
|
||||
const formattedChunk = jsBeautify.js_beautify(chunk, beautifyOptions);
|
||||
resultChunks.push(formattedChunk);
|
||||
}
|
||||
return resultChunks.join('\n');
|
||||
}
|
||||
// 直接格式化小代码块
|
||||
return jsBeautify.js_beautify(code, beautifyOptions);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('js-beautify 格式化失败:', error);
|
||||
// 如果格式化失败,返回原始代码
|
||||
return code;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 检测是否为 Squirrel 代码(用于确定是否应用格式化)
|
||||
*/
|
||||
function isSquirrelCode(code) {
|
||||
// 简单的启发式检测 - Squirrel 特有关键字
|
||||
const squirrelKeywords = [
|
||||
'function', 'local', 'if', 'else', 'while', 'for', 'foreach',
|
||||
'class', 'constructor', 'extends', 'instanceof', 'in',
|
||||
'try', 'catch', 'throw', 'clone', 'delegate', 'resume', 'yield',
|
||||
'typeof', 'member', 'rawcall', 'call', 'setdebughook'
|
||||
];
|
||||
// 提高检测准确性 - 需要至少匹配到1个关键字
|
||||
return squirrelKeywords.some(keyword => new RegExp(`\\b${keyword}\\b`).test(code));
|
||||
}
|
||||
//# sourceMappingURL=beautifyHelper.js.map
|
||||
1
dist/utils/beautifyHelper.js.map
vendored
Normal file
1
dist/utils/beautifyHelper.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
44
js-beautify-wrapper-fixed.js
Normal file
44
js-beautify-wrapper-fixed.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 因为 js-beautify.js 直接在全局作用域定义 js_beautify,
|
||||
// 我们可以直接使用 require 来引入并获取函数
|
||||
|
||||
// 特别注意:js-beautify.js 假设需要 window 或 global 对象
|
||||
// Node.js 环境下,我们需要将 js_beautify 挂载到全局
|
||||
|
||||
let js_beautify;
|
||||
|
||||
// 读取并执行 js-beautify.js
|
||||
const beautifyPath = path.join(__dirname, 'js-beautify.js');
|
||||
const beautifyCode = fs.readFileSync(beautifyPath, 'utf-8');
|
||||
|
||||
// 创建一个安全的沙箱环境
|
||||
global.window = global;
|
||||
global.module = undefined;
|
||||
global.exports = undefined;
|
||||
|
||||
// 执行代码
|
||||
try {
|
||||
eval(beautifyCode);
|
||||
js_beautify = global.js_beautify;
|
||||
} catch (error) {
|
||||
console.error('加载 js-beautify.js 失败:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// 清理全局变量
|
||||
delete global.window;
|
||||
|
||||
// 如果 js_beautify 没有挂载到 global,尝试从 globalThis 获取
|
||||
if (!js_beautify && globalThis.js_beautify) {
|
||||
js_beautify = globalThis.js_beautify;
|
||||
}
|
||||
|
||||
if (!js_beautify) {
|
||||
throw new Error('无法从 js-beautify.js 中找到 js_beautify 函数');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
js_beautify: js_beautify
|
||||
};
|
||||
15
js-beautify-wrapper.js
Normal file
15
js-beautify-wrapper.js
Normal file
@@ -0,0 +1,15 @@
|
||||
// js-beautify.js 的 CommonJS 包装器
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 读取原始 js-beautify.js 文件内容
|
||||
const beautifyPath = path.join(__dirname, 'js-beautify.js');
|
||||
const beautifyContent = fs.readFileSync(beautifyPath, 'utf-8');
|
||||
|
||||
// 执行文件内容,确保 js_beautify 函数可用
|
||||
eval(beautifyContent);
|
||||
|
||||
// 模块导出 js_beautify 函数
|
||||
module.exports = {
|
||||
js_beautify: global.js_beautify || js_beautify
|
||||
};
|
||||
2
node_modules/.package-lock.json
generated
vendored
2
node_modules/.package-lock.json
generated
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "squirrel-nut-explorer",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "squirrel-nut-explorer",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "squirrel-nut-explorer",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.19.11",
|
||||
"@types/vscode": "^1.99.0",
|
||||
|
||||
BIN
squirrel-nut-explorer-1.0.0.vsix
Normal file
BIN
squirrel-nut-explorer-1.0.0.vsix
Normal file
Binary file not shown.
@@ -1,100 +1,50 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { beautifyCode, isSquirrelCode } from '../utils/beautifyHelper';
|
||||
|
||||
// 文档格式化提供者类
|
||||
/**
|
||||
* 文档格式化提供者类 - 使用 js-beautify.js
|
||||
*/
|
||||
export class DocumentFormattingProvider implements vscode.DocumentFormattingEditProvider {
|
||||
// 提供整个文档的代码格式化功能
|
||||
/**
|
||||
* 提供整个文档的代码格式化功能
|
||||
*/
|
||||
async provideDocumentFormattingEdits(
|
||||
document: vscode.TextDocument,
|
||||
options: vscode.FormattingOptions,
|
||||
token: vscode.CancellationToken
|
||||
): Promise<vscode.TextEdit[]> {
|
||||
const edits: vscode.TextEdit[] = [];
|
||||
const lines: string[] = [];
|
||||
|
||||
// 逐行处理文档内容
|
||||
for (let i = 0; i < document.lineCount; i++) {
|
||||
const line = document.lineAt(i);
|
||||
lines.push(line.text);
|
||||
try {
|
||||
// 获取文档全文
|
||||
const fullText = document.getText();
|
||||
|
||||
// 检查是否是 Squirrel 代码
|
||||
if (!isSquirrelCode(fullText)) {
|
||||
return edits; // 如果不是 Squirrel 代码,不应用格式化
|
||||
}
|
||||
|
||||
// 使用 js-beautify 格式化代码
|
||||
const formattedText = beautifyCode(fullText, options);
|
||||
|
||||
// 如果格式化后的代码与原代码相同,不需要修改
|
||||
if (formattedText === fullText) {
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 创建编辑操作,替换整个文档
|
||||
const fullRange = new vscode.Range(
|
||||
document.positionAt(0),
|
||||
document.positionAt(fullText.length)
|
||||
);
|
||||
|
||||
edits.push(vscode.TextEdit.replace(fullRange, formattedText));
|
||||
|
||||
} catch (error) {
|
||||
console.error('文档格式化失败:', error);
|
||||
// 如果格式化失败,返回空编辑数组,保持原代码不变
|
||||
}
|
||||
|
||||
// 格式化文档
|
||||
const formattedLines = this.formatDocument(lines, options);
|
||||
|
||||
// 创建编辑操作
|
||||
const fullRange = new vscode.Range(
|
||||
document.positionAt(0),
|
||||
document.positionAt(document.getText().length)
|
||||
);
|
||||
|
||||
edits.push(vscode.TextEdit.replace(fullRange, formattedLines.join('\n')));
|
||||
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 格式化文档
|
||||
private formatDocument(lines: string[], options: vscode.FormattingOptions): string[] {
|
||||
const formattedLines: string[] = [];
|
||||
let indentLevel = 0;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i];
|
||||
const trimmedLine = line.trim();
|
||||
|
||||
if (trimmedLine.length === 0) {
|
||||
// 空行保持原样或删除
|
||||
formattedLines.push('');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查是否需要减少缩进(遇到右大括号等)
|
||||
if (trimmedLine.startsWith('}') || trimmedLine.startsWith(')') || trimmedLine.startsWith(']')) {
|
||||
indentLevel = Math.max(0, indentLevel - 1);
|
||||
}
|
||||
|
||||
// 添加适当的缩进
|
||||
const indent = this.createIndent(indentLevel, options);
|
||||
const formattedLine = indent + trimmedLine;
|
||||
formattedLines.push(formattedLine);
|
||||
|
||||
// 检查是否需要增加缩进(遇到左大括号等)
|
||||
if (trimmedLine.endsWith('{') || trimmedLine.endsWith('(') || trimmedLine.endsWith('[')) {
|
||||
indentLevel++;
|
||||
}
|
||||
|
||||
// 特殊处理else、catch等关键字,它们应该与前面的右大括号在同一行
|
||||
if (trimmedLine.startsWith('else') || trimmedLine.startsWith('catch') || trimmedLine.startsWith('elif')) {
|
||||
if (formattedLines.length > 1) {
|
||||
const prevLine = formattedLines[formattedLines.length - 2];
|
||||
if (prevLine.trim().endsWith('}')) {
|
||||
// 将else等关键字与前面的右大括号放在同一行
|
||||
formattedLines[formattedLines.length - 2] = prevLine.trim() + ' ' + trimmedLine;
|
||||
formattedLines.pop(); // 移除当前行
|
||||
indentLevel--; // 修正缩进级别
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 规范化空格(在操作符周围添加适当空格)
|
||||
return formattedLines.map(line => this.normalizeSpaces(line));
|
||||
}
|
||||
|
||||
// 在操作符周围添加适当空格
|
||||
private normalizeSpaces(line: string): string {
|
||||
// 在常见的操作符周围添加空格
|
||||
return line
|
||||
.replace(/([^\s])(==|!=|<=|>=|<|>|=|\+|-|\*|\/|%)([^\s])/g, '$1 $2 $3')
|
||||
.replace(/([^\s])(,)([^\s])/g, '$1$2 $3')
|
||||
.replace(/\s+/g, ' ') // 将多个空格替换为单个空格
|
||||
.trim();
|
||||
}
|
||||
|
||||
// 创建指定级别的缩进
|
||||
private createIndent(level: number, options: vscode.FormattingOptions): string {
|
||||
if (options.insertSpaces) {
|
||||
return ' '.repeat(level * options.tabSize);
|
||||
} else {
|
||||
return '\t'.repeat(level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,13 @@
|
||||
import * as vscode from 'vscode';
|
||||
import { beautifyCode, isSquirrelCode } from '../utils/beautifyHelper';
|
||||
|
||||
// 输入时格式化提供者类
|
||||
/**
|
||||
* 输入时格式化提供者类 - 使用 js-beautify.js
|
||||
*/
|
||||
export class OnTypeFormattingProvider implements vscode.OnTypeFormattingEditProvider {
|
||||
// 在用户输入特定字符时自动格式化代码
|
||||
/**
|
||||
* 在用户输入特定字符时自动格式化代码
|
||||
*/
|
||||
async provideOnTypeFormattingEdits(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
@@ -12,138 +17,162 @@ export class OnTypeFormattingProvider implements vscode.OnTypeFormattingEditProv
|
||||
): Promise<vscode.TextEdit[]> {
|
||||
const edits: vscode.TextEdit[] = [];
|
||||
|
||||
// 根据输入的字符执行不同的格式化操作
|
||||
switch (ch) {
|
||||
case ')':
|
||||
// 输入右括号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case ';':
|
||||
// 输入分号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case '}':
|
||||
// 输入右大括号时格式化整个代码块
|
||||
edits.push(...this.formatCodeBlock(document, position, options));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
try {
|
||||
// 检查是否是 Squirrel 代码
|
||||
const textBefore = document.getText(new vscode.Range(new vscode.Position(0, 0), position));
|
||||
if (!isSquirrelCode(textBefore)) {
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 根据输入的字符执行不同的格式化操作
|
||||
switch (ch) {
|
||||
case ')':
|
||||
// 输入右括号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case ';':
|
||||
// 输入分号时格式化当前行
|
||||
edits.push(...this.formatCurrentLine(document, position, options));
|
||||
break;
|
||||
case '}':
|
||||
// 输入右大括号时格式化整个代码块
|
||||
edits.push(...this.formatCodeBlock(document, position, options));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('输入时格式化失败:', error);
|
||||
}
|
||||
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 格式化当前行
|
||||
/**
|
||||
* 使用 js-beautify 格式化当前行
|
||||
*/
|
||||
private formatCurrentLine(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
options: vscode.FormattingOptions
|
||||
): vscode.TextEdit[] {
|
||||
const line = document.lineAt(position.line);
|
||||
const trimmedLine = line.text.trim();
|
||||
const edits: vscode.TextEdit[] = [];
|
||||
|
||||
if (trimmedLine.length === 0) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
// 获取当前行
|
||||
const line = document.lineAt(position.line);
|
||||
const lineText = line.text;
|
||||
|
||||
// 简单的格式化:确保行尾没有多余空格
|
||||
if (line.text !== trimmedLine && !line.text.endsWith(' ')) {
|
||||
const range = new vscode.Range(
|
||||
new vscode.Position(position.line, 0),
|
||||
new vscode.Position(position.line, line.text.length)
|
||||
// 获取当前行的上下文(向前几行,向后几行)
|
||||
const startLine = Math.max(0, position.line - 2);
|
||||
const endLine = Math.min(document.lineCount - 1, position.line + 2);
|
||||
|
||||
const contextText = document.getText(
|
||||
new vscode.Range(
|
||||
new vscode.Position(startLine, 0),
|
||||
new vscode.Position(endLine, document.lineAt(endLine).text.length)
|
||||
)
|
||||
);
|
||||
return [vscode.TextEdit.replace(range, trimmedLine)];
|
||||
|
||||
// 使用 js-beautify 格式化代码块
|
||||
const formattedContext = beautifyCode(contextText, options);
|
||||
|
||||
// 比较原始文本和格式化后的文本
|
||||
if (formattedContext === contextText) {
|
||||
return edits; // 没有变化,不需要编辑
|
||||
}
|
||||
|
||||
// 应用格式化结果
|
||||
const originalLines = contextText.split('\n');
|
||||
const formattedLines = formattedContext.split('\n');
|
||||
|
||||
for (let i = 0; i < originalLines.length && i < formattedLines.length; i++) {
|
||||
const original = originalLines[i];
|
||||
const formatted = formattedLines[i];
|
||||
|
||||
if (original !== formatted) {
|
||||
const lineNumber = startLine + i;
|
||||
const range = new vscode.Range(
|
||||
new vscode.Position(lineNumber, 0),
|
||||
new vscode.Position(lineNumber, document.lineAt(lineNumber).text.length)
|
||||
);
|
||||
edits.push(vscode.TextEdit.replace(range, formatted));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('格式化当前行失败:', error);
|
||||
}
|
||||
|
||||
return [];
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 格式化代码块
|
||||
/**
|
||||
* 使用 js-beautify 格式化代码块
|
||||
*/
|
||||
private formatCodeBlock(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
options: vscode.FormattingOptions
|
||||
): vscode.TextEdit[] {
|
||||
const edits: vscode.TextEdit[] = [];
|
||||
const line = document.lineAt(position.line);
|
||||
|
||||
// 查找匹配的左大括号
|
||||
let braceCount = 1;
|
||||
let blockStartLine = -1;
|
||||
try {
|
||||
// 查找匹配的左大括号
|
||||
let braceCount = 1;
|
||||
let blockStartLine = -1;
|
||||
|
||||
for (let i = position.line - 1; i >= 0; i--) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const lineText = currentLine.text;
|
||||
for (let i = position.line - 1; i >= 0; i--) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const lineText = currentLine.text;
|
||||
|
||||
for (let j = lineText.length - 1; j >= 0; j--) {
|
||||
if (lineText[j] === '}') {
|
||||
braceCount++;
|
||||
} else if (lineText[j] === '{') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
blockStartLine = i;
|
||||
break;
|
||||
for (let j = lineText.length - 1; j >= 0; j--) {
|
||||
if (lineText[j] === '}') {
|
||||
braceCount++;
|
||||
} else if (lineText[j] === '{') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
blockStartLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (blockStartLine !== -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (blockStartLine !== -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 获取代码块的范围
|
||||
const endLine = position.line;
|
||||
const blockText = document.getText(
|
||||
new vscode.Range(
|
||||
new vscode.Position(blockStartLine, 0),
|
||||
new vscode.Position(endLine + 1, 0) // 包含右大括号行
|
||||
)
|
||||
);
|
||||
|
||||
if (blockStartLine !== -1) {
|
||||
// 调整代码块的缩进
|
||||
const startLine = document.lineAt(blockStartLine);
|
||||
const startIndent = this.getIndentLevel(startLine.text);
|
||||
// 使用 js-beautify 格式化代码块
|
||||
const formattedBlock = beautifyCode(blockText, options);
|
||||
|
||||
for (let i = blockStartLine + 1; i < position.line; i++) {
|
||||
const currentLine = document.lineAt(i);
|
||||
const currentIndent = this.getIndentLevel(currentLine.text);
|
||||
|
||||
if (currentIndent < startIndent + 1) {
|
||||
const newIndent = this.createIndent(startIndent + 1, options);
|
||||
const range = new vscode.Range(
|
||||
new vscode.Position(i, 0),
|
||||
new vscode.Position(i, currentIndent)
|
||||
);
|
||||
edits.push(vscode.TextEdit.replace(range, newIndent));
|
||||
if (formattedBlock === blockText) {
|
||||
return edits; // 没有变化
|
||||
}
|
||||
|
||||
// 应用格式化结果
|
||||
const range = new vscode.Range(
|
||||
new vscode.Position(blockStartLine, 0),
|
||||
new vscode.Position(endLine + 1, 0)
|
||||
);
|
||||
edits.push(vscode.TextEdit.replace(range, formattedBlock));
|
||||
}
|
||||
|
||||
// 调整右大括号的缩进
|
||||
const endIndent = this.createIndent(startIndent, options);
|
||||
const endRange = new vscode.Range(
|
||||
new vscode.Position(position.line, 0),
|
||||
new vscode.Position(position.line, this.getIndentLevel(line.text))
|
||||
);
|
||||
edits.push(vscode.TextEdit.replace(endRange, endIndent));
|
||||
} catch (error) {
|
||||
console.error('格式化代码块失败:', error);
|
||||
}
|
||||
|
||||
return edits;
|
||||
}
|
||||
|
||||
// 获取行的缩进级别
|
||||
private getIndentLevel(line: string): number {
|
||||
let indent = 0;
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
if (line[i] === ' ') {
|
||||
indent++;
|
||||
} else if (line[i] === '\t') {
|
||||
indent += 4; // 假设一个tab等于4个空格
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return indent;
|
||||
}
|
||||
|
||||
// 创建指定级别的缩进
|
||||
private createIndent(level: number, options: vscode.FormattingOptions): string {
|
||||
if (options.insertSpaces) {
|
||||
return ' '.repeat(level);
|
||||
} else {
|
||||
return '\t'.repeat(Math.floor(level / 4)); // 假设一个tab等于4个空格
|
||||
}
|
||||
}
|
||||
}
|
||||
228
src/utils/beautifyHelper.ts
Normal file
228
src/utils/beautifyHelper.ts
Normal file
@@ -0,0 +1,228 @@
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
// 由于 js-beautify.js 文件体积较大且复杂,我们将创建专门的存根函数
|
||||
// 将使用原生的 js-beautify 功能
|
||||
|
||||
let _jsBeauifyInstance: any = null;
|
||||
|
||||
/**
|
||||
* 动态创建 js_beautify 函数
|
||||
*/
|
||||
function createJsBeautify(): any {
|
||||
if (_jsBeauifyInstance) {
|
||||
return _jsBeauifyInstance;
|
||||
}
|
||||
|
||||
try {
|
||||
// 加载原始的 js-beautify.js 文件
|
||||
const beautifyModule = loadJsBeautify();
|
||||
_jsBeauifyInstance = beautifyModule;
|
||||
return _jsBeauifyInstance;
|
||||
} catch (error) {
|
||||
console.error('加载 js-beautify 失败,使用后备实现:', error);
|
||||
// 调用后备实现
|
||||
return createBasicJsBeautify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载 js-beautify 模块
|
||||
*/
|
||||
function loadJsBeautify(): any {
|
||||
// 根据环境动态加载
|
||||
try {
|
||||
// 尝试 require 原始的 js-beautify.js 文件
|
||||
// 注意:TypeScript 会从 ./dist 目录运行,所以需要从正确的路径加载
|
||||
const beautifyPath = __dirname + '/../../js-beautify.js';
|
||||
const Module = require('module');
|
||||
const vm = require('vm');
|
||||
const fs = require('fs');
|
||||
|
||||
// 读取文件内容
|
||||
const code = fs.readFileSync(beautifyPath, 'utf8');
|
||||
|
||||
// 设置全局环境
|
||||
const sandbox: any = {
|
||||
window: {},
|
||||
global: {},
|
||||
console: console,
|
||||
String: String,
|
||||
Array: Array,
|
||||
Object: Object,
|
||||
Math: Math
|
||||
};
|
||||
|
||||
// 在沙箱中执行代码
|
||||
const script = new vm.Script(code);
|
||||
const context = vm.createContext(sandbox);
|
||||
script.runInContext(context);
|
||||
|
||||
// 获取 js_beautify 函数
|
||||
return context.window.js_beautify || context.js_beautify || sandbox.window.js_beautify;
|
||||
} catch (loadError) {
|
||||
console.error('无法加载原始 js-beautify, 错误:', loadError);
|
||||
throw loadError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 基础的 js-beautify 实现(后备方案)
|
||||
*/
|
||||
function createBasicJsBeautify(): any {
|
||||
return function(code: string, options: any = {}): string {
|
||||
// 默认选项
|
||||
const defaultOptions = {
|
||||
indent_size: 4,
|
||||
indent_char: ' ',
|
||||
preserve_newlines: true,
|
||||
brace_style: 'collapse',
|
||||
space_before_conditional: true,
|
||||
space_after_anon_function: false,
|
||||
wrap_line_length: 120,
|
||||
end_with_newline: false
|
||||
};
|
||||
|
||||
// 合并选项
|
||||
const opts = { ...defaultOptions, ...options };
|
||||
|
||||
// 简化的代码美化实现
|
||||
let formatted = code;
|
||||
|
||||
// 清理缩进
|
||||
formatted = formatted.replace(/[\r\n]+/g, '\n');
|
||||
|
||||
const lines = formatted.split('\n');
|
||||
const result: string[] = [];
|
||||
let indentLevel = 0;
|
||||
const indentStr = opts.indent_char.repeat(opts.indent_size);
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
|
||||
// 跳过空行
|
||||
if (trimmed.length === 0) {
|
||||
result.push('');
|
||||
continue;
|
||||
}
|
||||
|
||||
// 处理大括号
|
||||
if (trimmed.startsWith('}') || trimmed.startsWith(')') || trimmed.startsWith(']')) {
|
||||
indentLevel = Math.max(0, indentLevel - 1);
|
||||
}
|
||||
|
||||
// 添加缩进
|
||||
const indentedLine = indentStr.repeat(indentLevel) + trimmed;
|
||||
result.push(indentedLine);
|
||||
|
||||
// 增加缩进
|
||||
if (trimmed.endsWith('{') || trimmed.endsWith('(') || trimmed.endsWith('[')) {
|
||||
indentLevel++;
|
||||
}
|
||||
|
||||
// 特殊处理 else、catch 等关键字
|
||||
if (trimmed.startsWith('else') || trimmed.startsWith('catch') || trimmed.startsWith('elif')) {
|
||||
// 检查前面一行是否以 } 结尾
|
||||
if (result.length > 1) {
|
||||
const prevLine = result[result.length - 2];
|
||||
const prevTrimmed = prevLine.trim();
|
||||
if (prevTrimmed.endsWith('}')) {
|
||||
// 移动到前一行的必要部分
|
||||
result[result.length - 2] = indentStr.repeat(indentLevel - 1) +
|
||||
prevTrimmed + ' ' + trimmed;
|
||||
result.pop(); // 移除当前行
|
||||
indentLevel--; // 修正缩进级别
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let finalResult = result.join('\n');
|
||||
|
||||
// 处理空格 - 在操作符周围添加空格
|
||||
finalResult = finalResult
|
||||
.replace(/([a-zA-Z0-9_$])([=!<>+\-*/%])([a-zA-Z0-9_$])/g, '$1 $2 $3')
|
||||
.replace(/([a-zA-Z0-9_$])(,)([a-zA-Z0-9_$])/g, '$1$2 $3')
|
||||
.replace(/\s+/g, ' ') // 将多个空格替换为单个空格
|
||||
.trim();
|
||||
|
||||
return finalResult;
|
||||
};
|
||||
}
|
||||
|
||||
// 初始化 js_beautify
|
||||
const jsBeautify = {
|
||||
js_beautify: createJsBeautify()
|
||||
};
|
||||
|
||||
/**
|
||||
* Squirrel 语言的 js-beautify 选项配置
|
||||
*/
|
||||
export function getSquirrelBeautifyOptions(options: vscode.FormattingOptions): any {
|
||||
return {
|
||||
indent_size: options.tabSize,
|
||||
indent_char: options.insertSpaces ? ' ' : '\t',
|
||||
preserve_newlines: true,
|
||||
max_preserve_newlines: 2,
|
||||
jslint_happy: false,
|
||||
brace_style: "collapse",
|
||||
space_before_conditional: true,
|
||||
space_after_anon_function: false,
|
||||
unescape_strings: false,
|
||||
wrap_line_length: 120,
|
||||
end_with_newline: false
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 js-beautify 格式化代码
|
||||
*/
|
||||
export function beautifyCode(code: string, options: vscode.FormattingOptions): string {
|
||||
if (!jsBeautify || !jsBeautify.js_beautify) {
|
||||
console.warn('js-beautify 不可用,返回原始代码');
|
||||
return code;
|
||||
}
|
||||
|
||||
try {
|
||||
const beautifyOptions = getSquirrelBeautifyOptions(options);
|
||||
|
||||
// 检查代码长度,处理大块代码
|
||||
const maxChunkSize = 50000; // 50KB 每块
|
||||
if (code.length > maxChunkSize) {
|
||||
// 分割代码并分块处理
|
||||
const chunks = code.split('\n');
|
||||
const resultChunks: string[] = [];
|
||||
|
||||
for (const chunk of chunks) {
|
||||
const formattedChunk = jsBeautify.js_beautify(chunk, beautifyOptions);
|
||||
resultChunks.push(formattedChunk);
|
||||
}
|
||||
|
||||
return resultChunks.join('\n');
|
||||
}
|
||||
|
||||
// 直接格式化小代码块
|
||||
return jsBeautify.js_beautify(code, beautifyOptions);
|
||||
} catch (error) {
|
||||
console.error('js-beautify 格式化失败:', error);
|
||||
// 如果格式化失败,返回原始代码
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测是否为 Squirrel 代码(用于确定是否应用格式化)
|
||||
*/
|
||||
export function isSquirrelCode(code: string): boolean {
|
||||
// 简单的启发式检测 - Squirrel 特有关键字
|
||||
const squirrelKeywords = [
|
||||
'function', 'local', 'if', 'else', 'while', 'for', 'foreach',
|
||||
'class', 'constructor', 'extends', 'instanceof', 'in',
|
||||
'try', 'catch', 'throw', 'clone', 'delegate', 'resume', 'yield',
|
||||
'typeof', 'member', 'rawcall', 'call', 'setdebughook'
|
||||
];
|
||||
|
||||
// 提高检测准确性 - 需要至少匹配到1个关键字
|
||||
return squirrelKeywords.some(keyword =>
|
||||
new RegExp(`\\b${keyword}\\b`).test(code)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user