chore: format all common files (#431)
This commit is contained in:
@@ -1,10 +1,26 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
SourceFile,
|
||||
ChineseComment,
|
||||
ParsedComment,
|
||||
FileWithComments,
|
||||
CommentType,
|
||||
MultiLineContext
|
||||
MultiLineContext,
|
||||
} from '../types/index';
|
||||
import { getCommentPatterns } from '../utils/language';
|
||||
import { containsChinese, cleanCommentText } from '../utils/chinese';
|
||||
@@ -69,15 +85,17 @@ const parseSingleLineComments = (
|
||||
let matchCount = 0;
|
||||
const maxMatches = 100; // Limit each line to a maximum of 100 matches
|
||||
let lastIndex = 0;
|
||||
|
||||
|
||||
while ((match = pattern.exec(line)) !== null) {
|
||||
// Multiple protections against infinite loops
|
||||
matchCount++;
|
||||
if (matchCount > maxMatches) {
|
||||
console.warn(`⚠️ 单行匹配次数过多,中断处理: ${line.substring(0, 50)}...`);
|
||||
console.warn(
|
||||
`⚠️ 单行匹配次数过多,中断处理: ${line.substring(0, 50)}...`,
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Check if lastIndex is advancing to prevent an infinite loop
|
||||
if (pattern.global) {
|
||||
if (pattern.lastIndex <= lastIndex) {
|
||||
@@ -89,7 +107,7 @@ const parseSingleLineComments = (
|
||||
}
|
||||
lastIndex = pattern.lastIndex;
|
||||
}
|
||||
|
||||
|
||||
if (match[1]) {
|
||||
const commentContent = match[1];
|
||||
let commentStartIndex = match.index!;
|
||||
@@ -246,7 +264,6 @@ const parseMultiLineComments = (
|
||||
const commentContent = line.substring(0, endMatch.index!);
|
||||
commentLines.push(commentContent);
|
||||
|
||||
|
||||
comments.push({
|
||||
content: commentLines.join('\n'),
|
||||
startLine: commentStart!.line,
|
||||
@@ -298,11 +315,14 @@ export const filterChineseComments = (
|
||||
language?: string,
|
||||
): ChineseComment[] => {
|
||||
const result: ChineseComment[] = [];
|
||||
|
||||
|
||||
for (const comment of comments) {
|
||||
if (comment.type === 'multi-line' && comment.content.includes('\n')) {
|
||||
// Multi-line comments: line-by-line processing
|
||||
const multiLineResults = processMultiLineCommentForChinese(comment, language);
|
||||
const multiLineResults = processMultiLineCommentForChinese(
|
||||
comment,
|
||||
language,
|
||||
);
|
||||
result.push(...multiLineResults);
|
||||
} else if (containsChinese(comment.content)) {
|
||||
// Single-line comments or single-line multi-line comments
|
||||
@@ -316,7 +336,7 @@ export const filterChineseComments = (
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -329,14 +349,14 @@ const processMultiLineCommentForChinese = (
|
||||
): ChineseComment[] => {
|
||||
const lines = comment.content.split('\n');
|
||||
const result: ChineseComment[] = [];
|
||||
|
||||
|
||||
lines.forEach((line, lineIndex) => {
|
||||
const cleanedLine = cleanCommentText(line, 'multi-line', language);
|
||||
|
||||
|
||||
if (containsChinese(cleanedLine)) {
|
||||
// Calculate the position of this line in the original file
|
||||
const actualLineNumber = comment.startLine + lineIndex;
|
||||
|
||||
|
||||
// Create a comment object representing this line
|
||||
const lineComment: ChineseComment = {
|
||||
content: cleanedLine,
|
||||
@@ -350,14 +370,14 @@ const processMultiLineCommentForChinese = (
|
||||
isPartOfMultiLine: true,
|
||||
originalComment: comment,
|
||||
lineIndexInComment: lineIndex,
|
||||
totalLinesInComment: lines.length
|
||||
}
|
||||
totalLinesInComment: lines.length,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
result.push(lineComment);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -393,7 +413,9 @@ export const detectChineseInFile = (file: SourceFile): ChineseComment[] => {
|
||||
/**
|
||||
* Batch detection of Chinese comments in multiple files
|
||||
*/
|
||||
export const detectChineseInFiles = (files: SourceFile[]): FileWithComments[] => {
|
||||
export const detectChineseInFiles = (
|
||||
files: SourceFile[],
|
||||
): FileWithComments[] => {
|
||||
const results: FileWithComments[] = [];
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
@@ -428,7 +450,9 @@ export const detectChineseInFiles = (files: SourceFile[]): FileWithComments[] =>
|
||||
/**
|
||||
* Get annotation statistics
|
||||
*/
|
||||
export const getCommentStats = (files: SourceFile[]): {
|
||||
export const getCommentStats = (
|
||||
files: SourceFile[],
|
||||
): {
|
||||
totalFiles: number;
|
||||
filesWithComments: number;
|
||||
totalComments: number;
|
||||
@@ -441,12 +465,15 @@ export const getCommentStats = (files: SourceFile[]): {
|
||||
const commentsByType: Record<CommentType, number> = {
|
||||
'single-line': 0,
|
||||
'multi-line': 0,
|
||||
'documentation': 0
|
||||
documentation: 0,
|
||||
};
|
||||
|
||||
files.forEach(file => {
|
||||
const allComments = parseComments(file);
|
||||
const chineseCommentsInFile = filterChineseComments(allComments, file.language);
|
||||
const chineseCommentsInFile = filterChineseComments(
|
||||
allComments,
|
||||
file.language,
|
||||
);
|
||||
|
||||
if (chineseCommentsInFile.length > 0) {
|
||||
filesWithComments++;
|
||||
@@ -465,6 +492,6 @@ export const getCommentStats = (files: SourceFile[]): {
|
||||
filesWithComments,
|
||||
totalComments,
|
||||
chineseComments,
|
||||
commentsByType
|
||||
commentsByType,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,13 +1,35 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import { SourceFile, FileScanConfig, Result } from '../types/index';
|
||||
import { detectLanguage, filterFilesByExtensions, isTextFile } from '../utils/language';
|
||||
import {
|
||||
detectLanguage,
|
||||
filterFilesByExtensions,
|
||||
isTextFile,
|
||||
} from '../utils/language';
|
||||
import { getGitTrackedFiles, getAllGitFiles } from '../utils/git';
|
||||
import { tryCatch } from '../utils/fp';
|
||||
|
||||
/**
|
||||
* Read the file contents and create a SourceFile object
|
||||
*/
|
||||
export const readSourceFile = async (filePath: string): Promise<Result<SourceFile>> => {
|
||||
export const readSourceFile = async (
|
||||
filePath: string,
|
||||
): Promise<Result<SourceFile>> => {
|
||||
return tryCatch(async () => {
|
||||
const content = await fs.readFile(filePath, 'utf-8');
|
||||
const language = detectLanguage(filePath);
|
||||
@@ -15,7 +37,7 @@ export const readSourceFile = async (filePath: string): Promise<Result<SourceFil
|
||||
return {
|
||||
path: filePath,
|
||||
content,
|
||||
language
|
||||
language,
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -23,14 +45,17 @@ export const readSourceFile = async (filePath: string): Promise<Result<SourceFil
|
||||
/**
|
||||
* Batch reading of source files
|
||||
*/
|
||||
export const readSourceFiles = async (filePaths: string[]): Promise<SourceFile[]> => {
|
||||
export const readSourceFiles = async (
|
||||
filePaths: string[],
|
||||
): Promise<SourceFile[]> => {
|
||||
const results = await Promise.allSettled(
|
||||
filePaths.map(path => readSourceFile(path))
|
||||
filePaths.map(path => readSourceFile(path)),
|
||||
);
|
||||
|
||||
return results
|
||||
.filter((result): result is PromiseFulfilledResult<Result<SourceFile>> =>
|
||||
result.status === 'fulfilled' && result.value.success
|
||||
.filter(
|
||||
(result): result is PromiseFulfilledResult<Result<SourceFile>> =>
|
||||
result.status === 'fulfilled' && result.value.success,
|
||||
)
|
||||
.map(result => (result.value as { success: true; data: SourceFile }).data);
|
||||
};
|
||||
@@ -38,7 +63,9 @@ export const readSourceFiles = async (filePaths: string[]): Promise<SourceFile[]
|
||||
/**
|
||||
* Get the source code file in the Git repository
|
||||
*/
|
||||
export const getSourceFiles = async (config: FileScanConfig): Promise<Result<string[]>> => {
|
||||
export const getSourceFiles = async (
|
||||
config: FileScanConfig,
|
||||
): Promise<Result<string[]>> => {
|
||||
const { root, extensions, includeUntracked } = config;
|
||||
|
||||
return tryCatch(async () => {
|
||||
@@ -66,7 +93,9 @@ export const getSourceFiles = async (config: FileScanConfig): Promise<Result<str
|
||||
/**
|
||||
* Scan and read all source code files
|
||||
*/
|
||||
export const scanSourceFiles = async (config: FileScanConfig): Promise<Result<SourceFile[]>> => {
|
||||
export const scanSourceFiles = async (
|
||||
config: FileScanConfig,
|
||||
): Promise<Result<SourceFile[]>> => {
|
||||
return tryCatch(async () => {
|
||||
const filesResult = await getSourceFiles(config);
|
||||
|
||||
@@ -94,28 +123,32 @@ export const isFileAccessible = async (filePath: string): Promise<boolean> => {
|
||||
/**
|
||||
* Get file statistics
|
||||
*/
|
||||
export const getFileStats = async (filePaths: string[]): Promise<{
|
||||
export const getFileStats = async (
|
||||
filePaths: string[],
|
||||
): Promise<{
|
||||
total: number;
|
||||
accessible: number;
|
||||
textFiles: number;
|
||||
supportedFiles: number;
|
||||
}> => {
|
||||
const accessibilityResults = await Promise.allSettled(
|
||||
filePaths.map(isFileAccessible)
|
||||
filePaths.map(isFileAccessible),
|
||||
);
|
||||
|
||||
const accessible = accessibilityResults.filter(
|
||||
(result): result is PromiseFulfilledResult<boolean> =>
|
||||
result.status === 'fulfilled' && result.value
|
||||
result.status === 'fulfilled' && result.value,
|
||||
).length;
|
||||
|
||||
const textFiles = filePaths.filter(isTextFile).length;
|
||||
const supportedFiles = filePaths.filter(path => detectLanguage(path) !== 'other').length;
|
||||
const supportedFiles = filePaths.filter(
|
||||
path => detectLanguage(path) !== 'other',
|
||||
).length;
|
||||
|
||||
return {
|
||||
total: filePaths.length,
|
||||
accessible,
|
||||
textFiles,
|
||||
supportedFiles
|
||||
supportedFiles,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ProcessingReport,
|
||||
ProcessingStats,
|
||||
@@ -198,18 +214,22 @@ export const generateMarkdownReport = (report: ProcessingReport): string => {
|
||||
detail.status === 'success'
|
||||
? '✅'
|
||||
: detail.status === 'error'
|
||||
? '❌'
|
||||
: detail.status === 'skipped'
|
||||
? '⏭️'
|
||||
: '🔄';
|
||||
? '❌'
|
||||
: detail.status === 'skipped'
|
||||
? '⏭️'
|
||||
: '🔄';
|
||||
|
||||
markdown += `| ${detail.file} | ${status} | ${detail.commentCount} | ${duration} | ${detail.errorMessage || '-'} |\n`;
|
||||
markdown += `| ${detail.file} | ${status} | ${
|
||||
detail.commentCount
|
||||
} | ${duration} | ${detail.errorMessage || '-'} |\n`;
|
||||
});
|
||||
|
||||
if (stats.errors.length > 0) {
|
||||
markdown += '\n## ❌ 错误详情\n\n';
|
||||
stats.errors.forEach((error, index) => {
|
||||
markdown += `${index + 1}. **${error.file}**\n \`\`\`\n ${error.error}\n \`\`\`\n\n`;
|
||||
markdown += `${index + 1}. **${error.file}**\n \`\`\`\n ${
|
||||
error.error
|
||||
}\n \`\`\`\n\n`;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -276,7 +296,9 @@ export class ProgressDisplay {
|
||||
const speed = current / elapsed;
|
||||
const eta = speed > 0 ? (this.total - current) / speed : 0;
|
||||
|
||||
let line = `进度: ${current}/${this.total} (${percentage}%) | 耗时: ${elapsed.toFixed(1)}s`;
|
||||
let line = `进度: ${current}/${
|
||||
this.total
|
||||
} (${percentage}%) | 耗时: ${elapsed.toFixed(1)}s`;
|
||||
|
||||
if (eta > 0) {
|
||||
line += ` | 预计剩余: ${eta.toFixed(1)}s`;
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
TranslationResult,
|
||||
TranslationContext,
|
||||
@@ -7,7 +23,10 @@ import {
|
||||
import { TranslationConfig } from '../types/config';
|
||||
import { retry, chunk } from '../utils/fp';
|
||||
import { isValidTranslation } from '../utils/chinese';
|
||||
import { translate as volcTranslate, TranslateConfig as VolcTranslateConfig } from '../volc/translate';
|
||||
import {
|
||||
translate as volcTranslate,
|
||||
TranslateConfig as VolcTranslateConfig,
|
||||
} from '../volc/translate';
|
||||
|
||||
/**
|
||||
* Translation services
|
||||
@@ -59,7 +78,7 @@ export class TranslationService {
|
||||
private async callVolcTranslate(texts: string[]): Promise<string[]> {
|
||||
const volcConfig = this.toVolcConfig();
|
||||
const response = await volcTranslate(texts, volcConfig);
|
||||
|
||||
|
||||
return response.TranslationList.map(item => item.Translation);
|
||||
}
|
||||
|
||||
@@ -101,7 +120,9 @@ export class TranslationService {
|
||||
return result;
|
||||
} catch (error) {
|
||||
throw new TranslationError(
|
||||
`Translation failed: ${error instanceof Error ? error.message : String(error)}`,
|
||||
`Translation failed: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
comment,
|
||||
);
|
||||
}
|
||||
@@ -146,7 +167,7 @@ export class TranslationService {
|
||||
|
||||
// Batch translation of uncached comments
|
||||
const chunks = chunk(uncachedComments, concurrency);
|
||||
|
||||
|
||||
for (const chunkItems of chunks) {
|
||||
try {
|
||||
const textsToTranslate = chunkItems.map(item => item.comment.content);
|
||||
@@ -163,13 +184,16 @@ export class TranslationService {
|
||||
const result: TranslationResult = {
|
||||
original: item.comment.content,
|
||||
translated,
|
||||
confidence: this.calculateConfidence(translated, item.comment.content),
|
||||
confidence: this.calculateConfidence(
|
||||
translated,
|
||||
item.comment.content,
|
||||
),
|
||||
};
|
||||
|
||||
// cache results
|
||||
const cacheKey = this.getCacheKey(item.comment.content);
|
||||
this.cache.set(cacheKey, result);
|
||||
|
||||
|
||||
results[item.index] = result;
|
||||
} else {
|
||||
// If the translation fails, an error result is created
|
||||
@@ -189,8 +213,12 @@ export class TranslationService {
|
||||
confidence: 0,
|
||||
};
|
||||
});
|
||||
|
||||
console.warn(`批量翻译失败: ${error instanceof Error ? error.message : String(error)}`);
|
||||
|
||||
console.warn(
|
||||
`批量翻译失败: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user