Skip to content

Commit

Permalink
fix: diff : support removed files
Browse files Browse the repository at this point in the history
  • Loading branch information
uctakeoff committed Jan 16, 2022
1 parent f20df5e commit 5dda781
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "vscode-counter",
"displayName": "VS Code Counter",
"description": "Count lines of code in many programming languages.",
"version": "3.0.2",
"version": "3.0.3",
"publisher": "uctakeoff",
"author": {
"name": "Ushiyama Kentaro"
Expand Down
19 changes: 7 additions & 12 deletions src/LineCounter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,11 @@ export class Count {
};

export class LineCounter {
public readonly name: string;
private lineComments: string[];
private blockComments: [string, string][];
private blockStrings: [string, string][];

constructor(name: string, lineComments: string[], blockComments: [string, string][], blockStrings: [string, string][]) {
this.name = name;
this.lineComments = lineComments;
this.blockComments = blockComments;
this.blockStrings = blockStrings;
constructor(
public readonly name: string,
private lineComments: string[],
private blockComments: [string, string][],
private blockStrings: [string, string][]) {
}
public count(text: string): Count {
enum LineType { Code, Comment, Blank }
Expand All @@ -49,17 +44,17 @@ export class LineCounter {
let type = (blockCommentEnd.length > 0) ? LineType.Comment : (blockStringEnd.length > 0) ? LineType.Code : LineType.Blank;
let i = 0;
while (i < line.length) {
// now in block comment
if (blockCommentEnd.length > 0) {
// now in block comment
const index = nextIndexOf(line, blockCommentEnd, i);
if (index >= 0) {
blockCommentEnd = '';
i = index;
} else {
break;
}
// now in block string (here document)
} else if (blockStringEnd.length > 0) {
// now in block string (here document)
const index = nextIndexOf(line, blockStringEnd, i);
if (index >= 0) {
blockStringEnd = '';
Expand Down
34 changes: 21 additions & 13 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as path from 'path';
import { LineCounter, Count } from './LineCounter';
import Gitignore from './Gitignore';
import * as minimatch from 'minimatch';
import { buildUri, createTextDecoder, currentWorkspaceFolder, dirUri, makeDirectories, readJsonFile, readTextFiles, showTextPreview, writeTextFile } from './vscode-utils';
import { buildUri, createTextDecoder, currentWorkspaceFolder, dirUri, makeDirectories, readJsonFile, readUtf8Files, showTextPreview, writeTextFile } from './vscode-utils';

const EXTENSION_ID = 'uctakeoff.vscode-counter';
const EXTENSION_NAME = 'VSCodeCounter';
Expand Down Expand Up @@ -227,7 +227,7 @@ class CodeCounterController {
throw Error(`There was no target file.`);
}
statusBar.text = `VSCodeCounter: Totaling...`;

await makeDirectories(outputDir);
const regex = /^\d\d\d\d-\d\d-\d\d\_\d\d-\d\d-\d\d$/;
const histories = (await vscode.workspace.fs.readDirectory(outputDir))
Expand Down Expand Up @@ -300,8 +300,8 @@ class CodeCounterController {
const loadGitIgnore = async () => {
const gitignoreFiles = await vscode.workspace.findFiles('**/.gitignore', '');
gitignoreFiles.forEach(f => log(`use gitignore : ${f}`));
const values = await readTextFiles(gitignoreFiles.sort());
return new Gitignore('').merge(...values.map(p => new Gitignore(p.data ?? '', dirUri(p.uri).fsPath)));
const values = await readUtf8Files(gitignoreFiles.sort());
return new Gitignore('').merge(...values.map(p => new Gitignore(p.data, dirUri(p.uri).fsPath)));
}

const countLines = (lineCounterTable: LineCounterTable, fileUris: vscode.Uri[], maxOpenFiles: number, fileEncoding: string, ignoreUnsupportedFile: boolean, showStatus: (text: string) => void) => {
Expand Down Expand Up @@ -412,7 +412,7 @@ const collectLanguageConfigurations = (langs: Map<string, LanguageConf>): Promis
const langExt = append(langs, l);
if (l.configuration) {
const confUrl = vscode.Uri.file(path.join(ex.extensionPath, l.configuration));
readJsonFile(confUrl).then((langConf: vscode.LanguageConfiguration) => {
readJsonFile<vscode.LanguageConfiguration>(confUrl, undefined, {}).then((langConf) => {
// log(`${confUrl} ${data.length}B :${l.id}`);
if (langConf.comments) {
if (langConf.comments.lineComment) {
Expand Down Expand Up @@ -470,7 +470,7 @@ const loadLanguageConfigurations = async (conf: Config): Promise<{ [key: string]
case "output directory":
const workFolder = await currentWorkspaceFolder();
const outputDir = buildUri(workFolder.uri, conf.outputDirectory);
return await readJsonFile(outputDir, 'languages.json');
return await readJsonFile<{ [key: string]: LanguageConf }>(outputDir, 'languages.json', {});
default: break;
}
} catch (e: any) {
Expand Down Expand Up @@ -500,11 +500,11 @@ class LineCounterTable {
public getCounter(uri: vscode.Uri, langId?: string) {
const filePath = uri.fsPath;
// priority
return this.getByAssociations(filePath)
return this.getByAssociations(filePath)
|| this.filenameRules.get(path.basename(filePath))
|| this.getById(langId)
|| this.fileextRules.get(filePath)
|| this.fileextRules.get(path.extname(filePath))
|| this.getById(langId)
|| this.fileextRules.get(filePath)
|| this.fileextRules.get(path.extname(filePath))
;
}

Expand Down Expand Up @@ -536,15 +536,23 @@ const outputResults = async (date: Date, targetDirUri: vscode.Uri, results: Resu
const diffs: Result[] = [];
if (prevOutputDir) {
try {
const prevResults: { [uri: string]: Count } = await readJsonFile(prevOutputDir, 'results.json');
log(`Previous OutputDir : ${prevOutputDir}, count ${prevResults.length} files`);
results.map(r => {
const prevResults = await readJsonFile<{ [uri: string]: Count&{language:string} }>(prevOutputDir, 'results.json', {});
log(`Previous OutputDir : ${prevOutputDir}, count ${Object.keys(prevResults).length} files`);
results.forEach(r => {
const p = prevResults[r.uri.toString()];
delete prevResults[r.uri.toString()];
const diff = p ? r.clone().sub(p) : r;
if (!diff.isEmpty) {
diffs.push(diff);
}
});
log(` removed ${Object.keys(prevResults).length} files`);
Object.entries(prevResults).forEach(v => {
const diff = new Result(vscode.Uri.parse(v[0]), v[1].language, new Count().sub(v[1]));
if (!diff.isEmpty) {
diffs.push(diff);
}
});
} catch (e: any) {
log(`failed to access previous "results.json"`);
diffs.length = 0;
Expand Down
51 changes: 34 additions & 17 deletions src/vscode-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,47 @@ const vscodeEncodingTable = new Map<string, string>([

export const createTextDecoder = (vscodeTextEncoding: string) => new TextDecoder(vscodeEncodingTable.get(vscodeTextEncoding) || vscodeTextEncoding);

export const readTextFile = async (baseUri: vscode.Uri, path?: string) => {
export const readUtf8File = async (baseUri: vscode.Uri, path?: string): Promise<{ uri: vscode.Uri, data: string, error?: any }> => {
const uri = path ? buildUri(baseUri, path) : baseUri;
const data = await vscode.workspace.fs.readFile(uri);
log(`read ${uri} : ${data.length}B`);
return decoderU8.decode(data);
try {
const bin = await vscode.workspace.fs.readFile(uri);
// log(`read ${uri} : ${bin.length}B`);
const data = decoderU8.decode(bin);
return {uri, data};
} catch (error: any) {
log(`readUtf8File(${baseUri}, ${path}) failed. : ${error}`);
return { uri, data: '', error };
}
}

export const readTextFiles = async (uris: vscode.Uri[]) => {
const ret: { uri: vscode.Uri, data?: string, error?: any }[] = [];
export const readUtf8Files = async (uris: vscode.Uri[]) => {
const ret: { uri: vscode.Uri, data: string, error?: any }[] = [];
for (const uri of uris) {
try {
const data = await readTextFile(uri);
ret.push({ uri, data });
} catch (error: any) {
log(`failed to read ${uri} : ${error}`);
ret.push({ uri, error });
}
ret.push(await readUtf8File(uri));
}
return ret;
}

export const readJsonFile = async (baseUri: vscode.Uri, path?: string) => {
const data = await readTextFile(baseUri, path);
return JSONC.parse(data);
export const checkJsonType = <T extends boolean | number | string | Array<any> | { [key: string]: any }>(json: any, defaultValue: T): T => {
if (json === null || json === undefined) return defaultValue;
if (Array.isArray(json)) return json as T;
const type = typeof json;
if ((type === typeof defaultValue) && ['object', 'number', 'boolean', 'string'].some(t => t === type)) {
return json as T;
}
return defaultValue;
}

export const readJsonFile = async <T extends boolean | number | string | Array<any> | { [key: string]: any }>(baseUri: vscode.Uri, path: string | undefined, defaultValue: T): Promise<T> => {
try {
const text = await readUtf8File(baseUri, path);
if (text.error) return defaultValue;
const json = JSONC.parse(text.data);
return checkJsonType(json, defaultValue);
} catch (e: any) {
log(`readJsonFile(${baseUri}, ${path}) failed. : ${e}`);
}
return defaultValue;
}

const makeDirectories_ = (dirpath: vscode.Uri, resolve: () => void, reject: (reason: string) => void) => {
Expand Down Expand Up @@ -131,7 +148,7 @@ export const showTextFile = async (uri: vscode.Uri) => {
}
export const showTextPreview = async (uri: vscode.Uri) => {
if (uri.path.endsWith('.md')) {
await vscode.commands.executeCommand("markdown.showPreview", uri);
await vscode.commands.executeCommand("markdown.showPreview", uri);
} else {
await showTextFile(uri);
}
Expand Down

0 comments on commit 5dda781

Please sign in to comment.