Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds support for gulpfiles using ESM. #113505

Merged
merged 1 commit into from Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
118 changes: 87 additions & 31 deletions extensions/gulp/src/main.ts
Expand Up @@ -13,12 +13,31 @@ const localize = nls.loadMessageBundle();

type AutoDetect = 'on' | 'off';

function exists(file: string): Promise<boolean> {
return new Promise<boolean>((resolve, _reject) => {
fs.exists(file, (value) => {
resolve(value);
});
});
/**
* Check if the given filename is a file.
*
* If returns false in case the file does not exist or
* the file stats cannot be accessed/queried or it
* is no file at all.
*
* @param filename
* the filename to the checked
* @returns
* true in case the file exists, in any other case false.
*/
async function exists(filename: string): Promise<boolean> {
try {

if ((await fs.promises.stat(filename)).isFile()) {
return true;
}
} catch (ex) {
// In case requesting the file statistics fail.
// we assume it does not exist.
return false;
}

return false;
}

function exec(command: string, options: cp.ExecOptions): Promise<{ stdout: string; stderr: string }> {
Expand Down Expand Up @@ -70,21 +89,23 @@ function showError() {
}

async function findGulpCommand(rootPath: string): Promise<string> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I cannot deny that the refactoring here is clearer, it's easier/faster/less cognitive load to review PRs that don't include refactors and features together. The greater the number of lines changed, the less likely I am to get to it quickly (and I know I'm not alone on that :))

let gulpCommand: string;
let platform = process.platform;

if (platform === 'win32' && await exists(path.join(rootPath, 'node_modules', '.bin', 'gulp.cmd'))) {
const globalGulp = path.join(process.env.APPDATA ? process.env.APPDATA : '', 'npm', 'gulp.cmd');
if (await exists(globalGulp)) {
gulpCommand = '"' + globalGulp + '"';
} else {
gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp.cmd');
return `"${globalGulp}"`;
}
} else if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath, 'node_modules', '.bin', 'gulp'))) {
gulpCommand = path.join('.', 'node_modules', '.bin', 'gulp');
} else {
gulpCommand = 'gulp';

return path.join('.', 'node_modules', '.bin', 'gulp.cmd');

}

if ((platform === 'linux' || platform === 'darwin') && await exists(path.join(rootPath, 'node_modules', '.bin', 'gulp'))) {
return path.join('.', 'node_modules', '.bin', 'gulp');
}
return gulpCommand;

return 'gulp';
}

interface GulpTaskDefinition extends vscode.TaskDefinition {
Expand All @@ -111,22 +132,23 @@ class FolderDetector {
}

public start(): void {
let pattern = path.join(this._workspaceFolder.uri.fsPath, '{node_modules,gulpfile{.babel.js,.js,.ts}}');
let pattern = path.join(this._workspaceFolder.uri.fsPath, '{node_modules,gulpfile{.babel.js,.esm.js,.js,.mjs,.cjs,.ts}}');
this.fileWatcher = vscode.workspace.createFileSystemWatcher(pattern);
this.fileWatcher.onDidChange(() => this.promise = undefined);
this.fileWatcher.onDidCreate(() => this.promise = undefined);
this.fileWatcher.onDidDelete(() => this.promise = undefined);
}

public async getTasks(): Promise<vscode.Task[]> {
if (this.isEnabled()) {
if (!this.promise) {
this.promise = this.computeTasks();
}
return this.promise;
} else {
if (!this.isEnabled()) {
return [];
}

if (!this.promise) {
this.promise = this.computeTasks();
}

return this.promise;
}

public async getTask(_task: vscode.Task): Promise<vscode.Task | undefined> {
Expand All @@ -140,21 +162,55 @@ class FolderDetector {
return undefined;
}

/**
* Searches for a gulp entry point inside the given folder.
*
* Typically the entry point is a file named "gulpfile.js"
*
* It can also be a transposed gulp entry points, like gulp.babel.js or gulp.esm.js
*
* Additionally recent node version prefer the .mjs or .cjs extension over the .js.
*
* @param root
* the folder which should be checked.
*/
private async hasGulpfile(root: string): Promise<boolean | undefined> {

for (const filename of await fs.promises.readdir(root)) {

const ext = path.extname(filename);
if (ext !== '.js' && ext !== '.mjs' && ext !== '.cjs') {
continue;
}

if (!exists(filename)) {
continue;
}

let basename = path.basename(filename, ext).toLowerCase();
if (basename === 'gulpfile') {
return true;
}
if (basename === 'gulpfile.esm') {
return true;
}
if (basename === 'gulpfile.babel') {
return true;
}
}

return false;
}

private async computeTasks(): Promise<vscode.Task[]> {
let rootPath = this._workspaceFolder.uri.scheme === 'file' ? this._workspaceFolder.uri.fsPath : undefined;
let emptyTasks: vscode.Task[] = [];
if (!rootPath) {
return emptyTasks;
}
let gulpfile = path.join(rootPath, 'gulpfile.js');
if (!await exists(gulpfile)) {
gulpfile = path.join(rootPath, 'Gulpfile.js');
if (!await exists(gulpfile)) {
gulpfile = path.join(rootPath, 'gulpfile.babel.js');
if (!await exists(gulpfile)) {
return emptyTasks;
}
}

if (!this.hasGulpfile(rootPath)) {
return emptyTasks;
}

let commandLine = `${await this._gulpCommand} --tasks-simple --no-color`;
Expand Down
5 changes: 4 additions & 1 deletion extensions/theme-seti/icons/vs-seti-icon-theme.json
Expand Up @@ -1666,6 +1666,9 @@
"gruntfile.coffee": "_grunt",
"gulpfile": "_gulp",
"gulpfile.js": "_gulp",
"gulpfile.mjs": "_gulp",
"gulpfile.cjs": "_gulp",
"gulpfile.esm.js": "_gulp",
"ionic.config.json": "_ionic",
"ionic.project": "_ionic",
"platformio.ini": "_platformio",
Expand Down Expand Up @@ -2099,4 +2102,4 @@
}
},
"version": "https://github.com/jesseweed/seti-ui/commit/4bbf2132df28c71302e305077ce20a811bf7d64b"
}
}