Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/theme-check-common/src/AugmentedThemeDocset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ export class AugmentedThemeDocset implements ThemeDocset {

public isAugmented = true;

private objectsByPrefix = new Map<string, ObjectEntry[]>();

setObjectsForURI(uri: string, objects: ObjectEntry[]) {
this.objectsByPrefix.set(uri, objects);
}

getObjectsForURI(uri: string): ObjectEntry[] | undefined {
// Exact match first
const exact = this.objectsByPrefix.get(uri);
if (exact) return exact;

// Prefix match: allows registering by step path and matching file URIs within it
for (const [prefix, objects] of this.objectsByPrefix) {
if (uri.startsWith(prefix)) return objects;
}

return undefined;
}

filters = memo(async (): Promise<FilterEntry[]> => {
const officialFilters = await this.themeDocset.filters();
return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ export const UndefinedObject: LiquidCheckDefinition = {
},

async onCodePathEnd() {
const objects = await globalObjects(themeDocset, relativePath);
const objects = await globalObjects(themeDocset, relativePath, context.file.uri);

objects.forEach((obj) => fileScopedVariables.add(obj.name));

Expand All @@ -172,8 +172,9 @@ export const UndefinedObject: LiquidCheckDefinition = {
},
};

async function globalObjects(themeDocset: ThemeDocset, relativePath: string) {
const objects = await themeDocset.objects();
async function globalObjects(themeDocset: ThemeDocset, relativePath: string, uri?: string) {
const perURI = uri ? themeDocset.getObjectsForURI?.(uri) : undefined;
const objects = perURI ?? (await themeDocset.objects());
const contextualObjects = getContextualObjects(relativePath);

const globalObjects = objects.filter(({ access, name }) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/theme-check-common/src/types/theme-liquid-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export interface ThemeDocset {

/** Returns system translations available on themes. */
systemTranslations(): Promise<Translations>;

/** Returns objects scoped to a specific URI, if available. */
getObjectsForURI?(uri: string): ObjectEntry[] | undefined;
}

/** A URI that will uniquely describe the schema */
Expand Down
27 changes: 15 additions & 12 deletions packages/theme-language-server-common/src/TypeSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export class TypeSystem {
*/
public objectMap = async (uri: string, ast: LiquidHtmlNode): Promise<ObjectMap> => {
const [objectMap, themeSettingProperties, metafieldDefinitionsObjectMap] = await Promise.all([
this._objectMap(),
this._objectMap(uri),
this.themeSettingProperties(uri),
this.metafieldDefinitionsObjectMap(uri),
]);
Expand Down Expand Up @@ -257,14 +257,13 @@ export class TypeSystem {
return result;
}

// This is the big one we reuse (memoized)
private _objectMap = memo(async (): Promise<ObjectMap> => {
const entries = await this.objectEntries();
private async _objectMap(uri?: string): Promise<ObjectMap> {
const entries = await this.objectEntries(uri);
return entries.reduce((map, entry) => {
map[entry.name] = entry;
return map;
}, {} as ObjectMap);
});
}

/** An indexed representation of filters.json by name */
public filtersMap = memo(async (): Promise<FiltersMap> => {
Expand All @@ -279,9 +278,13 @@ export class TypeSystem {
return this.themeDocset.filters();
});

public objectEntries = memo(async () => {
public async objectEntries(uri?: string): Promise<ObjectEntry[]> {
if (uri && this.themeDocset.getObjectsForURI) {
const perURI = this.themeDocset.getObjectsForURI(uri);
if (perURI) return perURI;
}
return this.themeDocset.objects();
});
}

private async symbolsTable(partialAst: LiquidHtmlNode, uri: string): Promise<SymbolsTable> {
const seedSymbolsTable = await this.seedSymbolsTable(uri);
Expand All @@ -299,7 +302,7 @@ export class TypeSystem {
*/
private seedSymbolsTable = async (uri: string) => {
const [globalVariables, contextualVariables] = await Promise.all([
this.globalVariables(),
this.globalVariables(uri),
this.contextualVariables(uri),
]);
return globalVariables.concat(contextualVariables).reduce((table, objectEntry) => {
Expand All @@ -313,15 +316,15 @@ export class TypeSystem {
}, {} as SymbolsTable);
};

private globalVariables = memo(async () => {
const entries = await this.objectEntries();
private globalVariables = async (uri?: string) => {
const entries = await this.objectEntries(uri);
return entries.filter(
(entry) => !entry.access || entry.access.global === true || entry.access.template.length > 0,
);
});
};

private contextualVariables = async (uri: string) => {
const entries = await this.objectEntries();
const entries = await this.objectEntries(uri);
const contextualEntries = getContextualEntries(uri);
return entries.filter((entry) => contextualEntries.includes(entry.name));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { RenameHandler } from '../renamed/RenameHandler';
import { GetTranslationsForURI } from '../translations';
import {
Dependencies,
SetObjectsNotification,
ThemeGraphDeadCodeRequest,
ThemeGraphDependenciesRequest,
ThemeGraphReferenceRequest,
Expand Down Expand Up @@ -756,5 +757,9 @@ export function startServer(
return deadFiles;
});

connection.onNotification(SetObjectsNotification.type, ({ uri, objects }) => {
themeDocset.setObjectsForURI(uri, objects);
});

connection.listen();
}
10 changes: 10 additions & 0 deletions packages/theme-language-server-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
AbstractFileSystem,
Config,
Dependencies as ThemeCheckDependencies,
ObjectEntry,
} from '@shopify/theme-check-common';
import { URI } from 'vscode-languageserver';
import * as rpc from 'vscode-jsonrpc';
Expand Down Expand Up @@ -148,6 +149,15 @@ export namespace ThemeGraphDidUpdateNotification {
}
}

export namespace SetObjectsNotification {
export const method = 'shopify/setObjects';
export interface Params {
uri: string;
objects: ObjectEntry[];
}
export const type = new rpc.NotificationType<Params>(method);
}

export type AugmentedLocationWithExistence = {
uri: string;
range: undefined;
Expand Down