@shopify/theme-language-server-common
Version:
<h1 align="center" style="position: relative;" > <br> <img src="https://github.com/Shopify/theme-check-vscode/blob/main/images/shopify_glyph.png?raw=true" alt="logo" width="141" height="160"> <br> Theme Language Server </h1>
112 lines (104 loc) • 4.15 kB
text/typescript
import {
GetDocDefinitionForURI,
MetafieldDefinitionMap,
SourceCodeType,
ThemeDocset,
} from '@shopify/theme-check-common';
import { CompletionItem, CompletionParams } from 'vscode-languageserver';
import { TypeSystem } from '../TypeSystem';
import { DocumentManager } from '../documents';
import { GetThemeSettingsSchemaForURI } from '../settings';
import { GetTranslationsForURI } from '../translations';
import { createLiquidCompletionParams } from './params';
import {
ContentForCompletionProvider,
ContentForBlockTypeCompletionProvider,
ContentForParameterCompletionProvider,
FilterCompletionProvider,
FilterNamedParameterCompletionProvider,
GetSnippetNamesForURI,
HtmlAttributeCompletionProvider,
HtmlAttributeValueCompletionProvider,
HtmlTagCompletionProvider,
LiquidDocParamTypeCompletionProvider,
LiquidDocTagCompletionProvider,
LiquidTagsCompletionProvider,
ObjectAttributeCompletionProvider,
ObjectCompletionProvider,
Provider,
RenderSnippetCompletionProvider,
RenderSnippetParameterCompletionProvider,
TranslationCompletionProvider,
} from './providers';
export interface CompletionProviderDependencies {
documentManager: DocumentManager;
themeDocset: ThemeDocset;
getTranslationsForURI?: GetTranslationsForURI;
getSnippetNamesForURI?: GetSnippetNamesForURI;
getThemeSettingsSchemaForURI?: GetThemeSettingsSchemaForURI;
getMetafieldDefinitions: (rootUri: string) => Promise<MetafieldDefinitionMap>;
getDocDefinitionForURI?: GetDocDefinitionForURI;
getThemeBlockNames?: (rootUri: string, includePrivate: boolean) => Promise<string[]>;
log?: (message: string) => void;
}
export class CompletionsProvider {
private providers: Provider[] = [];
readonly documentManager: DocumentManager;
readonly themeDocset: ThemeDocset;
readonly log: (message: string) => void;
constructor({
documentManager,
themeDocset,
getMetafieldDefinitions,
getTranslationsForURI = async () => ({}),
getSnippetNamesForURI = async () => [],
getThemeSettingsSchemaForURI = async () => [],
getDocDefinitionForURI = async (uri, _relativePath) => ({ uri }),
getThemeBlockNames = async (_rootUri: string, _includePrivate: boolean) => [],
log = () => {},
}: CompletionProviderDependencies) {
this.documentManager = documentManager;
this.themeDocset = themeDocset;
this.log = log;
const typeSystem = new TypeSystem(
themeDocset,
getThemeSettingsSchemaForURI,
getMetafieldDefinitions,
);
this.providers = [
new ContentForCompletionProvider(),
new ContentForBlockTypeCompletionProvider(getThemeBlockNames),
new ContentForParameterCompletionProvider(getDocDefinitionForURI),
new HtmlTagCompletionProvider(),
new HtmlAttributeCompletionProvider(documentManager),
new HtmlAttributeValueCompletionProvider(),
new LiquidTagsCompletionProvider(themeDocset),
new ObjectCompletionProvider(typeSystem),
new ObjectAttributeCompletionProvider(typeSystem, getThemeSettingsSchemaForURI),
new FilterCompletionProvider(typeSystem),
new TranslationCompletionProvider(documentManager, getTranslationsForURI),
new RenderSnippetCompletionProvider(getSnippetNamesForURI),
new RenderSnippetParameterCompletionProvider(getDocDefinitionForURI),
new FilterNamedParameterCompletionProvider(themeDocset),
new LiquidDocTagCompletionProvider(),
new LiquidDocParamTypeCompletionProvider(themeDocset),
];
}
async completions(params: CompletionParams): Promise<CompletionItem[]> {
const uri = params.textDocument.uri;
const document = this.documentManager.get(uri);
// Supports only Liquid resources
if (document?.type !== SourceCodeType.LiquidHtml) {
return [];
}
try {
const liquidParams = createLiquidCompletionParams(document, params);
const promises = this.providers.map((p) => p.completions(liquidParams));
const results = await Promise.all(promises);
return results.flat();
} catch (err) {
this.log(`[SERVER] CompletionsProvider error: ${err}`);
return [];
}
}
}