Skip to content

Commit e71a463

Browse files
committed
wip
1 parent f686a8e commit e71a463

File tree

4 files changed

+107
-19
lines changed

4 files changed

+107
-19
lines changed

l10n/bundle.l10n.ja.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,7 @@
1010
"No {0} found": "{0} は見つかりませんでした",
1111
"Searching for replacement characters...": "置換文字を検索しています...",
1212
"Checking {0}...": "{0} を確認しています...",
13-
"No '{0}' found in workspace": "ワークスペース内に '{0}' は見つかりませんでした"
13+
"No '{0}' found in workspace": "ワークスペース内に '{0}' は見つかりませんでした",
14+
"Report saved to: {0}": "レポートを保存しました: {0}",
15+
"Failed to save report: {0}": "レポートの保存に失敗しました: {0}"
1416
}

l10n/bundle.l10n.json

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
{
2-
"Detect U+FFFD (replacement character)": "Detect U+FFFD (replacement character)",
3-
"Current File": "Current File",
4-
"Search in the current file only": "Search in the current file only",
5-
"Workspace": "Workspace",
6-
"Search in all files in the workspace": "Search in all files in the workspace",
7-
"Select search scope": "Select search scope",
8-
"No active text editor": "No active text editor",
9-
"extension.replacementCharacterFound": "extension.replacementCharacterFound",
10-
"No {0} found": "No {0} found",
11-
"Searching for replacement characters...": "Searching for replacement characters...",
12-
"Checking {0}...": "Checking {0}...",
13-
"No '{0}' found in workspace": "No '{0}' found in workspace"
2+
"Detect U+FFFD (replacement character)": "Detect U+FFFD (replacement character)",
3+
"Report saved to: {0}": "Report saved to: {0}",
4+
"Failed to save report: {0}": "Failed to save report: {0}",
5+
"Current File": "Current File",
6+
"Search in the current file only": "Search in the current file only",
7+
"Workspace": "Workspace",
8+
"Search in all files in the workspace": "Search in all files in the workspace",
9+
"Select search scope": "Select search scope",
10+
"No active text editor": "No active text editor",
11+
"extension.replacementCharacterFound": "extension.replacementCharacterFound",
12+
"No {0} found": "No {0} found",
13+
"Searching for replacement characters...": "Searching for replacement characters...",
14+
"Checking {0}...": "Checking {0}...",
15+
"No '{0}' found in workspace": "No '{0}' found in workspace"
1416
}

package.json

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"url": "https://github.com/ktyubeshi/mojibake-inspector"
1010
},
1111
"engines": {
12-
"vscode": "^1.73.0"
12+
"vscode": "^1.48.2"
1313
},
1414
"categories": [
1515
"Other"
@@ -45,7 +45,17 @@
4545
"**/dist/**",
4646
"**/out/**"
4747
],
48-
"description": "Patterns to exclude from workspace-wide search"
48+
"description": "ワークスペース全体検索から除外するglobパターンの配列"
49+
},
50+
"mojibakeInspector.report.enabled": {
51+
"type": "boolean",
52+
"default": false,
53+
"description": "文字化け検出結果をレポートファイルに出力する"
54+
},
55+
"mojibakeInspector.report.outputPath": {
56+
"type": "string",
57+
"default": "mojibake-report.txt",
58+
"description": "レポートファイルの出力先(ワークスペースルートからの相対パス)"
4959
}
5060
}
5161
}
@@ -65,7 +75,7 @@
6575
"devDependencies": {
6676
"@types/mocha": "^10.0.10",
6777
"@types/node": "20.x",
68-
"@types/vscode": "^1.73.0",
78+
"@types/vscode": "^1.48.2",
6979
"@typescript-eslint/eslint-plugin": "^8.17.0",
7080
"@typescript-eslint/parser": "^8.17.0",
7181
"@vscode/l10n-dev": "^0.0.35",
@@ -77,8 +87,5 @@
7787
"typescript": "^5.7.2",
7888
"webpack": "^5.95.0",
7989
"webpack-cli": "^5.1.4"
80-
},
81-
"dependencies": {
82-
"@vscode/l10n": "^0.0.10"
8390
}
8491
}

src/extension.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import * as vscode from 'vscode';
33
import * as path from 'path';
44
import { l10n } from 'vscode';
5+
import * as fs from 'fs';
56

67
// 置換文字のデコレーション設定
78
const mojibakeDecoration = vscode.window.createTextEditorDecorationType({
@@ -32,6 +33,54 @@ const DEFAULT_EXCLUDE_PATTERNS = [
3233
'**/out/**'
3334
];
3435

36+
// エラーコード定義
37+
const ERROR_CODE = 'E001';
38+
const ERROR_DESCRIPTION = 'U+FFFD (replacement character) detected';
39+
40+
// レポート出力インターフェース
41+
interface MojibakeReport {
42+
errorCode: string;
43+
filePath: string;
44+
line: number;
45+
column: number;
46+
}
47+
48+
// レポートファイル出力関数
49+
async function writeReport(reports: MojibakeReport[], reportPath: string) {
50+
const header = `# Mojibake Inspector Report
51+
# Error Codes:
52+
# ${ERROR_CODE}\t${ERROR_DESCRIPTION}\n`;
53+
54+
let content = '';
55+
if (reports.length === 0) {
56+
content = 'No mojibake characters were found.\n';
57+
} else {
58+
content = 'ErrorCode\tFilePath\tLine\tColumn\n' +
59+
reports.map(report =>
60+
`${report.errorCode}\t${report.filePath}\t${report.line}\t${report.column}`
61+
).join('\n');
62+
}
63+
64+
try {
65+
await vscode.workspace.fs.writeFile(
66+
vscode.Uri.file(reportPath),
67+
Buffer.from(header + content, 'utf8')
68+
);
69+
vscode.window.showInformationMessage(l10n.t('Report saved to: {0}', reportPath));
70+
} catch (error: unknown) {
71+
const errorMessage = error instanceof Error ? error.message : String(error);
72+
vscode.window.showErrorMessage(l10n.t('Failed to save report: {0}', errorMessage));
73+
}
74+
}
75+
76+
// 既存のインターフェース定義の近くに追加
77+
interface MojibakeResult {
78+
file: string;
79+
line: number;
80+
mojibake: string;
81+
encoding: string;
82+
}
83+
3584
export function activate(context: vscode.ExtensionContext) {
3685
try {
3786
console.log('Activating Mojibake Inspector extension...');
@@ -156,6 +205,11 @@ async function findReplacementCharactersInWorkspace() {
156205
// ワークスペースの設定から除外パターンを取得(設定がない場合はデフォルトを使用)
157206
const config = vscode.workspace.getConfiguration('mojibakeInspector');
158207
const excludePatterns = config.get<string[]>('excludePatterns', DEFAULT_EXCLUDE_PATTERNS);
208+
const reportConfig = {
209+
enabled: config.get<boolean>('report.enabled', false),
210+
outputPath: config.get<string>('report.outputPath', 'mojibake-report.txt')
211+
};
212+
const reports: MojibakeReport[] = [];
159213

160214
const progress = await vscode.window.withProgress({
161215
location: vscode.ProgressLocation.Notification,
@@ -193,6 +247,20 @@ async function findReplacementCharactersInWorkspace() {
193247
diagnostic.code = 'mojibake';
194248
diagnostics.push(diagnostic);
195249

250+
if (reportConfig.enabled) {
251+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri);
252+
const relativePath = workspaceFolder
253+
? path.relative(workspaceFolder.uri.fsPath, document.uri.fsPath)
254+
: document.uri.fsPath;
255+
256+
reports.push({
257+
errorCode: ERROR_CODE,
258+
filePath: relativePath,
259+
line: startPos.line + 1,
260+
column: startPos.character + 1
261+
});
262+
}
263+
196264
totalCount++;
197265
}
198266

@@ -211,6 +279,15 @@ async function findReplacementCharactersInWorkspace() {
211279
return totalCount;
212280
});
213281

282+
// レポートファイルの出力
283+
if (reportConfig.enabled) {
284+
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
285+
if (workspaceFolder) {
286+
const reportPath = path.join(workspaceFolder.uri.fsPath, reportConfig.outputPath);
287+
await writeReport(reports, reportPath);
288+
}
289+
}
290+
214291
// 結果を表示
215292
if (progress > 0) {
216293
vscode.window.showInformationMessage(

0 commit comments

Comments
 (0)