diff --git a/src/commands/check.ts b/src/commands/check.ts index 4fce10b..7c9a5a7 100644 --- a/src/commands/check.ts +++ b/src/commands/check.ts @@ -4,6 +4,7 @@ import * as fse from 'fs-extra'; import { Uri, window, workspace } from 'vscode'; import { checkstyleDiagnosticManager } from '../checkstyleDiagnosticManager'; +import { findNonIgnoredFiles } from '../utils/workspaceUtils'; export async function checkCode(uri?: Uri): Promise { if (!uri) { // If not specified, check active editor @@ -14,7 +15,7 @@ export async function checkCode(uri?: Uri): Promise { } let filesToCheck: Uri[]; if ((await fse.stat(uri.fsPath)).isDirectory()) { - filesToCheck = await workspace.findFiles(`${workspace.asRelativePath(uri)}/**/*.java`); + filesToCheck = await findNonIgnoredFiles(`${workspace.asRelativePath(uri)}/**/*.java`); } else { filesToCheck = [uri]; } diff --git a/src/commands/config.ts b/src/commands/config.ts index 5ade95e..f1cdbb2 100644 --- a/src/commands/config.ts +++ b/src/commands/config.ts @@ -3,12 +3,13 @@ import * as fse from 'fs-extra'; import * as path from 'path'; -import { Uri, window, workspace, WorkspaceFolder } from 'vscode'; +import { Uri, window, WorkspaceFolder } from 'vscode'; import * as xmljs from 'xml-js'; import { checkstyleChannel } from '../checkstyleChannel'; import { BuiltinConfiguration, checkstyleDoctypeIds } from '../constants/checkstyleConfigs'; import { IQuickPickItemEx } from '../models'; -import { getDefaultWorkspaceFolder, setCheckstyleConfigurationPath, tryUseWorkspaceFolder } from '../utils/settingUtils'; +import { setCheckstyleConfigurationPath } from '../utils/settingUtils'; +import { findNonIgnoredFiles, getDefaultWorkspaceFolder, tryUseWorkspaceFolder } from '../utils/workspaceUtils'; export async function setConfiguration(uri?: Uri): Promise { if (uri) { @@ -89,7 +90,7 @@ async function inputConfiguration(): Promise { async function detectConfigurations(): Promise { const detected: IQuickPickItemEx[] = []; - for (const xml of await workspace.findFiles('**/*.xml')) { + for (const xml of await findNonIgnoredFiles('**/*.xml')) { const relativeXml: string = tryUseWorkspaceFolder(xml.fsPath); function doctypeFn(doctype: string): void { const [name, type] = doctype.split(/\s+/, 2); diff --git a/src/utils/settingUtils.ts b/src/utils/settingUtils.ts index 519e7e5..fc6fce6 100644 --- a/src/utils/settingUtils.ts +++ b/src/utils/settingUtils.ts @@ -1,9 +1,9 @@ // Copyright (c) jdneo. All rights reserved. // Licensed under the GNU LGPLv3 license. -import * as path from 'path'; -import { ConfigurationTarget, Uri, window, workspace, WorkspaceConfiguration, WorkspaceFolder } from 'vscode'; +import { ConfigurationTarget, Uri, window, workspace, WorkspaceConfiguration } from 'vscode'; import { JAVA_CHECKSTYLE_AUTOCHECK, JAVA_CHECKSTYLE_CONFIGURATION, JAVA_CHECKSTYLE_PROPERTIES, JAVA_CHECKSTYLE_VERSION } from '../constants/settings'; +import { resolveVariables } from './workspaceUtils'; export function setCheckstyleConfigurationPath(fsPath: string, uri?: Uri): void { setConfiguration(JAVA_CHECKSTYLE_CONFIGURATION, fsPath, uri); @@ -31,34 +31,10 @@ export function getCheckstyleProperties(uri?: Uri): object { return properties; } -export function getDefaultWorkspaceFolder(): WorkspaceFolder | undefined { - const workspaceFolders: WorkspaceFolder[] | undefined = workspace.workspaceFolders; - if (workspaceFolders === undefined) { - return undefined; - } - if (workspaceFolders.length === 1) { - return workspaceFolders[0]; - } - if (window.activeTextEditor) { - const activeWorkspaceFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); - return activeWorkspaceFolder; - } - return undefined; -} - export function isAutoCheckEnabled(): boolean { return getConfiguration().get(JAVA_CHECKSTYLE_AUTOCHECK, true); } -export function tryUseWorkspaceFolder(fsPath: string): string { - const result: string = workspace.asRelativePath(fsPath); - if (result === fsPath) { - return result; - } else { - return path.join('${workspaceFolder}', result); - } -} - export function getConfiguration(uri?: Uri): WorkspaceConfiguration { return workspace.getConfiguration(undefined, uri || null); } @@ -69,20 +45,3 @@ function setConfiguration(section: string, value: any, uri?: Uri): void { } getConfiguration(uri).update(section, value, ConfigurationTarget.WorkspaceFolder); } - -const workspaceRegexp: RegExp = /\$\{workspacefolder\}/i; -function resolveVariables(value: string, resourceUri?: Uri): string { - let workspaceFolder: WorkspaceFolder | undefined; - if (resourceUri) { - workspaceFolder = workspace.getWorkspaceFolder(resourceUri); - } else { - workspaceFolder = getDefaultWorkspaceFolder(); - } - if (workspaceRegexp.test(value)) { - if (!workspaceFolder) { - throw new Error('No workspace folder is opened in current VS Code workspace when resolving ${workspaceFolder}'); - } - return value.replace(workspaceRegexp, workspaceFolder.uri.fsPath); - } - return value; -} diff --git a/src/utils/workspaceUtils.ts b/src/utils/workspaceUtils.ts new file mode 100644 index 0000000..0393d8e --- /dev/null +++ b/src/utils/workspaceUtils.ts @@ -0,0 +1,87 @@ +// Copyright (c) jdneo. All rights reserved. +// Licensed under the GNU LGPLv3 license. + +import * as cp from 'child_process'; +import * as _ from 'lodash'; +import * as path from 'path'; +import { Uri, window, workspace, WorkspaceFolder } from 'vscode'; +import { checkstyleChannel } from '../checkstyleChannel'; + +export function getDefaultWorkspaceFolder(): WorkspaceFolder | undefined { + const workspaceFolders: WorkspaceFolder[] | undefined = workspace.workspaceFolders; + if (workspaceFolders === undefined) { + return undefined; + } + if (workspaceFolders.length === 1) { + return workspaceFolders[0]; + } + if (window.activeTextEditor) { + const activeWorkspaceFolder: WorkspaceFolder | undefined = workspace.getWorkspaceFolder(window.activeTextEditor.document.uri); + return activeWorkspaceFolder; + } + return undefined; +} + +export function tryUseWorkspaceFolder(fsPath: string): string { + const result: string = workspace.asRelativePath(fsPath); + if (result === fsPath) { + return result; + } else { + return path.join('${workspaceFolder}', result); + } +} + +const workspaceRegexp: RegExp = /\$\{workspacefolder\}/i; + +export function resolveVariables(value: string, resourceUri?: Uri): string { + let workspaceFolder: WorkspaceFolder | undefined; + if (resourceUri) { + workspaceFolder = workspace.getWorkspaceFolder(resourceUri); + } else { + workspaceFolder = getDefaultWorkspaceFolder(); + } + if (workspaceRegexp.test(value)) { + if (!workspaceFolder) { + throw Error('No workspace folder is opened in current VS Code workspace when resolving ${workspaceFolder}'); + } + return value.replace(workspaceRegexp, workspaceFolder.uri.fsPath); + } + return value; +} + +// workspace.findFiles only defaults to exclude entires in files.exclude +// so it is not even able to exclude node_modules +// Refer to: https://github.com/Microsoft/vscode/issues/48674 +export async function findNonIgnoredFiles(pattern: string): Promise { + let uris: Uri[] = await workspace.findFiles(pattern, `{${[ + ...Object.keys(await workspace.getConfiguration('search', null).get('exclude') || {}), + ...Object.keys(await workspace.getConfiguration('files', null).get('exclude') || {}), + ].join(',')}}`); + + const workspaceFolder: WorkspaceFolder | undefined = getDefaultWorkspaceFolder(); + if (workspaceFolder) { + try { // tslint:disable-next-line: typedef + const result: string = await new Promise((resolve, reject) => { + cp.exec(`git check-ignore ${uris.map((uri: Uri) => workspace.asRelativePath(uri)).join(' ')}`, { + cwd: workspaceFolder.uri.fsPath, + }, (error: Error & { code?: 0 | 1 | 128 }, stdout: string, stderr: string) => { + if (error && (error.code !== 0 && error.code !== 1)) { + reject(error); + } else if (stderr) { + reject(new Error(stderr)); + } else { + resolve(stdout); + } + }); + }); + const excludes: Uri[] = result.trim().split('\n').map((relativePath: string) => { + return Uri.file(path.join(workspaceFolder.uri.fsPath, relativePath.replace(/"(.+)"/, '$1'))); + }); + uris = _.differenceBy(uris, excludes, 'fsPath'); + } catch (error) { + checkstyleChannel.appendLine(`git check-ignore exec error: ${error.toString()}`); + } + } + + return uris; +}