Skip to content

Commit

Permalink
Run prettier on the code
Browse files Browse the repository at this point in the history
  • Loading branch information
charlespwd committed Jan 10, 2025
1 parent 46a5475 commit e9b69f7
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 70 deletions.
12 changes: 8 additions & 4 deletions packages/vscode-extension/src/node/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ export async function activate(context: ExtensionContext) {
);
context.subscriptions.push(
commands.registerCommand('shopifyLiquid.openPreview', async () => {
const config = new Config({projectName: 'shopify-cli-theme-conf'});
const config = new Config({ projectName: 'shopify-cli-theme-conf' });
const storeUrl = config.get('themeStore');

if (!storeUrl) {
window.showErrorMessage('Make sure Shopify is CLI is available in your environment and authenticated');
window.showErrorMessage(
'Make sure Shopify is CLI is available in your environment and authenticated',
);
return;
}

Expand All @@ -59,10 +61,12 @@ export async function activate(context: ExtensionContext) {
try {
await liquidProfiler.showProfileForUrl(url);
} catch (error) {
window.showErrorMessage('Could not establish a profile for this URL. Check that you can execute `shopify theme profile` in your terminal');
window.showErrorMessage(
'Could not establish a profile for this URL. Check that you can execute `shopify theme profile` in your terminal',
);
}
}
})
}),
);

await startServer(context);
Expand Down
107 changes: 67 additions & 40 deletions packages/vscode-extension/src/node/liquid_profiler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { Disposable, ExtensionContext, Uri, ViewColumn, WebviewPanel, window, workspace, Range, DecorationOptions, Position } from 'vscode';
import {
Disposable,
ExtensionContext,
Uri,
ViewColumn,
WebviewPanel,
window,
workspace,
Range,
DecorationOptions,
Position,
} from 'vscode';
import * as path from 'node:path';
import { execSync } from 'node:child_process';

Expand All @@ -21,9 +32,9 @@ export class LiquidProfiler {
margin: '0 0 1rem 0',
textDecoration: 'none',
},
rangeBehavior: 1 // DecorationRangeBehavior.ClosedOpen
rangeBehavior: 1, // DecorationRangeBehavior.ClosedOpen
});

private lineDecorationType = window.createTextEditorDecorationType({
backgroundColor: 'rgba(173, 216, 230, 0.2)',
border: '1px solid rgba(173, 216, 230, 0.5)',
Expand Down Expand Up @@ -53,19 +64,16 @@ export class LiquidProfiler {
this._panel.title = `Liquid Profile: ${url}`;
this._panel.webview.html = '';
} else {
this._panel = window.createWebviewPanel(
'liquidProfile',
`Liquid Profile: ${url}`,
column,
{
enableScripts: true,
// Allow files in the user's workspace (.tmp directory) to be used as local resources
localResourceRoots: [
...(workspace.workspaceFolders ? workspace.workspaceFolders.map(folder => folder.uri) : []),
Uri.file(this._context.asAbsolutePath(path.join('dist', 'node', 'speedscope')))
]
}
);
this._panel = window.createWebviewPanel('liquidProfile', `Liquid Profile: ${url}`, column, {
enableScripts: true,
// Allow files in the user's workspace (.tmp directory) to be used as local resources
localResourceRoots: [
...(workspace.workspaceFolders
? workspace.workspaceFolders.map((folder) => folder.uri)
: []),
Uri.file(this._context.asAbsolutePath(path.join('dist', 'node', 'speedscope'))),
],
});
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
}

Expand All @@ -78,7 +86,9 @@ export class LiquidProfiler {
}

private async _getSpeedscopeHtml(profileContents: string) {
const indexHtmlPath = Uri.file(this._context.asAbsolutePath(path.join('dist', 'node', 'speedscope', 'index.html')));
const indexHtmlPath = Uri.file(
this._context.asAbsolutePath(path.join('dist', 'node', 'speedscope', 'index.html')),
);
let htmlContent = Buffer.from(await workspace.fs.readFile(indexHtmlPath)).toString('utf8');

// Convert local resource paths to vscode-resource URIs, and replace the paths in the HTML content
Expand All @@ -96,8 +106,12 @@ export class LiquidProfiler {
const tmpFile = path.join(tmpDir!, '.tmp', 'profile.json');
await workspace.fs.writeFile(Uri.file(tmpFile), Buffer.from(profileContents));
const tmpUri = this._panel!.webview.asWebviewUri(Uri.file(tmpFile));
htmlContent = htmlContent.replace('<body>', `<body><script>window.location.hash = "profileURL=${encodeURIComponent
(tmpUri.toString())}";</script>`);
htmlContent = htmlContent.replace(
'<body>',
`<body><script>window.location.hash = "profileURL=${encodeURIComponent(
tmpUri.toString(),
)}";</script>`,
);

return htmlContent;
}
Expand All @@ -116,7 +130,7 @@ export class LiquidProfiler {
/**
* Calculate the execution times for each file and line in the profile.
* @param profile - The parsed profile data.
* @returns An object containing two maps:
* @returns An object containing two maps:
* fileExecutionTimes: Map<string, number> - The execution time for each file.
* lineExecutionTimes: Map<number, number> - The execution time for each line.
*/
Expand All @@ -125,7 +139,7 @@ export class LiquidProfiler {
const lineExecutionTimes = new Map<SharedProfileFrame, number>();
const openEvents = new Map<number, number>();

profile.profiles[0].events.forEach(event => {
profile.profiles[0].events.forEach((event) => {
const frameId = event.frame;
const frame = profile.shared.frames[frameId];

Expand All @@ -136,7 +150,10 @@ export class LiquidProfiler {
if (startTime !== undefined) {
const duration = event.at - startTime;

if (frame.file && (frame.file.startsWith('sections/') || frame.file.startsWith('snippets/'))) {
if (
frame.file &&
(frame.file.startsWith('sections/') || frame.file.startsWith('snippets/'))
) {
let current = lineExecutionTimes.get(frame) || 0;
lineExecutionTimes.set(frame, current + duration);

Expand Down Expand Up @@ -169,8 +186,8 @@ export class LiquidProfiler {

const { fileExecutionTimes, lineExecutionTimes } = this.calculateExecutionTimes(parsedProfile);

// Check if there are any workspace folders.
// TODO: Is this necessary?
// Check if there are any workspace folders.
// TODO: Is this necessary?
const workspaceFolders = workspace.workspaceFolders;
if (!workspaceFolders) {
console.error('[Liquid Profiler] No workspace folders found');
Expand All @@ -193,8 +210,8 @@ export class LiquidProfiler {
after: {
contentText: ` (File) ⏱️ ${(duration / 1000000).toFixed(2)}ms`,
color: this.getColorForDuration(duration),
}
}
},
},
};

// Store the file-level decoration.
Expand All @@ -204,15 +221,24 @@ export class LiquidProfiler {
// Store the paths it's been applied to in a set.
const appliedPaths = new Set<string>();
for (const editor of visibleEditors) {
if (editor.document.uri.fsPath === uri.fsPath && !appliedPaths.has(editor.document.uri.fsPath)) {
console.log(`[Liquid Profiler] Applying file decoration for ${liquidFile} (${(duration / 1000000).toFixed(2)}ms)
if (
editor.document.uri.fsPath === uri.fsPath &&
!appliedPaths.has(editor.document.uri.fsPath)
) {
console.log(`[Liquid Profiler] Applying file decoration for ${liquidFile} (${(
duration / 1000000
).toFixed(2)}ms)
`);
editor.setDecorations(this.fileDecorationType, [decoration]);
appliedPaths.add(editor.document.uri.fsPath);
}
}

console.log(`[Liquid Profiler] Created file decoration for ${liquidFile} (${(duration / 1000000).toFixed(2)}ms)`);
console.log(
`[Liquid Profiler] Created file decoration for ${liquidFile} (${(
duration / 1000000
).toFixed(2)}ms)`,
);
} catch (err) {
console.error(`[Liquid Profiler] Error creating file decoration for ${fullPath}:`, err);
}
Expand All @@ -223,19 +249,19 @@ export class LiquidProfiler {
try {
const uri = Uri.file(path.join(rootPath, `${frame.file}.liquid`));
const document = await workspace.openTextDocument(uri);
// If frame.name starts with 'variable:', then scan the line for the variable name after "variable:" and find the
// If frame.name starts with 'variable:', then scan the line for the variable name after "variable:" and find the
// range immediately after the variable name to apply the decoration to
let range: Range | undefined;
if (frame.name.startsWith('variable:') || frame.name.startsWith('tag:')) {
const variableName = frame.name.split('variable:')[1] || frame.name.split('tag:')[1];
const variableName = frame.name.split('variable:')[1] || frame.name.split('tag:')[1];
const line = document.lineAt(frame.line - 1);
const variableRange = line.text.indexOf(variableName);// 7
const variableRange = line.text.indexOf(variableName); // 7

if (variableRange !== -1) {
// Create range that covers the variable name itself using explicit positions
range = new Range(
new Position(line.lineNumber, variableRange),
new Position(line.lineNumber, variableRange + variableName.length)
new Position(line.lineNumber, variableRange + variableName.length),
);
} else {
// Fallback to full line if variable name not found
Expand All @@ -249,16 +275,18 @@ export class LiquidProfiler {
}
const decoration: DecorationOptions = {
range: range!,
renderOptions: { after: { contentText: ` ⏱️ ${(duration / 1000000).toFixed(2)}ms` } }
renderOptions: { after: { contentText: ` ⏱️ ${(duration / 1000000).toFixed(2)}ms` } },
};

// Store the decoration in a map where the key is the file path and the value is an array of decorations
const fileDecorations = this._decorations.get(uri.fsPath) || [];
fileDecorations.push(decoration);
this._decorations.set(uri.fsPath, fileDecorations);

} catch (err) {
console.error(`[Liquid Profiler] Error creating line decoration for ${frame.file}:${frame.line}:`, err);
console.error(
`[Liquid Profiler] Error creating line decoration for ${frame.file}:${frame.line}:`,
err,
);
}
}

Expand All @@ -272,7 +300,7 @@ export class LiquidProfiler {

// Add listener for active editor changes
this._context.subscriptions.push(
window.onDidChangeActiveTextEditor(editor => {
window.onDidChangeActiveTextEditor((editor) => {
if (editor) {
const decorations = this._decorations.get(editor.document.uri.fsPath);
if (decorations) {
Expand All @@ -282,7 +310,7 @@ export class LiquidProfiler {
editor.setDecorations(this.fileDecorationType, []);
}
}
})
}),
);
}

Expand All @@ -292,7 +320,7 @@ export class LiquidProfiler {
if (ms < 10) {
// Fast: Green
return '#4caf50';
}
}
if (ms < 50) {
// Medium: Yellow
return '#ffc107';
Expand Down Expand Up @@ -325,4 +353,3 @@ export class LiquidProfiler {
}
}
}

59 changes: 33 additions & 26 deletions packages/vscode-extension/src/node/test/liquid_profiler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,16 @@ vi.mock('node:child_process', () => ({

describe('LiquidProfiler', () => {
let profiler: LiquidProfiler;

beforeEach(() => {
const mockContext = {
subscriptions: [],
asAbsolutePath: (path: string) => path,
} as unknown as ExtensionContext;

profiler = new LiquidProfiler(mockContext);
});


describe('getProfileContents', () => {
it('successfully retrieves profile content', () => {
const mockJson = '{"profiles":[{"events":[]}]}';
Expand Down Expand Up @@ -361,35 +360,43 @@ describe('LiquidProfiler', () => {
const executionTimes = profiler['calculateExecutionTimes'](profile);

expect(executionTimes).toEqual({
'fileExecutionTimes': new Map([
['sections/single-collection.liquid', 949434],
fileExecutionTimes: new Map([
['sections/single-collection.liquid', 949434],
['snippets/collection-item.liquid', 90944],
]),
'lineExecutionTimes': new Map([
[{
file: 'sections/single-collection',
line: 7,
name: 'variable:\'favicon.png\' | asset_url',
}, 249384],
[{
file: 'sections/single-collection',
line: 13,
name: 'variable:child.system.url',
}, 700050],
[{
file: 'snippets/collection-item',
line: 15,
name: 'variable:child.name',
}, 90944],
])
lineExecutionTimes: new Map([
[
{
file: 'sections/single-collection',
line: 7,
name: "variable:'favicon.png' | asset_url",
},
249384,
],
[
{
file: 'sections/single-collection',
line: 13,
name: 'variable:child.system.url',
},
700050,
],
[
{
file: 'snippets/collection-item',
line: 15,
name: 'variable:child.name',
},
90944,
],
]),
});
});

it('handles invalid profile data gracefully', async () => {
const invalidProfileData = 'invalid json';

await expect(profiler['processAndShowDecorations'](invalidProfileData))
.rejects.toThrow();

await expect(profiler['processAndShowDecorations'](invalidProfileData)).rejects.toThrow();
});
});
});
});

0 comments on commit e9b69f7

Please sign in to comment.