Get current filename in Babel Plugin? - babeljs

I'm attempting to write a plugin for babel, and am needing the filename of the current file that is being parsed. I know the lines of the code are passed in, but I haven't managed to find a reference to the filename. Any help??
For instance given this code what could I do
export default function({ types: t }) {
return {
visitor: {
Identifier(path) {
// something here??
}
}
};
}

You can you this or use the 2nd parameter in a visitor (state)
Identifier(path, state) {
console.log(state.file.opts.filename);
}

For any future viewers, you can use this.file.opts.filename in a visitor function

Related

How to remove the fbclid paramter in SvelteKit

at the moment, the issue is that Facebook fbclid queries look atrocious on my otherwise very nice URLs.
I WANT THEM GONE
solution below
the solution that i could find was to use a handle hook to remove it if it's there.
import type { Handle } from '#sveltejs/kit';
export const handle: Handle = ({ event, resolve }) => {
let assign: any = {};
if (event.request.url.match(/\?fbclid=.+/)) {
assign = {
redirected: true,
headers: {
Location: event.request.url.replace(/[\?&]fbclid=[^&]+/, '')
}
};
}
let r = resolve(event);
Object.assign(r, assign);
return r;
};
the key part of this code here is the /[\\?&]fbclid=[^&]+/ which allows other query parameters to exist, this will only remove the fbclid parameter as shown on regexr
I hope this helps :)

What vs command opens files in vscode from URI paths?

I have an array with paths to files in the workspace.
I would like to execute a command that opens all of these files. Which command do I use?
Here is an example of an array with my paths:
["/c:/Users/User/Desktop/Kod/extension/src/home.ts", /c:/Users/User/Desktop/Kod/extension/src/main.ts]
I send these paths from a webview that executes this function:
webviewView.webview.onDidReceiveMessage(async (data) => {
const { tabPaths, name, isOpen } = data.value;
switch (data.type) {
case "onOpenTabs": {
if (!data.value || !tabPaths) {
return;
}
tabPaths.forEach(path => {
vscode.commands.executeCommand("vscode.open", path);
});
break;
}
});
I can confirm that I get the paths in my onDidReceiveMessages.
I then try the vscode.open command but I get this error message:
Is it the wrong command? Can I do something else?
Ah! ok. Thanks to Mark and rioV8 I know the answer. I didn't save a valid textdocument.
Instead I just save an array of vscode.workspace.textDocuments as is. Like so:
const paths = vscode.workspace.textDocuments.map(
(doc) => doc
);
Then open them with vscode.window.showTextDocument instead of vscode.commands.executeCommand. Like so:
paths.forEach(doc => {
vscode.window.showTextDocument(doc);
});
So simple and it works. Thanks.

Unable to add tasks from the provideTasks function

Following on from this question I have another question about how to implement the provideTasks method of the registerTaskProvider.
Using the npm extension as an example I have tried to implement a basic function, to simply return a single, hard-coded, task. This would then be extended to actually parse a file, ready to add dynamic tasks. However, I have been unable to get this to work.
The code that I am trying is:
vscode.workspace.findFiles('**/*.cake').then((files) => {
if (files.length === 0) {
return emptyTasks;
}
try {
const result: vscode.Task[] = [];
result.push(new vscode.Task({type: 'cake', script: 'NuGet-Restore'} as CakeTaskDefinition, 'Nuget-Restore', 'cake', new vscode.ShellExecution('npm install'), []));
console.log(result);
return Promise.resolve(result);
} catch (e) {
return Promise.resolve(emptyTasks);
}
});
Even though I can see that result contains a Task, I don't see it populated in the Task drop down list.
Can anyone offer any help in why this is not working?
A repository with the current code can be found here.
UPDATE
I have just edited the above code to be the following:
try {
const result: vscode.Task[] = [];
result.push(new vscode.Task({ type: 'cake', script: 'NuGet-Restore' } as CakeTaskDefinition, 'Nuget-Restore', 'cake', new vscode.ShellExecution('npm install'), []));
console.log(result);
return Promise.resolve(result);
} catch (e) {
return Promise.resolve(emptyTasks);
}
By not including the initial findFiles function, it correctly populates the Task Menu with the single hard-coded Task. Why is it that I can't do the return from within the findFiles method? I now suspect that this is a TypeScript/JavaScript problem, rather than one with the provideTasks function, but I am still looking for some help on this.
What is the recommended approach for what I am trying to do? Thanks in advance!
You need to return findFiles to ensure the tasks are actually returned from the task provider:
return vscode.workspace.findFiles('**/*.cake').then((files) => {
...
});
Using "noImplicitReturns": true in your tsconfig.json—or, even better, "strict": true—can help catch bugs like this

Can I prevent Babel from traversing code inserted by a plugin?

I'm building a plugin that inserts enterFunction() in front of every existing function call by calling path.insertBefore. So my code is transformed from:
myFunction();
To:
enterFunction();
myFunction();
The problem is that when I insert the node Babel once again traverses the inserted node. Here's the logging output:
'CallExpression', 'myFunction'
'CallExpression', 'enterFunction'
How can I prevent Babel from entering the enterFunction call expression and its children?
This is the code I'm currently using for my Babel plugin:
function(babel) {
return {
visitor: {
CallExpression: function(path) {
console.log("CallExpression", path.node.callee.name)
if (path.node.ignore) {
return;
}
path.node.ignore = true
var enterCall = babel.types.callExpression(
babel.types.identifier("enterFunction"), []
)
enterCall.ignore = true;
path.insertBefore(enterCall)
}
}
}
}
The Babel Handbook mentions the following section:
If your plugin needs to not run in a certain situation, the simpliest thing to do is to write an early return.
BinaryExpression(path) {
if (path.node.operator !== '**') return;
}
If you are doing a sub-traversal in a top level path, you can use 2 provided API methods:
path.skip() skips traversing the children of the current path. path.stop() stops traversal entirely.
outerPath.traverse({
Function(innerPath) {
innerPath.skip(); // if checking the children is irrelevant
},
ReferencedIdentifier(innerPath, state) {
state.iife = true;
innerPath.stop(); // if you want to save some state and then stop traversal, or deopt
}
});
In short, use path.skip() to skip traversing the children of the current path.
One application of this method is illustrated in this snippet using Visitors, CallExpression and skip():
export default function (babel) {
const { types: t } = babel;
return {
name: "ast-transform", // not required
visitor: {
CallExpression(path) {
path.replaceWith(t.blockStatement([
t.expressionStatement(t.yieldExpression(path.node))
]));
path.skip();
}
}
};
}

Passing Chrome FileSystem API FileEntry to Web worker

I'm trying to use a WebWorker to parse certain files from a directory the user selected, like so:
function readEntries(reader, callback) {
reader.readEntries(function(results) {
results.forEach(function(entry) {
if (entry.isDirectory) { readEntries(entry.createReader(), callback); }
else { callback(entry); }
});
});
}
readEntries(initialDir.createReader(), function(entry) {
var nodeWorker = new Worker('worker.js');
nodeWorker.onmessage = function(e) { /* do stuff */ }
nodeWorker.postMessage(entry);
});
The initialDir is a DirectoryEntry from chrome.fileSystem.chooseEntry({'type': 'openDirectory'}, ....
The corresponding worker.js would use FileReaderSync to parse the passed file(s) and pass analysis results back to /* do stuff */.
If I execute this, I get the following DOMException:
Error: Failed to execute 'postMessage' on 'Worker': An object could not be cloned.
Since entry.toURL() returns an empty string, how am I supposed to pass local, unsandboxed files to the web worker? Is there any other way to achieve what I want?