@platformos/platformos-language-server-common 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +87 -0
- package/dist/ClientCapabilities.d.ts +14 -0
- package/dist/ClientCapabilities.js +52 -0
- package/dist/ClientCapabilities.js.map +1 -0
- package/dist/PropertyShapeInference.d.ts +57 -0
- package/dist/PropertyShapeInference.js +336 -0
- package/dist/PropertyShapeInference.js.map +1 -0
- package/dist/TypeSystem.d.ts +94 -0
- package/dist/TypeSystem.js +1481 -0
- package/dist/TypeSystem.js.map +1 -0
- package/dist/VariableShapeExtractor.d.ts +14 -0
- package/dist/VariableShapeExtractor.js +283 -0
- package/dist/VariableShapeExtractor.js.map +1 -0
- package/dist/codeActions/BaseCodeActionsProvider.d.ts +11 -0
- package/dist/codeActions/BaseCodeActionsProvider.js +14 -0
- package/dist/codeActions/BaseCodeActionsProvider.js.map +1 -0
- package/dist/codeActions/CodeActionsProvider.d.ts +9 -0
- package/dist/codeActions/CodeActionsProvider.js +22 -0
- package/dist/codeActions/CodeActionsProvider.js.map +1 -0
- package/dist/codeActions/index.d.ts +1 -0
- package/dist/codeActions/index.js +7 -0
- package/dist/codeActions/index.js.map +1 -0
- package/dist/codeActions/providers/FixAllProvider.d.ts +23 -0
- package/dist/codeActions/providers/FixAllProvider.js +52 -0
- package/dist/codeActions/providers/FixAllProvider.js.map +1 -0
- package/dist/codeActions/providers/FixProvider.d.ts +6 -0
- package/dist/codeActions/providers/FixProvider.js +72 -0
- package/dist/codeActions/providers/FixProvider.js.map +1 -0
- package/dist/codeActions/providers/GenerateDocBlockProvider.d.ts +10 -0
- package/dist/codeActions/providers/GenerateDocBlockProvider.js +39 -0
- package/dist/codeActions/providers/GenerateDocBlockProvider.js.map +1 -0
- package/dist/codeActions/providers/SuggestionProvider.d.ts +6 -0
- package/dist/codeActions/providers/SuggestionProvider.js +41 -0
- package/dist/codeActions/providers/SuggestionProvider.js.map +1 -0
- package/dist/codeActions/providers/index.d.ts +3 -0
- package/dist/codeActions/providers/index.js +10 -0
- package/dist/codeActions/providers/index.js.map +1 -0
- package/dist/codeActions/providers/utils.d.ts +20 -0
- package/dist/codeActions/providers/utils.js +29 -0
- package/dist/codeActions/providers/utils.js.map +1 -0
- package/dist/commands/BaseExecuteCommandProvider.d.ts +13 -0
- package/dist/commands/BaseExecuteCommandProvider.js +13 -0
- package/dist/commands/BaseExecuteCommandProvider.js.map +1 -0
- package/dist/commands/ExecuteCommandProvider.d.ts +11 -0
- package/dist/commands/ExecuteCommandProvider.js +30 -0
- package/dist/commands/ExecuteCommandProvider.js.map +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +9 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/providers/ApplyFixesProvider.d.ts +19 -0
- package/dist/commands/providers/ApplyFixesProvider.js +69 -0
- package/dist/commands/providers/ApplyFixesProvider.js.map +1 -0
- package/dist/commands/providers/ApplySuggestionProvider.d.ts +19 -0
- package/dist/commands/providers/ApplySuggestionProvider.js +73 -0
- package/dist/commands/providers/ApplySuggestionProvider.js.map +1 -0
- package/dist/commands/providers/GenerateDocBlockCommandProvider.d.ts +19 -0
- package/dist/commands/providers/GenerateDocBlockCommandProvider.js +64 -0
- package/dist/commands/providers/GenerateDocBlockCommandProvider.js.map +1 -0
- package/dist/commands/providers/RunChecksProvider.d.ts +26 -0
- package/dist/commands/providers/RunChecksProvider.js +32 -0
- package/dist/commands/providers/RunChecksProvider.js.map +1 -0
- package/dist/commands/providers/index.d.ts +3 -0
- package/dist/commands/providers/index.js +12 -0
- package/dist/commands/providers/index.js.map +1 -0
- package/dist/completions/CompletionsProvider.d.ts +35 -0
- package/dist/completions/CompletionsProvider.js +55 -0
- package/dist/completions/CompletionsProvider.js.map +1 -0
- package/dist/completions/index.d.ts +1 -0
- package/dist/completions/index.js +6 -0
- package/dist/completions/index.js.map +1 -0
- package/dist/completions/params/LiquidCompletionParams.d.ts +24 -0
- package/dist/completions/params/LiquidCompletionParams.js +436 -0
- package/dist/completions/params/LiquidCompletionParams.js.map +1 -0
- package/dist/completions/params/fix.d.ts +11 -0
- package/dist/completions/params/fix.js +238 -0
- package/dist/completions/params/fix.js.map +1 -0
- package/dist/completions/params/index.d.ts +2 -0
- package/dist/completions/params/index.js +8 -0
- package/dist/completions/params/index.js.map +1 -0
- package/dist/completions/providers/ContentForBlockTypeCompletionProvider.d.ts +8 -0
- package/dist/completions/providers/ContentForBlockTypeCompletionProvider.js +36 -0
- package/dist/completions/providers/ContentForBlockTypeCompletionProvider.js.map +1 -0
- package/dist/completions/providers/ContentForCompletionProvider.d.ts +7 -0
- package/dist/completions/providers/ContentForCompletionProvider.js +87 -0
- package/dist/completions/providers/ContentForCompletionProvider.js.map +1 -0
- package/dist/completions/providers/ContentForParameterCompletionProvider.d.ts +23 -0
- package/dist/completions/providers/ContentForParameterCompletionProvider.js +127 -0
- package/dist/completions/providers/ContentForParameterCompletionProvider.js.map +1 -0
- package/dist/completions/providers/FilterCompletionProvider.d.ts +21 -0
- package/dist/completions/providers/FilterCompletionProvider.js +162 -0
- package/dist/completions/providers/FilterCompletionProvider.js.map +1 -0
- package/dist/completions/providers/FilterNamedParameterCompletionProvider.d.ts +15 -0
- package/dist/completions/providers/FilterNamedParameterCompletionProvider.js +86 -0
- package/dist/completions/providers/FilterNamedParameterCompletionProvider.js.map +1 -0
- package/dist/completions/providers/HtmlAttributeCompletionProvider.d.ts +13 -0
- package/dist/completions/providers/HtmlAttributeCompletionProvider.js +83 -0
- package/dist/completions/providers/HtmlAttributeCompletionProvider.js.map +1 -0
- package/dist/completions/providers/HtmlAttributeValueCompletionProvider.d.ts +7 -0
- package/dist/completions/providers/HtmlAttributeValueCompletionProvider.js +53 -0
- package/dist/completions/providers/HtmlAttributeValueCompletionProvider.js.map +1 -0
- package/dist/completions/providers/HtmlTagCompletionProvider.d.ts +7 -0
- package/dist/completions/providers/HtmlTagCompletionProvider.js +90 -0
- package/dist/completions/providers/HtmlTagCompletionProvider.js.map +1 -0
- package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.d.ts +9 -0
- package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.js +56 -0
- package/dist/completions/providers/LiquidDocParamTypeCompletionProvider.js.map +1 -0
- package/dist/completions/providers/LiquidDocTagCompletionProvider.d.ts +8 -0
- package/dist/completions/providers/LiquidDocTagCompletionProvider.js +62 -0
- package/dist/completions/providers/LiquidDocTagCompletionProvider.js.map +1 -0
- package/dist/completions/providers/LiquidTagsCompletionProvider.d.ts +9 -0
- package/dist/completions/providers/LiquidTagsCompletionProvider.js +367 -0
- package/dist/completions/providers/LiquidTagsCompletionProvider.js.map +1 -0
- package/dist/completions/providers/ObjectAttributeCompletionProvider.d.ts +9 -0
- package/dist/completions/providers/ObjectAttributeCompletionProvider.js +71 -0
- package/dist/completions/providers/ObjectAttributeCompletionProvider.js.map +1 -0
- package/dist/completions/providers/ObjectCompletionProvider.d.ts +9 -0
- package/dist/completions/providers/ObjectCompletionProvider.js +35 -0
- package/dist/completions/providers/ObjectCompletionProvider.js.map +1 -0
- package/dist/completions/providers/PartialCompletionProvider.d.ts +9 -0
- package/dist/completions/providers/PartialCompletionProvider.js +34 -0
- package/dist/completions/providers/PartialCompletionProvider.js.map +1 -0
- package/dist/completions/providers/RenderPartialParameterCompletionProvider.d.ts +10 -0
- package/dist/completions/providers/RenderPartialParameterCompletionProvider.js +55 -0
- package/dist/completions/providers/RenderPartialParameterCompletionProvider.js.map +1 -0
- package/dist/completions/providers/TranslationCompletionProvider.d.ts +11 -0
- package/dist/completions/providers/TranslationCompletionProvider.js +78 -0
- package/dist/completions/providers/TranslationCompletionProvider.js.map +1 -0
- package/dist/completions/providers/common/CompletionItemProperties.d.ts +7 -0
- package/dist/completions/providers/common/CompletionItemProperties.js +52 -0
- package/dist/completions/providers/common/CompletionItemProperties.js.map +1 -0
- package/dist/completions/providers/common/Provider.d.ts +5 -0
- package/dist/completions/providers/common/Provider.js +3 -0
- package/dist/completions/providers/common/Provider.js.map +1 -0
- package/dist/completions/providers/common/index.d.ts +7 -0
- package/dist/completions/providers/common/index.js +17 -0
- package/dist/completions/providers/common/index.js.map +1 -0
- package/dist/completions/providers/data/contentForParameterCompletionOptions.d.ts +7 -0
- package/dist/completions/providers/data/contentForParameterCompletionOptions.js +13 -0
- package/dist/completions/providers/data/contentForParameterCompletionOptions.js.map +1 -0
- package/dist/completions/providers/index.d.ts +17 -0
- package/dist/completions/providers/index.js +36 -0
- package/dist/completions/providers/index.js.map +1 -0
- package/dist/css/CSSLanguageService.d.ts +12 -0
- package/dist/css/CSSLanguageService.js +94 -0
- package/dist/css/CSSLanguageService.js.map +1 -0
- package/dist/css/test/test-helpers.d.ts +4 -0
- package/dist/css/test/test-helpers.js +19 -0
- package/dist/css/test/test-helpers.js.map +1 -0
- package/dist/definitions/BaseDefinitionProvider.d.ts +5 -0
- package/dist/definitions/BaseDefinitionProvider.js +3 -0
- package/dist/definitions/BaseDefinitionProvider.js.map +1 -0
- package/dist/definitions/DefinitionProvider.d.ts +8 -0
- package/dist/definitions/DefinitionProvider.js +29 -0
- package/dist/definitions/DefinitionProvider.js.map +1 -0
- package/dist/definitions/providers/SchemaTranslationStringDefinitionProvider.d.ts +10 -0
- package/dist/definitions/providers/SchemaTranslationStringDefinitionProvider.js +55 -0
- package/dist/definitions/providers/SchemaTranslationStringDefinitionProvider.js.map +1 -0
- package/dist/definitions/providers/TranslationStringDefinitionProvider.d.ts +10 -0
- package/dist/definitions/providers/TranslationStringDefinitionProvider.js +48 -0
- package/dist/definitions/providers/TranslationStringDefinitionProvider.js.map +1 -0
- package/dist/diagnostics/DiagnosticsManager.d.ts +24 -0
- package/dist/diagnostics/DiagnosticsManager.js +40 -0
- package/dist/diagnostics/DiagnosticsManager.js.map +1 -0
- package/dist/diagnostics/index.d.ts +2 -0
- package/dist/diagnostics/index.js +8 -0
- package/dist/diagnostics/index.js.map +1 -0
- package/dist/diagnostics/offenseToDiagnostic.d.ts +4 -0
- package/dist/diagnostics/offenseToDiagnostic.js +68 -0
- package/dist/diagnostics/offenseToDiagnostic.js.map +1 -0
- package/dist/diagnostics/runChecks.d.ts +9 -0
- package/dist/diagnostics/runChecks.js +103 -0
- package/dist/diagnostics/runChecks.js.map +1 -0
- package/dist/docset/HtmlDocset.d.ts +35 -0
- package/dist/docset/HtmlDocset.js +39 -0
- package/dist/docset/HtmlDocset.js.map +1 -0
- package/dist/docset/MarkdownRenderer.d.ts +7 -0
- package/dist/docset/MarkdownRenderer.js +125 -0
- package/dist/docset/MarkdownRenderer.js.map +1 -0
- package/dist/docset/index.d.ts +2 -0
- package/dist/docset/index.js +22 -0
- package/dist/docset/index.js.map +1 -0
- package/dist/documentHighlights/BaseDocumentHighlightsProvider.d.ts +5 -0
- package/dist/documentHighlights/BaseDocumentHighlightsProvider.js +3 -0
- package/dist/documentHighlights/BaseDocumentHighlightsProvider.js.map +1 -0
- package/dist/documentHighlights/DocumentHighlightsProvider.d.ts +22 -0
- package/dist/documentHighlights/DocumentHighlightsProvider.js +41 -0
- package/dist/documentHighlights/DocumentHighlightsProvider.js.map +1 -0
- package/dist/documentHighlights/index.d.ts +1 -0
- package/dist/documentHighlights/index.js +7 -0
- package/dist/documentHighlights/index.js.map +1 -0
- package/dist/documentHighlights/providers/HtmlTagNameDocumentHighlightsProvider.d.ts +11 -0
- package/dist/documentHighlights/providers/HtmlTagNameDocumentHighlightsProvider.js +20 -0
- package/dist/documentHighlights/providers/HtmlTagNameDocumentHighlightsProvider.js.map +1 -0
- package/dist/documentHighlights/providers/LiquidBlockTagDocumentHighlightsProvider.d.ts +11 -0
- package/dist/documentHighlights/providers/LiquidBlockTagDocumentHighlightsProvider.js +48 -0
- package/dist/documentHighlights/providers/LiquidBlockTagDocumentHighlightsProvider.js.map +1 -0
- package/dist/documentHighlights/providers/index.d.ts +2 -0
- package/dist/documentHighlights/providers/index.js +8 -0
- package/dist/documentHighlights/providers/index.js.map +1 -0
- package/dist/documentLinks/DocumentLinksProvider.d.ts +12 -0
- package/dist/documentLinks/DocumentLinksProvider.js +78 -0
- package/dist/documentLinks/DocumentLinksProvider.js.map +1 -0
- package/dist/documentLinks/index.d.ts +1 -0
- package/dist/documentLinks/index.js +6 -0
- package/dist/documentLinks/index.js.map +1 -0
- package/dist/documents/DocumentManager.d.ts +60 -0
- package/dist/documents/DocumentManager.js +167 -0
- package/dist/documents/DocumentManager.js.map +1 -0
- package/dist/documents/index.d.ts +2 -0
- package/dist/documents/index.js +21 -0
- package/dist/documents/index.js.map +1 -0
- package/dist/documents/types.d.ts +39 -0
- package/dist/documents/types.js +11 -0
- package/dist/documents/types.js.map +1 -0
- package/dist/formatting/OnTypeFormattingProvider.d.ts +10 -0
- package/dist/formatting/OnTypeFormattingProvider.js +24 -0
- package/dist/formatting/OnTypeFormattingProvider.js.map +1 -0
- package/dist/formatting/index.d.ts +1 -0
- package/dist/formatting/index.js +6 -0
- package/dist/formatting/index.js.map +1 -0
- package/dist/formatting/providers/BracketsAutoclosingOnTypeFormattingProvider.d.ts +49 -0
- package/dist/formatting/providers/BracketsAutoclosingOnTypeFormattingProvider.js +105 -0
- package/dist/formatting/providers/BracketsAutoclosingOnTypeFormattingProvider.js.map +1 -0
- package/dist/formatting/providers/HtmlElementAutoclosingOnTypeFormattingProvider.d.ts +41 -0
- package/dist/formatting/providers/HtmlElementAutoclosingOnTypeFormattingProvider.js +105 -0
- package/dist/formatting/providers/HtmlElementAutoclosingOnTypeFormattingProvider.js.map +1 -0
- package/dist/formatting/types.d.ts +7 -0
- package/dist/formatting/types.js +3 -0
- package/dist/formatting/types.js.map +1 -0
- package/dist/hover/BaseHoverProvider.d.ts +5 -0
- package/dist/hover/BaseHoverProvider.js +3 -0
- package/dist/hover/BaseHoverProvider.js.map +1 -0
- package/dist/hover/HoverProvider.d.ts +20 -0
- package/dist/hover/HoverProvider.js +55 -0
- package/dist/hover/HoverProvider.js.map +1 -0
- package/dist/hover/index.d.ts +1 -0
- package/dist/hover/index.js +6 -0
- package/dist/hover/index.js.map +1 -0
- package/dist/hover/providers/ContentForArgumentHoverProvider.d.ts +8 -0
- package/dist/hover/providers/ContentForArgumentHoverProvider.js +37 -0
- package/dist/hover/providers/ContentForArgumentHoverProvider.js.map +1 -0
- package/dist/hover/providers/ContentForTypeHoverProvider.d.ts +8 -0
- package/dist/hover/providers/ContentForTypeHoverProvider.js +32 -0
- package/dist/hover/providers/ContentForTypeHoverProvider.js.map +1 -0
- package/dist/hover/providers/HtmlAttributeHoverProvider.d.ts +6 -0
- package/dist/hover/providers/HtmlAttributeHoverProvider.js +37 -0
- package/dist/hover/providers/HtmlAttributeHoverProvider.js.map +1 -0
- package/dist/hover/providers/HtmlAttributeValueHoverProvider.d.ts +6 -0
- package/dist/hover/providers/HtmlAttributeValueHoverProvider.js +42 -0
- package/dist/hover/providers/HtmlAttributeValueHoverProvider.js.map +1 -0
- package/dist/hover/providers/HtmlTagHoverProvider.d.ts +6 -0
- package/dist/hover/providers/HtmlTagHoverProvider.js +37 -0
- package/dist/hover/providers/HtmlTagHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidDocTagHoverProvider.d.ts +9 -0
- package/dist/hover/providers/LiquidDocTagHoverProvider.js +42 -0
- package/dist/hover/providers/LiquidDocTagHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidFilterArgumentHoverProvider.d.ts +8 -0
- package/dist/hover/providers/LiquidFilterArgumentHoverProvider.js +36 -0
- package/dist/hover/providers/LiquidFilterArgumentHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidFilterHoverProvider.d.ts +8 -0
- package/dist/hover/providers/LiquidFilterHoverProvider.js +29 -0
- package/dist/hover/providers/LiquidFilterHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidObjectAttributeHoverProvider.d.ts +9 -0
- package/dist/hover/providers/LiquidObjectAttributeHoverProvider.js +113 -0
- package/dist/hover/providers/LiquidObjectAttributeHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidObjectHoverProvider.d.ts +9 -0
- package/dist/hover/providers/LiquidObjectHoverProvider.js +72 -0
- package/dist/hover/providers/LiquidObjectHoverProvider.js.map +1 -0
- package/dist/hover/providers/LiquidTagHoverProvider.d.ts +8 -0
- package/dist/hover/providers/LiquidTagHoverProvider.js +31 -0
- package/dist/hover/providers/LiquidTagHoverProvider.js.map +1 -0
- package/dist/hover/providers/RenderPartialHoverProvider.d.ts +8 -0
- package/dist/hover/providers/RenderPartialHoverProvider.js +28 -0
- package/dist/hover/providers/RenderPartialHoverProvider.js.map +1 -0
- package/dist/hover/providers/RenderPartialParameterHoverProvider.d.ts +8 -0
- package/dist/hover/providers/RenderPartialParameterHoverProvider.js +33 -0
- package/dist/hover/providers/RenderPartialParameterHoverProvider.js.map +1 -0
- package/dist/hover/providers/TranslationHoverProvider.d.ts +13 -0
- package/dist/hover/providers/TranslationHoverProvider.js +45 -0
- package/dist/hover/providers/TranslationHoverProvider.js.map +1 -0
- package/dist/hover/providers/index.d.ts +11 -0
- package/dist/hover/providers/index.js +26 -0
- package/dist/hover/providers/index.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-types.d.ts +1 -0
- package/dist/internal-types.js +3 -0
- package/dist/internal-types.js.map +1 -0
- package/dist/json/JSONContributions.d.ts +25 -0
- package/dist/json/JSONContributions.js +99 -0
- package/dist/json/JSONContributions.js.map +1 -0
- package/dist/json/JSONLanguageService.d.ts +27 -0
- package/dist/json/JSONLanguageService.js +171 -0
- package/dist/json/JSONLanguageService.js.map +1 -0
- package/dist/json/RequestContext.d.ts +22 -0
- package/dist/json/RequestContext.js +14 -0
- package/dist/json/RequestContext.js.map +1 -0
- package/dist/json/completions/JSONCompletionProvider.d.ts +30 -0
- package/dist/json/completions/JSONCompletionProvider.js +3 -0
- package/dist/json/completions/JSONCompletionProvider.js.map +1 -0
- package/dist/json/completions/providers/BlockSettingsPropertyCompletionProvider.d.ts +44 -0
- package/dist/json/completions/providers/BlockSettingsPropertyCompletionProvider.js +98 -0
- package/dist/json/completions/providers/BlockSettingsPropertyCompletionProvider.js.map +1 -0
- package/dist/json/completions/providers/BlockTypeCompletionProvider.d.ts +35 -0
- package/dist/json/completions/providers/BlockTypeCompletionProvider.js +97 -0
- package/dist/json/completions/providers/BlockTypeCompletionProvider.js.map +1 -0
- package/dist/json/completions/providers/ReferencedBlockTypeCompletionProvider.d.ts +34 -0
- package/dist/json/completions/providers/ReferencedBlockTypeCompletionProvider.js +95 -0
- package/dist/json/completions/providers/ReferencedBlockTypeCompletionProvider.js.map +1 -0
- package/dist/json/completions/providers/SchemaTranslationCompletionProvider.d.ts +9 -0
- package/dist/json/completions/providers/SchemaTranslationCompletionProvider.js +46 -0
- package/dist/json/completions/providers/SchemaTranslationCompletionProvider.js.map +1 -0
- package/dist/json/completions/providers/SettingsPropertyCompletionProvider.d.ts +33 -0
- package/dist/json/completions/providers/SettingsPropertyCompletionProvider.js +64 -0
- package/dist/json/completions/providers/SettingsPropertyCompletionProvider.js.map +1 -0
- package/dist/json/documentLinks/DocumentLinksProvider.d.ts +6 -0
- package/dist/json/documentLinks/DocumentLinksProvider.js +45 -0
- package/dist/json/documentLinks/DocumentLinksProvider.js.map +1 -0
- package/dist/json/hover/JSONHoverProvider.d.ts +7 -0
- package/dist/json/hover/JSONHoverProvider.js +3 -0
- package/dist/json/hover/JSONHoverProvider.js.map +1 -0
- package/dist/json/hover/providers/BlockSettingsHoverProvider.d.ts +12 -0
- package/dist/json/hover/providers/BlockSettingsHoverProvider.js +75 -0
- package/dist/json/hover/providers/BlockSettingsHoverProvider.js.map +1 -0
- package/dist/json/hover/providers/SchemaTranslationHoverProvider.d.ts +10 -0
- package/dist/json/hover/providers/SchemaTranslationHoverProvider.js +36 -0
- package/dist/json/hover/providers/SchemaTranslationHoverProvider.js.map +1 -0
- package/dist/json/hover/providers/SettingsHoverProvider.d.ts +10 -0
- package/dist/json/hover/providers/SettingsHoverProvider.js +62 -0
- package/dist/json/hover/providers/SettingsHoverProvider.js.map +1 -0
- package/dist/json/hover/providers/TranslationPathHoverProvider.d.ts +9 -0
- package/dist/json/hover/providers/TranslationPathHoverProvider.js +65 -0
- package/dist/json/hover/providers/TranslationPathHoverProvider.js.map +1 -0
- package/dist/json/schemaSettings.d.ts +4 -0
- package/dist/json/schemaSettings.js +45 -0
- package/dist/json/schemaSettings.js.map +1 -0
- package/dist/json/test/test-helpers.d.ts +8 -0
- package/dist/json/test/test-helpers.js +42 -0
- package/dist/json/test/test-helpers.js.map +1 -0
- package/dist/json/utils.d.ts +6 -0
- package/dist/json/utils.js +31 -0
- package/dist/json/utils.js.map +1 -0
- package/dist/linkedEditingRanges/BaseLinkedEditingRangesProvider.d.ts +5 -0
- package/dist/linkedEditingRanges/BaseLinkedEditingRangesProvider.js +3 -0
- package/dist/linkedEditingRanges/BaseLinkedEditingRangesProvider.js.map +1 -0
- package/dist/linkedEditingRanges/LinkedEditingRangesProvider.d.ts +8 -0
- package/dist/linkedEditingRanges/LinkedEditingRangesProvider.js +31 -0
- package/dist/linkedEditingRanges/LinkedEditingRangesProvider.js.map +1 -0
- package/dist/linkedEditingRanges/index.d.ts +1 -0
- package/dist/linkedEditingRanges/index.js +6 -0
- package/dist/linkedEditingRanges/index.js.map +1 -0
- package/dist/linkedEditingRanges/providers/EmptyHtmlTagLinkedRangesProvider.d.ts +9 -0
- package/dist/linkedEditingRanges/providers/EmptyHtmlTagLinkedRangesProvider.js +37 -0
- package/dist/linkedEditingRanges/providers/EmptyHtmlTagLinkedRangesProvider.js.map +1 -0
- package/dist/linkedEditingRanges/providers/HtmlTagNameLinkedRangesProvider.d.ts +12 -0
- package/dist/linkedEditingRanges/providers/HtmlTagNameLinkedRangesProvider.js +26 -0
- package/dist/linkedEditingRanges/providers/HtmlTagNameLinkedRangesProvider.js.map +1 -0
- package/dist/linkedEditingRanges/providers/index.d.ts +2 -0
- package/dist/linkedEditingRanges/providers/index.js +8 -0
- package/dist/linkedEditingRanges/providers/index.js.map +1 -0
- package/dist/linkedEditingRanges/wordPattern.d.ts +1 -0
- package/dist/linkedEditingRanges/wordPattern.js +7 -0
- package/dist/linkedEditingRanges/wordPattern.js.map +1 -0
- package/dist/plugins/css.d.ts +3 -0
- package/dist/plugins/css.js +12 -0
- package/dist/plugins/css.js.map +1 -0
- package/dist/progress.d.ts +42 -0
- package/dist/progress.js +74 -0
- package/dist/progress.js.map +1 -0
- package/dist/rename/BaseRenameProvider.d.ts +6 -0
- package/dist/rename/BaseRenameProvider.js +3 -0
- package/dist/rename/BaseRenameProvider.js.map +1 -0
- package/dist/rename/RenameProvider.d.ts +21 -0
- package/dist/rename/RenameProvider.js +58 -0
- package/dist/rename/RenameProvider.js.map +1 -0
- package/dist/rename/providers/HtmlTagNameRenameProvider.d.ts +10 -0
- package/dist/rename/providers/HtmlTagNameRenameProvider.js +39 -0
- package/dist/rename/providers/HtmlTagNameRenameProvider.js.map +1 -0
- package/dist/rename/providers/LiquidVariableRenameProvider.d.ts +16 -0
- package/dist/rename/providers/LiquidVariableRenameProvider.js +194 -0
- package/dist/rename/providers/LiquidVariableRenameProvider.js.map +1 -0
- package/dist/renamed/BaseRenameHandler.d.ts +4 -0
- package/dist/renamed/BaseRenameHandler.js +3 -0
- package/dist/renamed/BaseRenameHandler.js.map +1 -0
- package/dist/renamed/RenameHandler.d.ts +18 -0
- package/dist/renamed/RenameHandler.js +37 -0
- package/dist/renamed/RenameHandler.js.map +1 -0
- package/dist/renamed/handlers/AssetRenameHandler.d.ts +26 -0
- package/dist/renamed/handlers/AssetRenameHandler.js +99 -0
- package/dist/renamed/handlers/AssetRenameHandler.js.map +1 -0
- package/dist/renamed/handlers/BlockRenameHandler.d.ts +41 -0
- package/dist/renamed/handlers/BlockRenameHandler.js +304 -0
- package/dist/renamed/handlers/BlockRenameHandler.js.map +1 -0
- package/dist/renamed/handlers/PartialRenameHandler.d.ts +26 -0
- package/dist/renamed/handlers/PartialRenameHandler.js +99 -0
- package/dist/renamed/handlers/PartialRenameHandler.js.map +1 -0
- package/dist/renamed/handlers/SectionRenameHandler.d.ts +25 -0
- package/dist/renamed/handlers/SectionRenameHandler.js +176 -0
- package/dist/renamed/handlers/SectionRenameHandler.js.map +1 -0
- package/dist/renamed/handlers/utils.d.ts +3 -0
- package/dist/renamed/handlers/utils.js +20 -0
- package/dist/renamed/handlers/utils.js.map +1 -0
- package/dist/server/CachedFileSystem.d.ts +12 -0
- package/dist/server/CachedFileSystem.js +29 -0
- package/dist/server/CachedFileSystem.js.map +1 -0
- package/dist/server/Configuration.d.ts +25 -0
- package/dist/server/Configuration.js +77 -0
- package/dist/server/Configuration.js.map +1 -0
- package/dist/server/ThemeGraphManager.d.ts +35 -0
- package/dist/server/ThemeGraphManager.js +200 -0
- package/dist/server/ThemeGraphManager.js.map +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +6 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/safe.d.ts +19 -0
- package/dist/server/safe.js +33 -0
- package/dist/server/safe.js.map +1 -0
- package/dist/server/startServer.d.ts +13 -0
- package/dist/server/startServer.js +598 -0
- package/dist/server/startServer.js.map +1 -0
- package/dist/settings/index.d.ts +29 -0
- package/dist/settings/index.js +11 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/test/ApplyEditsAssertion.d.ts +14 -0
- package/dist/test/ApplyEditsAssertion.js +19 -0
- package/dist/test/ApplyEditsAssertion.js.map +1 -0
- package/dist/test/CompletionItemsAssertion.d.ts +25 -0
- package/dist/test/CompletionItemsAssertion.js +60 -0
- package/dist/test/CompletionItemsAssertion.js.map +1 -0
- package/dist/test/HoverAssertion.d.ts +16 -0
- package/dist/test/HoverAssertion.js +54 -0
- package/dist/test/HoverAssertion.js.map +1 -0
- package/dist/test/MockChecks.d.ts +2 -0
- package/dist/test/MockChecks.js +30 -0
- package/dist/test/MockChecks.js.map +1 -0
- package/dist/test/MockConnection.d.ts +44 -0
- package/dist/test/MockConnection.js +106 -0
- package/dist/test/MockConnection.js.map +1 -0
- package/dist/test/test-setup.d.ts +1 -0
- package/dist/test/test-setup.js +8 -0
- package/dist/test/test-setup.js.map +1 -0
- package/dist/translations.d.ts +19 -0
- package/dist/translations.js +73 -0
- package/dist/translations.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +149 -0
- package/dist/types.js +63 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/array.d.ts +1 -0
- package/dist/utils/array.js +11 -0
- package/dist/utils/array.js.map +1 -0
- package/dist/utils/debounce.d.ts +37 -0
- package/dist/utils/debounce.js +44 -0
- package/dist/utils/debounce.js.map +1 -0
- package/dist/utils/htmlTagNames.d.ts +5 -0
- package/dist/utils/htmlTagNames.js +42 -0
- package/dist/utils/htmlTagNames.js.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +26 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/isCovered.d.ts +4 -0
- package/dist/utils/isCovered.js +7 -0
- package/dist/utils/isCovered.js.map +1 -0
- package/dist/utils/liquidDoc.d.ts +22 -0
- package/dist/utils/liquidDoc.js +78 -0
- package/dist/utils/liquidDoc.js.map +1 -0
- package/dist/utils/node.d.ts +24 -0
- package/dist/utils/node.js +52 -0
- package/dist/utils/node.js.map +1 -0
- package/dist/utils/uri.d.ts +12 -0
- package/dist/utils/uri.js +30 -0
- package/dist/utils/uri.js.map +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +9 -0
- package/dist/version.js.map +1 -0
- package/package.json +40 -0
- package/src/ClientCapabilities.ts +63 -0
- package/src/PropertyShapeInference.ts +394 -0
- package/src/TypeSystem.spec.ts +1150 -0
- package/src/TypeSystem.ts +1948 -0
- package/src/VariableShapeExtractor.ts +380 -0
- package/src/codeActions/BaseCodeActionsProvider.ts +18 -0
- package/src/codeActions/CodeActionsProvider.ts +28 -0
- package/src/codeActions/index.ts +1 -0
- package/src/codeActions/providers/FixAllProvider.spec.ts +115 -0
- package/src/codeActions/providers/FixAllProvider.ts +60 -0
- package/src/codeActions/providers/FixProvider.spec.ts +330 -0
- package/src/codeActions/providers/FixProvider.ts +105 -0
- package/src/codeActions/providers/SuggestionProvider.spec.ts +143 -0
- package/src/codeActions/providers/SuggestionProvider.ts +75 -0
- package/src/codeActions/providers/index.ts +3 -0
- package/src/codeActions/providers/utils.ts +47 -0
- package/src/commands/BaseExecuteCommandProvider.ts +15 -0
- package/src/commands/ExecuteCommandProvider.ts +59 -0
- package/src/commands/index.ts +2 -0
- package/src/commands/providers/ApplyFixesProvider.spec.ts +133 -0
- package/src/commands/providers/ApplyFixesProvider.ts +86 -0
- package/src/commands/providers/ApplySuggestionProvider.spec.ts +135 -0
- package/src/commands/providers/ApplySuggestionProvider.ts +105 -0
- package/src/commands/providers/RunChecksProvider.spec.ts +55 -0
- package/src/commands/providers/RunChecksProvider.ts +36 -0
- package/src/commands/providers/index.ts +3 -0
- package/src/completions/CompletionsProvider.ts +128 -0
- package/src/completions/index.ts +1 -0
- package/src/completions/params/LiquidCompletionParams.spec.ts +319 -0
- package/src/completions/params/LiquidCompletionParams.ts +538 -0
- package/src/completions/params/fix.spec.ts +159 -0
- package/src/completions/params/fix.ts +269 -0
- package/src/completions/params/index.ts +2 -0
- package/src/completions/params/testcases.txt +104 -0
- package/src/completions/providers/ContentForBlockTypeCompletionProvider.spec.ts +41 -0
- package/src/completions/providers/ContentForBlockTypeCompletionProvider.ts +42 -0
- package/src/completions/providers/ContentForCompletionProvider.spec.ts +96 -0
- package/src/completions/providers/ContentForCompletionProvider.ts +113 -0
- package/src/completions/providers/ContentForParameterCompletionProvider.spec.ts +362 -0
- package/src/completions/providers/ContentForParameterCompletionProvider.ts +187 -0
- package/src/completions/providers/FilterCompletionProvider.spec.ts +377 -0
- package/src/completions/providers/FilterCompletionProvider.ts +225 -0
- package/src/completions/providers/FilterNamedParameterCompletionProvider.spec.ts +239 -0
- package/src/completions/providers/FilterNamedParameterCompletionProvider.ts +121 -0
- package/src/completions/providers/HtmlAttributeCompletionProvider.spec.ts +150 -0
- package/src/completions/providers/HtmlAttributeCompletionProvider.ts +117 -0
- package/src/completions/providers/HtmlAttributeValueCompletionProvider.spec.ts +38 -0
- package/src/completions/providers/HtmlAttributeValueCompletionProvider.ts +65 -0
- package/src/completions/providers/HtmlTagCompletionProvider.spec.ts +57 -0
- package/src/completions/providers/HtmlTagCompletionProvider.ts +119 -0
- package/src/completions/providers/LiquidDocParamTypeCompletionProvider.spec.ts +79 -0
- package/src/completions/providers/LiquidDocParamTypeCompletionProvider.ts +65 -0
- package/src/completions/providers/LiquidDocTagCompletionProvider.spec.ts +144 -0
- package/src/completions/providers/LiquidDocTagCompletionProvider.ts +74 -0
- package/src/completions/providers/LiquidTagsCompletionProvider.spec.ts +377 -0
- package/src/completions/providers/LiquidTagsCompletionProvider.ts +459 -0
- package/src/completions/providers/ObjectAttributeCompletionProvider.spec.ts +524 -0
- package/src/completions/providers/ObjectAttributeCompletionProvider.ts +95 -0
- package/src/completions/providers/ObjectCompletionProvider.spec.ts +232 -0
- package/src/completions/providers/ObjectCompletionProvider.ts +44 -0
- package/src/completions/providers/PartialCompletionProvider.spec.ts +107 -0
- package/src/completions/providers/PartialCompletionProvider.ts +50 -0
- package/src/completions/providers/RenderPartialParameterCompletionProvider.spec.ts +91 -0
- package/src/completions/providers/RenderPartialParameterCompletionProvider.ts +79 -0
- package/src/completions/providers/TranslationCompletionProvider.spec.ts +65 -0
- package/src/completions/providers/TranslationCompletionProvider.ts +103 -0
- package/src/completions/providers/common/CompletionItemProperties.ts +66 -0
- package/src/completions/providers/common/Provider.ts +6 -0
- package/src/completions/providers/common/index.ts +18 -0
- package/src/completions/providers/data/contentForParameterCompletionOptions.ts +9 -0
- package/src/completions/providers/index.ts +20 -0
- package/src/css/CSSLanguageService.spec.ts +161 -0
- package/src/css/CSSLanguageService.ts +113 -0
- package/src/css/test/test-helpers.ts +30 -0
- package/src/definitions/BaseDefinitionProvider.ts +10 -0
- package/src/definitions/DefinitionProvider.ts +48 -0
- package/src/definitions/providers/SchemaTranslationStringDefinitionProvider.spec.ts +96 -0
- package/src/definitions/providers/SchemaTranslationStringDefinitionProvider.ts +82 -0
- package/src/definitions/providers/TranslationStringDefinitionProvider.spec.ts +77 -0
- package/src/definitions/providers/TranslationStringDefinitionProvider.ts +72 -0
- package/src/diagnostics/DiagnosticsManager.spec.ts +79 -0
- package/src/diagnostics/DiagnosticsManager.ts +58 -0
- package/src/diagnostics/index.ts +2 -0
- package/src/diagnostics/offenseToDiagnostic.ts +80 -0
- package/src/diagnostics/runChecks.spec.ts +285 -0
- package/src/diagnostics/runChecks.ts +147 -0
- package/src/docset/HtmlDocset.ts +43 -0
- package/src/docset/MarkdownRenderer.spec.ts +46 -0
- package/src/docset/MarkdownRenderer.ts +179 -0
- package/src/docset/index.ts +2 -0
- package/src/documentHighlights/BaseDocumentHighlightsProvider.ts +10 -0
- package/src/documentHighlights/DocumentHighlightsProvider.ts +54 -0
- package/src/documentHighlights/index.ts +1 -0
- package/src/documentHighlights/providers/HtmlTagNameDocumentHighlightsProvider.spec.ts +94 -0
- package/src/documentHighlights/providers/HtmlTagNameDocumentHighlightsProvider.ts +22 -0
- package/src/documentHighlights/providers/LiquidBlockTagDocumentHighlightsProvider.spec.ts +188 -0
- package/src/documentHighlights/providers/LiquidBlockTagDocumentHighlightsProvider.ts +73 -0
- package/src/documentHighlights/providers/index.ts +2 -0
- package/src/documentLinks/DocumentLinksProvider.spec.ts +66 -0
- package/src/documentLinks/DocumentLinksProvider.ts +123 -0
- package/src/documentLinks/index.ts +1 -0
- package/src/documents/DocumentManager.spec.ts +276 -0
- package/src/documents/DocumentManager.ts +232 -0
- package/src/documents/index.ts +2 -0
- package/src/documents/types.ts +55 -0
- package/src/formatting/OnTypeFormattingProvider.spec.ts +74 -0
- package/src/formatting/OnTypeFormattingProvider.ts +26 -0
- package/src/formatting/index.ts +1 -0
- package/src/formatting/providers/BracketsAutoclosingOnTypeFormattingProvider.spec.ts +88 -0
- package/src/formatting/providers/BracketsAutoclosingOnTypeFormattingProvider.ts +114 -0
- package/src/formatting/providers/HtmlElementAutoclosingOnTypeFormattingProvider.spec.ts +183 -0
- package/src/formatting/providers/HtmlElementAutoclosingOnTypeFormattingProvider.ts +127 -0
- package/src/formatting/types.ts +12 -0
- package/src/hover/BaseHoverProvider.ts +10 -0
- package/src/hover/HoverProvider.ts +86 -0
- package/src/hover/index.ts +1 -0
- package/src/hover/providers/ContentForArgumentHoverProvider.spec.ts +76 -0
- package/src/hover/providers/ContentForArgumentHoverProvider.ts +56 -0
- package/src/hover/providers/ContentForTypeHoverProvider.spec.ts +91 -0
- package/src/hover/providers/ContentForTypeHoverProvider.ts +42 -0
- package/src/hover/providers/HtmlAttributeHoverProvider.spec.ts +50 -0
- package/src/hover/providers/HtmlAttributeHoverProvider.ts +48 -0
- package/src/hover/providers/HtmlAttributeValueHoverProvider.spec.ts +38 -0
- package/src/hover/providers/HtmlAttributeValueHoverProvider.ts +52 -0
- package/src/hover/providers/HtmlTagHoverProvider.spec.ts +39 -0
- package/src/hover/providers/HtmlTagHoverProvider.ts +42 -0
- package/src/hover/providers/LiquidDocTagHoverProvider.spec.ts +64 -0
- package/src/hover/providers/LiquidDocTagHoverProvider.ts +58 -0
- package/src/hover/providers/LiquidFilterArgumentHoverProvider.spec.ts +57 -0
- package/src/hover/providers/LiquidFilterArgumentHoverProvider.ts +42 -0
- package/src/hover/providers/LiquidFilterHoverProvider.spec.ts +50 -0
- package/src/hover/providers/LiquidFilterHoverProvider.ts +29 -0
- package/src/hover/providers/LiquidObjectAttributeHoverProvider.spec.ts +238 -0
- package/src/hover/providers/LiquidObjectAttributeHoverProvider.ts +156 -0
- package/src/hover/providers/LiquidObjectHoverProvider.spec.ts +278 -0
- package/src/hover/providers/LiquidObjectHoverProvider.ts +95 -0
- package/src/hover/providers/LiquidTagHoverProvider.spec.ts +51 -0
- package/src/hover/providers/LiquidTagHoverProvider.ts +33 -0
- package/src/hover/providers/RenderPartialHoverProvider.spec.ts +85 -0
- package/src/hover/providers/RenderPartialHoverProvider.ts +38 -0
- package/src/hover/providers/RenderPartialParameterHoverProvider.spec.ts +70 -0
- package/src/hover/providers/RenderPartialParameterHoverProvider.ts +47 -0
- package/src/hover/providers/TranslationHoverProvider.spec.ts +59 -0
- package/src/hover/providers/TranslationHoverProvider.ts +61 -0
- package/src/hover/providers/index.ts +11 -0
- package/src/index.spec.ts +8 -0
- package/src/index.ts +34 -0
- package/src/internal-types.ts +1 -0
- package/src/json/JSONContributions.ts +150 -0
- package/src/json/JSONLanguageService.spec.ts +424 -0
- package/src/json/JSONLanguageService.ts +239 -0
- package/src/json/RequestContext.ts +35 -0
- package/src/json/completions/JSONCompletionProvider.ts +33 -0
- package/src/json/completions/providers/BlockSettingsPropertyCompletionProvider.spec.ts +163 -0
- package/src/json/completions/providers/BlockSettingsPropertyCompletionProvider.ts +121 -0
- package/src/json/completions/providers/BlockTypeCompletionProvider.spec.ts +137 -0
- package/src/json/completions/providers/BlockTypeCompletionProvider.ts +108 -0
- package/src/json/completions/providers/ReferencedBlockTypeCompletionProvider.spec.ts +132 -0
- package/src/json/completions/providers/ReferencedBlockTypeCompletionProvider.ts +120 -0
- package/src/json/completions/providers/SchemaTranslationCompletionProvider.ts +51 -0
- package/src/json/completions/providers/SettingsPropertyCompletionProvider.spec.ts +211 -0
- package/src/json/completions/providers/SettingsPropertyCompletionProvider.ts +75 -0
- package/src/json/documentLinks/DocumentLinksProvider.spec.ts +223 -0
- package/src/json/documentLinks/DocumentLinksProvider.ts +61 -0
- package/src/json/hover/JSONHoverProvider.ts +8 -0
- package/src/json/hover/providers/BlockSettingsHoverProvider.spec.ts +292 -0
- package/src/json/hover/providers/BlockSettingsHoverProvider.ts +99 -0
- package/src/json/hover/providers/SchemaTranslationHoverProvider.ts +35 -0
- package/src/json/hover/providers/SettingsHoverProvider.spec.ts +139 -0
- package/src/json/hover/providers/SettingsHoverProvider.ts +79 -0
- package/src/json/hover/providers/TranslationPathHoverProvider.ts +71 -0
- package/src/json/schemaSettings.spec.ts +103 -0
- package/src/json/schemaSettings.ts +53 -0
- package/src/json/test/test-helpers.ts +68 -0
- package/src/json/utils.ts +30 -0
- package/src/linkedEditingRanges/BaseLinkedEditingRangesProvider.ts +10 -0
- package/src/linkedEditingRanges/LinkedEditingRangesProvider.ts +40 -0
- package/src/linkedEditingRanges/index.ts +1 -0
- package/src/linkedEditingRanges/providers/EmptyHtmlTagLinkedRangesProvider.spec.ts +74 -0
- package/src/linkedEditingRanges/providers/EmptyHtmlTagLinkedRangesProvider.ts +47 -0
- package/src/linkedEditingRanges/providers/HtmlTagNameLinkedRangesProvider.spec.ts +102 -0
- package/src/linkedEditingRanges/providers/HtmlTagNameLinkedRangesProvider.ts +28 -0
- package/src/linkedEditingRanges/providers/index.ts +2 -0
- package/src/linkedEditingRanges/wordPattern.ts +3 -0
- package/src/plugins/css.ts +12 -0
- package/src/progress.ts +83 -0
- package/src/rename/BaseRenameProvider.ts +21 -0
- package/src/rename/RenameProvider.ts +91 -0
- package/src/rename/providers/HtmlTagNameRenameProvider.spec.ts +84 -0
- package/src/rename/providers/HtmlTagNameRenameProvider.ts +59 -0
- package/src/rename/providers/LiquidVariableRenameProvider.spec.ts +511 -0
- package/src/rename/providers/LiquidVariableRenameProvider.ts +300 -0
- package/src/renamed/BaseRenameHandler.ts +5 -0
- package/src/renamed/RenameHandler.ts +45 -0
- package/src/renamed/handlers/AssetRenameHandler.spec.ts +217 -0
- package/src/renamed/handlers/AssetRenameHandler.ts +108 -0
- package/src/renamed/handlers/BlockRenameHandler.spec.ts +399 -0
- package/src/renamed/handlers/BlockRenameHandler.ts +402 -0
- package/src/renamed/handlers/PartialRenameHandler.spec.ts +153 -0
- package/src/renamed/handlers/PartialRenameHandler.ts +110 -0
- package/src/renamed/handlers/SectionRenameHandler.spec.ts +321 -0
- package/src/renamed/handlers/SectionRenameHandler.ts +224 -0
- package/src/renamed/handlers/utils.ts +22 -0
- package/src/server/CachedFileSystem.ts +39 -0
- package/src/server/Configuration.ts +89 -0
- package/src/server/ThemeGraphManager.ts +265 -0
- package/src/server/index.ts +1 -0
- package/src/server/safe.ts +30 -0
- package/src/server/startServer.spec.ts +423 -0
- package/src/server/startServer.ts +771 -0
- package/src/settings/index.ts +50 -0
- package/src/test/ApplyEditsAssertion.spec.ts +57 -0
- package/src/test/ApplyEditsAssertion.ts +34 -0
- package/src/test/CompletionItemsAssertion.spec.ts +48 -0
- package/src/test/CompletionItemsAssertion.ts +99 -0
- package/src/test/HoverAssertion.ts +84 -0
- package/src/test/MockChecks.ts +32 -0
- package/src/test/MockConnection.ts +158 -0
- package/src/test/test-setup.ts +6 -0
- package/src/translations.ts +83 -0
- package/src/types.ts +173 -0
- package/src/utils/array.ts +6 -0
- package/src/utils/debounce.ts +60 -0
- package/src/utils/htmlTagNames.ts +61 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/isCovered.ts +3 -0
- package/src/utils/liquidDoc.spec.ts +167 -0
- package/src/utils/liquidDoc.ts +102 -0
- package/src/utils/node.ts +69 -0
- package/src/utils/uri.ts +22 -0
- package/src/version.ts +3 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,1481 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Unknown = exports.Untyped = exports.TypeSystem = void 0;
|
|
4
|
+
exports.docsetEntryReturnType = docsetEntryReturnType;
|
|
5
|
+
exports.isArrayType = isArrayType;
|
|
6
|
+
exports.isShapeType = isShapeType;
|
|
7
|
+
exports.isUnionType = isUnionType;
|
|
8
|
+
exports.typeToDisplayString = typeToDisplayString;
|
|
9
|
+
const liquid_html_parser_1 = require("@platformos/liquid-html-parser");
|
|
10
|
+
const platformos_check_common_1 = require("@platformos/platformos-check-common");
|
|
11
|
+
const settings_1 = require("./settings");
|
|
12
|
+
const utils_1 = require("./utils");
|
|
13
|
+
const platformos_check_common_2 = require("@platformos/platformos-check-common");
|
|
14
|
+
const PropertyShapeInference_1 = require("./PropertyShapeInference");
|
|
15
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
16
|
+
class TypeSystem {
|
|
17
|
+
constructor(themeDocset, getThemeSettingsSchemaForURI, getMetafieldDefinitions, fs, documentsLocator, findThemeRootURI) {
|
|
18
|
+
this.themeDocset = themeDocset;
|
|
19
|
+
this.getThemeSettingsSchemaForURI = getThemeSettingsSchemaForURI;
|
|
20
|
+
this.getMetafieldDefinitions = getMetafieldDefinitions;
|
|
21
|
+
this.fs = fs;
|
|
22
|
+
this.documentsLocator = documentsLocator;
|
|
23
|
+
this.findThemeRootURI = findThemeRootURI;
|
|
24
|
+
this.graphqlSchemaLoaded = false;
|
|
25
|
+
/**
|
|
26
|
+
* An indexed representation of objects.json by name
|
|
27
|
+
*
|
|
28
|
+
* e.g. objectMap['product'] returns the product ObjectEntry.
|
|
29
|
+
*/
|
|
30
|
+
this.objectMap = async (uri, ast) => {
|
|
31
|
+
const [objectMap, themeSettingProperties, metafieldDefinitionsObjectMap] = await Promise.all([
|
|
32
|
+
this._objectMap(),
|
|
33
|
+
this.themeSettingProperties(uri),
|
|
34
|
+
this.metafieldDefinitionsObjectMap(uri),
|
|
35
|
+
]);
|
|
36
|
+
// Here we shallow mutate `settings.properties` to have the properties made
|
|
37
|
+
// available by settings_schema.json
|
|
38
|
+
const result = {
|
|
39
|
+
...objectMap,
|
|
40
|
+
settings: {
|
|
41
|
+
...(objectMap.settings ?? {}),
|
|
42
|
+
properties: themeSettingProperties,
|
|
43
|
+
},
|
|
44
|
+
...customMetafieldTypeEntries(objectMap['metafield']),
|
|
45
|
+
...metafieldDefinitionsObjectMap,
|
|
46
|
+
};
|
|
47
|
+
// For each metafield definition fetched, we need to override existing types with `metafields` property
|
|
48
|
+
// to `${category}_metafield`.
|
|
49
|
+
//
|
|
50
|
+
// WARNING: Since we aren't cloning the object, we are mutating the original type for all themes in
|
|
51
|
+
// the workspace. However, this is fine since these changes are not unique to a theme.
|
|
52
|
+
for (let category of platformos_check_common_1.FETCHED_METAFIELD_CATEGORIES) {
|
|
53
|
+
if (!result[category])
|
|
54
|
+
continue;
|
|
55
|
+
let metafieldsProperty = result[category].properties?.find((prop) => prop.name === 'metafields');
|
|
56
|
+
if (!metafieldsProperty)
|
|
57
|
+
continue;
|
|
58
|
+
metafieldsProperty.return_type = [{ type: `${category}_metafields`, name: '' }];
|
|
59
|
+
}
|
|
60
|
+
// Deal with sections/file.liquid section.settings by infering the type from the {% schema %}
|
|
61
|
+
if (/[\/\\]sections[\/\\]/.test(uri) && result.section) {
|
|
62
|
+
result.section = JSON.parse(JSON.stringify(result.section)); // easy deep clone
|
|
63
|
+
const settings = result.section.properties?.find((x) => x.name === 'settings');
|
|
64
|
+
if (!settings || !settings.return_type)
|
|
65
|
+
return result;
|
|
66
|
+
settings.return_type = [{ type: 'section_settings', name: '' }];
|
|
67
|
+
result.section_settings = {
|
|
68
|
+
name: 'section_settings',
|
|
69
|
+
access: {
|
|
70
|
+
global: false,
|
|
71
|
+
parents: [],
|
|
72
|
+
template: [],
|
|
73
|
+
},
|
|
74
|
+
properties: schemaSettingsAsProperties(ast),
|
|
75
|
+
return_type: [],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// Deal with blocks/files.liquid block.settings in a similar fashion
|
|
79
|
+
if (/[\/\\]blocks[\/\\]/.test(uri) && result.block) {
|
|
80
|
+
result.block = JSON.parse(JSON.stringify(result.block)); // easy deep clone
|
|
81
|
+
const settings = result.block.properties?.find((x) => x.name === 'settings');
|
|
82
|
+
if (!settings || !settings.return_type)
|
|
83
|
+
return result;
|
|
84
|
+
settings.return_type = [{ type: 'block_settings', name: '' }];
|
|
85
|
+
result.block_settings = {
|
|
86
|
+
name: 'block_settings',
|
|
87
|
+
access: {
|
|
88
|
+
global: false,
|
|
89
|
+
parents: [],
|
|
90
|
+
template: [],
|
|
91
|
+
},
|
|
92
|
+
properties: schemaSettingsAsProperties(ast),
|
|
93
|
+
return_type: [],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
// This is the big one we reuse (memoized)
|
|
99
|
+
this._objectMap = (0, utils_1.memo)(async () => {
|
|
100
|
+
const entries = await this.objectEntries();
|
|
101
|
+
return entries.reduce((map, entry) => {
|
|
102
|
+
map[entry.name] = entry;
|
|
103
|
+
return map;
|
|
104
|
+
}, {});
|
|
105
|
+
});
|
|
106
|
+
/** An indexed representation of filters.json by name */
|
|
107
|
+
this.filtersMap = (0, utils_1.memo)(async () => {
|
|
108
|
+
const entries = await this.filterEntries();
|
|
109
|
+
return entries.reduce((map, entry) => {
|
|
110
|
+
map[entry.name] = entry;
|
|
111
|
+
return map;
|
|
112
|
+
}, {});
|
|
113
|
+
});
|
|
114
|
+
this.filterEntries = (0, utils_1.memo)(async () => {
|
|
115
|
+
return this.themeDocset.filters();
|
|
116
|
+
});
|
|
117
|
+
this.objectEntries = (0, utils_1.memo)(async () => {
|
|
118
|
+
return this.themeDocset.objects();
|
|
119
|
+
});
|
|
120
|
+
/**
|
|
121
|
+
* The seedSymbolsTable contains all the global variables.
|
|
122
|
+
*
|
|
123
|
+
* This lets us have the ambient type of things first, but if someone
|
|
124
|
+
* reassigns product, then we'll be able to change the type of product on
|
|
125
|
+
* the appropriate range.
|
|
126
|
+
*
|
|
127
|
+
* This is not memo'ed because we would otherwise need to clone the thing.
|
|
128
|
+
*/
|
|
129
|
+
this.seedSymbolsTable = async (uri) => {
|
|
130
|
+
const [globalVariables, contextualVariables] = await Promise.all([
|
|
131
|
+
this.globalVariables(),
|
|
132
|
+
this.contextualVariables(uri),
|
|
133
|
+
]);
|
|
134
|
+
return globalVariables.concat(contextualVariables).reduce((table, objectEntry) => {
|
|
135
|
+
table[objectEntry.name] ??= [];
|
|
136
|
+
table[objectEntry.name].push({
|
|
137
|
+
identifier: objectEntry.name,
|
|
138
|
+
type: objectEntryType(objectEntry),
|
|
139
|
+
range: [0],
|
|
140
|
+
});
|
|
141
|
+
return table;
|
|
142
|
+
}, {});
|
|
143
|
+
};
|
|
144
|
+
this.globalVariables = (0, utils_1.memo)(async () => {
|
|
145
|
+
const entries = await this.objectEntries();
|
|
146
|
+
return entries.filter((entry) => !entry.access || entry.access.global === true || entry.access.template.length > 0);
|
|
147
|
+
});
|
|
148
|
+
this.contextualVariables = async (uri) => {
|
|
149
|
+
const entries = await this.objectEntries();
|
|
150
|
+
const contextualEntries = getContextualEntries(uri);
|
|
151
|
+
return entries.filter((entry) => contextualEntries.includes(entry.name));
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
async getGraphQLSchema() {
|
|
155
|
+
if (!this.graphqlSchemaLoaded) {
|
|
156
|
+
this.graphqlSchemaCache = (await this.themeDocset.graphQL()) ?? undefined;
|
|
157
|
+
this.graphqlSchemaLoaded = true;
|
|
158
|
+
}
|
|
159
|
+
return this.graphqlSchemaCache;
|
|
160
|
+
}
|
|
161
|
+
async inferType(thing, partialAst, uri) {
|
|
162
|
+
const [objectMap, filtersMap, symbolsTable] = await Promise.all([
|
|
163
|
+
this.objectMap(uri, partialAst),
|
|
164
|
+
this.filtersMap(),
|
|
165
|
+
this.symbolsTable(partialAst, uri),
|
|
166
|
+
]);
|
|
167
|
+
return inferType(thing, symbolsTable, objectMap, filtersMap);
|
|
168
|
+
}
|
|
169
|
+
async availableVariables(partialAst, partial, node, uri) {
|
|
170
|
+
const [objectMap, filtersMap, symbolsTable] = await Promise.all([
|
|
171
|
+
this.objectMap(uri, partialAst),
|
|
172
|
+
this.filtersMap(),
|
|
173
|
+
this.symbolsTable(partialAst, uri),
|
|
174
|
+
]);
|
|
175
|
+
return Object.entries(symbolsTable)
|
|
176
|
+
.filter(([key, typeRanges]) => key.startsWith(partial) &&
|
|
177
|
+
typeRanges.some((typeRange) => isCorrectTypeRange(typeRange, node)))
|
|
178
|
+
.map(([identifier, typeRanges]) => {
|
|
179
|
+
const typeRange = (0, utils_1.findLast)(typeRanges, (typeRange) => isCorrectTypeRange(typeRange, node));
|
|
180
|
+
const type = resolveTypeRangeType(typeRange.type, symbolsTable, objectMap, filtersMap);
|
|
181
|
+
const entryType = isArrayType(type)
|
|
182
|
+
? type.valueType
|
|
183
|
+
: isShapeType(type) || isUnionType(type)
|
|
184
|
+
? exports.Untyped
|
|
185
|
+
: type;
|
|
186
|
+
const entry = objectMap[entryType] ?? {};
|
|
187
|
+
return {
|
|
188
|
+
entry: { ...entry, name: identifier },
|
|
189
|
+
type,
|
|
190
|
+
};
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
async themeSettingProperties(uri) {
|
|
194
|
+
const themeSettingsSchema = await this.getThemeSettingsSchemaForURI(uri);
|
|
195
|
+
const categories = themeSettingsSchema.filter(settings_1.isSettingsCategory);
|
|
196
|
+
const result = [];
|
|
197
|
+
for (const category of categories) {
|
|
198
|
+
const inputSettings = category.settings.filter(settings_1.isInputSetting);
|
|
199
|
+
for (const setting of inputSettings) {
|
|
200
|
+
result.push({
|
|
201
|
+
name: setting.id,
|
|
202
|
+
summary: '', // TODO, this should lookup the locale file for settings... setting.label
|
|
203
|
+
description: '', // TODO , this should lookup the locale file as well... setting.info,
|
|
204
|
+
return_type: settingReturnType(setting),
|
|
205
|
+
access: {
|
|
206
|
+
global: false,
|
|
207
|
+
parents: [],
|
|
208
|
+
template: [],
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
async metafieldDefinitionsObjectMap(uri) {
|
|
216
|
+
let result = {};
|
|
217
|
+
const metafieldDefinitionMap = await this.getMetafieldDefinitions(uri);
|
|
218
|
+
for (let [category, definitions] of Object.entries(metafieldDefinitionMap)) {
|
|
219
|
+
// Metafield definitions need to be grouped by their namespace
|
|
220
|
+
let metafieldNamespaces = new Map();
|
|
221
|
+
for (let definition of definitions) {
|
|
222
|
+
if (!metafieldNamespaces.has(definition.namespace)) {
|
|
223
|
+
metafieldNamespaces.set(definition.namespace, []);
|
|
224
|
+
}
|
|
225
|
+
metafieldNamespaces.get(definition.namespace).push({
|
|
226
|
+
name: definition.key,
|
|
227
|
+
description: definition.description,
|
|
228
|
+
return_type: metafieldReturnType(definition.type.name),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
let metafieldGroupProperties = [];
|
|
232
|
+
for (let [namespace, namespaceProperties] of metafieldNamespaces) {
|
|
233
|
+
const metafieldCategoryNamespaceHandle = `${category}_metafield_${namespace}`;
|
|
234
|
+
// Since the namespace can be shared by multiple categories, we need to make sure the return_type
|
|
235
|
+
// handle is unique across all categories
|
|
236
|
+
metafieldGroupProperties.push({
|
|
237
|
+
name: namespace,
|
|
238
|
+
return_type: [{ type: metafieldCategoryNamespaceHandle, name: '' }],
|
|
239
|
+
access: {
|
|
240
|
+
global: false,
|
|
241
|
+
parents: [],
|
|
242
|
+
template: [],
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
result[metafieldCategoryNamespaceHandle] = {
|
|
246
|
+
name: metafieldCategoryNamespaceHandle,
|
|
247
|
+
properties: namespaceProperties,
|
|
248
|
+
access: {
|
|
249
|
+
global: false,
|
|
250
|
+
parents: [],
|
|
251
|
+
template: [],
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
const metafieldCategoryHandle = `${category}_metafields`;
|
|
256
|
+
result[metafieldCategoryHandle] = {
|
|
257
|
+
name: metafieldCategoryHandle,
|
|
258
|
+
properties: metafieldGroupProperties,
|
|
259
|
+
access: {
|
|
260
|
+
global: false,
|
|
261
|
+
parents: [],
|
|
262
|
+
template: [],
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
async symbolsTable(partialAst, uri) {
|
|
269
|
+
const [seedSymbolsTable, liquidDrops, graphqlSchema, rootUri, objectMap, filtersMap] = await Promise.all([
|
|
270
|
+
this.seedSymbolsTable(uri),
|
|
271
|
+
this.themeDocset.liquidDrops(),
|
|
272
|
+
this.getGraphQLSchema(),
|
|
273
|
+
this.findThemeRootURI?.(uri) ?? null,
|
|
274
|
+
this.objectMap(uri, partialAst),
|
|
275
|
+
this.filtersMap(),
|
|
276
|
+
]);
|
|
277
|
+
return await buildSymbolsTable(partialAst, seedSymbolsTable, liquidDrops, graphqlSchema, this.fs, this.documentsLocator, rootUri ?? undefined, undefined, // processingFiles
|
|
278
|
+
objectMap, filtersMap);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
exports.TypeSystem = TypeSystem;
|
|
282
|
+
const SECTION_FILE_REGEX = /sections[\/\\][^.\\\/]*\.liquid$/;
|
|
283
|
+
const BLOCK_FILE_REGEX = /blocks[\/\\][^.\\\/]*\.liquid$/;
|
|
284
|
+
const PARTIAL_FILE_REGEX = /(views[\/\\]partials[\/\\]|[\/\\]lib[\/\\])[^.]*\.liquid$/;
|
|
285
|
+
const LAYOUT_FILE_REGEX = /layout[\/\\]checkout\.liquid$/;
|
|
286
|
+
function getContextualEntries(uri) {
|
|
287
|
+
const normalizedUri = platformos_check_common_1.path.normalize(uri);
|
|
288
|
+
if (LAYOUT_FILE_REGEX.test(normalizedUri)) {
|
|
289
|
+
return [
|
|
290
|
+
'locale',
|
|
291
|
+
'direction',
|
|
292
|
+
'skip_to_content_link',
|
|
293
|
+
'checkout_html_classes',
|
|
294
|
+
'checkout_stylesheets',
|
|
295
|
+
'checkout_scripts',
|
|
296
|
+
'content_for_logo',
|
|
297
|
+
'breadcrumb',
|
|
298
|
+
'order_summary_toggle',
|
|
299
|
+
'content_for_order_summary',
|
|
300
|
+
'alternative_payment_methods',
|
|
301
|
+
'content_for_footer',
|
|
302
|
+
'tracking_code',
|
|
303
|
+
];
|
|
304
|
+
}
|
|
305
|
+
if (SECTION_FILE_REGEX.test(normalizedUri)) {
|
|
306
|
+
return ['section', 'predictive_search', 'recommendations', 'comment'];
|
|
307
|
+
}
|
|
308
|
+
if (BLOCK_FILE_REGEX.test(normalizedUri)) {
|
|
309
|
+
return ['app', 'section', 'recommendations', 'block'];
|
|
310
|
+
}
|
|
311
|
+
if (PARTIAL_FILE_REGEX.test(normalizedUri)) {
|
|
312
|
+
return ['app'];
|
|
313
|
+
}
|
|
314
|
+
return [];
|
|
315
|
+
}
|
|
316
|
+
/** Untyped is for declared variables without a type (like `any`) */
|
|
317
|
+
exports.Untyped = 'untyped';
|
|
318
|
+
/** Unknown is for variables that don't exist, type would come from context (e.g. snippet var without LiquidDoc) */
|
|
319
|
+
exports.Unknown = 'unknown';
|
|
320
|
+
const String = 'string';
|
|
321
|
+
const arrayType = (valueType) => ({
|
|
322
|
+
kind: 'array',
|
|
323
|
+
valueType,
|
|
324
|
+
});
|
|
325
|
+
const shapeType = (shape) => ({
|
|
326
|
+
kind: 'shape',
|
|
327
|
+
shape,
|
|
328
|
+
});
|
|
329
|
+
const unionType = (types) => ({
|
|
330
|
+
kind: 'union',
|
|
331
|
+
types,
|
|
332
|
+
});
|
|
333
|
+
const lazyVariable = (node, offset) => ({
|
|
334
|
+
kind: liquid_html_parser_1.NodeTypes.LiquidVariable,
|
|
335
|
+
node,
|
|
336
|
+
offset,
|
|
337
|
+
});
|
|
338
|
+
const LazyDeconstructedExpression = (node, offset) => ({
|
|
339
|
+
kind: 'deconstructed',
|
|
340
|
+
node,
|
|
341
|
+
offset,
|
|
342
|
+
});
|
|
343
|
+
async function buildSymbolsTable(partialAst, seedSymbolsTable, liquidDrops, graphqlSchema, fs, documentsLocator, rootUri, processingFiles, objectMap, filtersMap) {
|
|
344
|
+
// Track shapes for hash_assign merging
|
|
345
|
+
const variableShapes = new Map();
|
|
346
|
+
const typeRanges = await (0, platformos_check_common_2.visit)(partialAst, {
|
|
347
|
+
// {% assign x = foo.x | filter %}
|
|
348
|
+
// {% assign x = '{"a": 1}' | parse_json %}
|
|
349
|
+
async AssignMarkup(node) {
|
|
350
|
+
// Check if this has a parse_json or to_hash filter
|
|
351
|
+
const hasParseJsonFilter = node.value.filters?.some((f) => f.name === 'parse_json' || f.name === 'to_hash');
|
|
352
|
+
if (hasParseJsonFilter) {
|
|
353
|
+
let jsonString;
|
|
354
|
+
// Check if expression is a direct JSON string
|
|
355
|
+
if (node.value.expression.type === liquid_html_parser_1.NodeTypes.String) {
|
|
356
|
+
jsonString = node.value.expression.value;
|
|
357
|
+
}
|
|
358
|
+
// Check if there's a default filter with a JSON string argument
|
|
359
|
+
if (!jsonString && node.value.filters) {
|
|
360
|
+
const defaultFilter = node.value.filters.find((f) => f.name === 'default');
|
|
361
|
+
if (defaultFilter && defaultFilter.args && defaultFilter.args.length > 0) {
|
|
362
|
+
const firstArg = defaultFilter.args[0];
|
|
363
|
+
if (firstArg.type === liquid_html_parser_1.NodeTypes.String) {
|
|
364
|
+
jsonString = firstArg.value;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (jsonString) {
|
|
369
|
+
const shape = (0, PropertyShapeInference_1.inferShapeFromJSONString)(jsonString);
|
|
370
|
+
if (shape) {
|
|
371
|
+
// Track shape for potential hash_assign merging
|
|
372
|
+
if (!variableShapes.has(node.name)) {
|
|
373
|
+
variableShapes.set(node.name, []);
|
|
374
|
+
}
|
|
375
|
+
variableShapes.get(node.name).push({ shape, rangeEnd: node.position.end });
|
|
376
|
+
return {
|
|
377
|
+
identifier: node.name,
|
|
378
|
+
type: shapeType(shape),
|
|
379
|
+
range: [node.position.end],
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
identifier: node.name,
|
|
386
|
+
type: lazyVariable(node.value, node.position.start),
|
|
387
|
+
range: [node.position.end],
|
|
388
|
+
};
|
|
389
|
+
},
|
|
390
|
+
// {% doc %}
|
|
391
|
+
// @param {string} name - your name
|
|
392
|
+
// {% enddoc %}
|
|
393
|
+
async LiquidDocParamNode(node) {
|
|
394
|
+
return {
|
|
395
|
+
identifier: node.paramName.value,
|
|
396
|
+
type: inferLiquidDocParamType(node, liquidDrops),
|
|
397
|
+
range: [node.position.end],
|
|
398
|
+
};
|
|
399
|
+
},
|
|
400
|
+
// This also covers tablerow
|
|
401
|
+
async ForMarkup(node, ancestors) {
|
|
402
|
+
const parentNode = ancestors.at(-1);
|
|
403
|
+
return {
|
|
404
|
+
identifier: node.variableName,
|
|
405
|
+
type: LazyDeconstructedExpression(node.collection, node.position.start),
|
|
406
|
+
range: [parentNode.blockStartPosition.end, end(parentNode.blockEndPosition?.end)],
|
|
407
|
+
};
|
|
408
|
+
},
|
|
409
|
+
// {% capture foo %}
|
|
410
|
+
// ...
|
|
411
|
+
// {% endcapture}
|
|
412
|
+
async LiquidTag(node) {
|
|
413
|
+
if (node.name === 'capture' && typeof node.markup !== 'string') {
|
|
414
|
+
return {
|
|
415
|
+
identifier: node.markup.name,
|
|
416
|
+
type: String,
|
|
417
|
+
range: [node.position.end],
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
else if (['form', 'paginate'].includes(node.name)) {
|
|
421
|
+
return {
|
|
422
|
+
identifier: node.name,
|
|
423
|
+
type: node.name,
|
|
424
|
+
range: [node.blockStartPosition.end, end(node.blockEndPosition?.end)],
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
else if (['for', 'tablerow'].includes(node.name)) {
|
|
428
|
+
return {
|
|
429
|
+
identifier: node.name + 'loop',
|
|
430
|
+
type: node.name + 'loop',
|
|
431
|
+
range: [node.blockStartPosition.end, end(node.blockEndPosition?.end)],
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
else if (isLiquidTagIncrement(node) || isLiquidTagDecrement(node)) {
|
|
435
|
+
if (node.markup.name === null)
|
|
436
|
+
return;
|
|
437
|
+
return {
|
|
438
|
+
identifier: node.markup.name,
|
|
439
|
+
type: 'number',
|
|
440
|
+
range: [node.position.start],
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
else if (node.name === 'layout') {
|
|
444
|
+
return {
|
|
445
|
+
identifier: 'none',
|
|
446
|
+
type: 'keyword',
|
|
447
|
+
range: [node.position.start, node.position.end],
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
// {% parse_json x %}{"a": 1}{% endparse_json %}
|
|
451
|
+
else if (isLiquidTagParseJson(node)) {
|
|
452
|
+
const variableName = node.markup.name;
|
|
453
|
+
if (variableName && node.children) {
|
|
454
|
+
const textContent = node.children
|
|
455
|
+
.filter((c) => c.type === liquid_html_parser_1.NodeTypes.TextNode)
|
|
456
|
+
.map((c) => c.value)
|
|
457
|
+
.join('');
|
|
458
|
+
const shape = (0, PropertyShapeInference_1.inferShapeFromJSONString)(textContent);
|
|
459
|
+
if (shape) {
|
|
460
|
+
// Track shape for potential hash_assign merging
|
|
461
|
+
if (!variableShapes.has(variableName)) {
|
|
462
|
+
variableShapes.set(variableName, []);
|
|
463
|
+
}
|
|
464
|
+
variableShapes.get(variableName).push({
|
|
465
|
+
shape,
|
|
466
|
+
rangeEnd: node.blockEndPosition?.end ?? node.position.end,
|
|
467
|
+
});
|
|
468
|
+
return {
|
|
469
|
+
identifier: variableName,
|
|
470
|
+
type: shapeType(shape),
|
|
471
|
+
range: [node.blockEndPosition?.end ?? node.position.end],
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// {% graphql result %}...{% endgraphql %} (inline)
|
|
477
|
+
else if (isLiquidTagGraphQL(node) && isGraphQLInlineMarkup(node.markup)) {
|
|
478
|
+
const markup = node.markup;
|
|
479
|
+
if (node.children) {
|
|
480
|
+
const textContent = node.children
|
|
481
|
+
.filter((c) => c.type === liquid_html_parser_1.NodeTypes.TextNode)
|
|
482
|
+
.map((c) => c.value)
|
|
483
|
+
.join('');
|
|
484
|
+
const shape = (0, PropertyShapeInference_1.inferShapeFromGraphQL)(textContent, graphqlSchema);
|
|
485
|
+
if (shape) {
|
|
486
|
+
// Track shape for potential hash_assign merging
|
|
487
|
+
if (!variableShapes.has(markup.name)) {
|
|
488
|
+
variableShapes.set(markup.name, []);
|
|
489
|
+
}
|
|
490
|
+
variableShapes.get(markup.name).push({
|
|
491
|
+
shape,
|
|
492
|
+
rangeEnd: node.blockEndPosition?.end ?? node.position.end,
|
|
493
|
+
});
|
|
494
|
+
return {
|
|
495
|
+
identifier: markup.name,
|
|
496
|
+
type: shapeType(shape),
|
|
497
|
+
range: [node.blockEndPosition?.end ?? node.position.end],
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
// {% graphql result = 'file' %} (file-based)
|
|
503
|
+
else if (isLiquidTagGraphQL(node) && isGraphQLFileMarkup(node.markup)) {
|
|
504
|
+
const markup = node.markup;
|
|
505
|
+
if (fs && documentsLocator && rootUri && isLiquidString(markup.graphql)) {
|
|
506
|
+
const graphqlFile = markup.graphql.value;
|
|
507
|
+
try {
|
|
508
|
+
const located = await documentsLocator.locate(vscode_uri_1.URI.parse(rootUri), 'graphql', graphqlFile);
|
|
509
|
+
if (located) {
|
|
510
|
+
const content = await fs.readFile(located);
|
|
511
|
+
const shape = (0, PropertyShapeInference_1.inferShapeFromGraphQL)(content, graphqlSchema);
|
|
512
|
+
if (shape) {
|
|
513
|
+
// Track shape for potential hash_assign merging
|
|
514
|
+
if (!variableShapes.has(markup.name)) {
|
|
515
|
+
variableShapes.set(markup.name, []);
|
|
516
|
+
}
|
|
517
|
+
variableShapes.get(markup.name).push({
|
|
518
|
+
shape,
|
|
519
|
+
rangeEnd: node.position.end,
|
|
520
|
+
});
|
|
521
|
+
return {
|
|
522
|
+
identifier: markup.name,
|
|
523
|
+
type: shapeType(shape),
|
|
524
|
+
range: [node.position.end],
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
// File read error - skip
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
// {% hash_assign x['key'] = value %}
|
|
535
|
+
else if (isLiquidTagHashAssign(node)) {
|
|
536
|
+
const markup = node.markup;
|
|
537
|
+
const variableName = markup.target.name;
|
|
538
|
+
if (!variableName)
|
|
539
|
+
return;
|
|
540
|
+
const lookupPath = getHashAssignLookupPath(markup);
|
|
541
|
+
// Determine value shape - check if value is a JSON string with parse_json filter
|
|
542
|
+
let valueShape;
|
|
543
|
+
if (markup.value.expression.type === liquid_html_parser_1.NodeTypes.String) {
|
|
544
|
+
const hasParseJsonFilter = markup.value.filters.some((f) => f.name === 'parse_json' || f.name === 'to_hash');
|
|
545
|
+
if (hasParseJsonFilter) {
|
|
546
|
+
valueShape = (0, PropertyShapeInference_1.inferShapeFromJSONString)(markup.value.expression.value) ?? undefined;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
// Check for existing type - first in variableShapes, then in seedSymbolsTable
|
|
550
|
+
const existingShapes = variableShapes.get(variableName) || [];
|
|
551
|
+
const existingShapeEntry = findLastApplicableShape(existingShapes, node.position.start);
|
|
552
|
+
// Check seedSymbolsTable for existing type if not in variableShapes
|
|
553
|
+
let existingType;
|
|
554
|
+
if (!existingShapeEntry && seedSymbolsTable[variableName]) {
|
|
555
|
+
const typeRanges = seedSymbolsTable[variableName];
|
|
556
|
+
// Find the most recent type before this position
|
|
557
|
+
for (const tr of typeRanges) {
|
|
558
|
+
if (tr.range[0] < node.position.start) {
|
|
559
|
+
// Resolve lazy types
|
|
560
|
+
if (typeof tr.type === 'string') {
|
|
561
|
+
existingType = tr.type;
|
|
562
|
+
}
|
|
563
|
+
else if (tr.type.kind === 'shape' ||
|
|
564
|
+
tr.type.kind === 'array' ||
|
|
565
|
+
tr.type.kind === 'union') {
|
|
566
|
+
existingType = tr.type;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
// Check if hash_assign is being applied to a non-object type (error case)
|
|
572
|
+
const nonObjectTypes = ['number', 'string', 'boolean'];
|
|
573
|
+
if (!existingShapeEntry && existingType) {
|
|
574
|
+
if (typeof existingType === 'string' && nonObjectTypes.includes(existingType)) {
|
|
575
|
+
// Can't hash_assign to a primitive - this is an error
|
|
576
|
+
// Return undefined to not change the type (let a check rule report the error)
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (isArrayType(existingType)) {
|
|
580
|
+
// Can't hash_assign to an array - this is an error
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
if (lookupPath && lookupPath.length > 0) {
|
|
585
|
+
// Nested property assignment: {% hash_assign a['key'] = value %}
|
|
586
|
+
let baseShape;
|
|
587
|
+
if (existingShapeEntry) {
|
|
588
|
+
baseShape = existingShapeEntry.shape;
|
|
589
|
+
}
|
|
590
|
+
else if (existingType && isShapeType(existingType)) {
|
|
591
|
+
baseShape = existingType.shape;
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
baseShape = { kind: 'object', properties: new Map() };
|
|
595
|
+
}
|
|
596
|
+
const newShape = mergeNestedPropertyIntoShape(baseShape, lookupPath, valueShape ?? { kind: 'primitive' });
|
|
597
|
+
// Track the new shape
|
|
598
|
+
if (!variableShapes.has(variableName)) {
|
|
599
|
+
variableShapes.set(variableName, []);
|
|
600
|
+
}
|
|
601
|
+
variableShapes.get(variableName).push({ shape: newShape, rangeEnd: node.position.end });
|
|
602
|
+
return {
|
|
603
|
+
identifier: variableName,
|
|
604
|
+
type: shapeType(newShape),
|
|
605
|
+
range: [node.position.end],
|
|
606
|
+
};
|
|
607
|
+
}
|
|
608
|
+
else if (valueShape) {
|
|
609
|
+
// Direct assignment: {% hash_assign a = value %} (works like assign)
|
|
610
|
+
if (!variableShapes.has(variableName)) {
|
|
611
|
+
variableShapes.set(variableName, []);
|
|
612
|
+
}
|
|
613
|
+
variableShapes
|
|
614
|
+
.get(variableName)
|
|
615
|
+
.push({ shape: valueShape, rangeEnd: node.position.end });
|
|
616
|
+
return {
|
|
617
|
+
identifier: variableName,
|
|
618
|
+
type: shapeType(valueShape),
|
|
619
|
+
range: [node.position.end],
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
// {% function result = 'partial/path', args... %}
|
|
624
|
+
else if (isLiquidTagFunction(node)) {
|
|
625
|
+
const markup = node.markup;
|
|
626
|
+
let returnType;
|
|
627
|
+
if (fs &&
|
|
628
|
+
documentsLocator &&
|
|
629
|
+
rootUri &&
|
|
630
|
+
objectMap &&
|
|
631
|
+
filtersMap &&
|
|
632
|
+
isLiquidString(markup.partial)) {
|
|
633
|
+
const partialPath = markup.partial.value;
|
|
634
|
+
try {
|
|
635
|
+
returnType = await inferFunctionReturnType(partialPath, fs, documentsLocator, rootUri, seedSymbolsTable, liquidDrops, graphqlSchema, processingFiles, objectMap, filtersMap);
|
|
636
|
+
}
|
|
637
|
+
catch {
|
|
638
|
+
// File read/parse error - returnType stays undefined
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
// Track shape for potential hash_assign merging
|
|
642
|
+
if (returnType && isShapeType(returnType)) {
|
|
643
|
+
if (!variableShapes.has(markup.name)) {
|
|
644
|
+
variableShapes.set(markup.name, []);
|
|
645
|
+
}
|
|
646
|
+
variableShapes.get(markup.name).push({
|
|
647
|
+
shape: returnType.shape,
|
|
648
|
+
rangeEnd: node.position.end,
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
// Always add function variable to symbolsTable, using Untyped as fallback
|
|
652
|
+
return {
|
|
653
|
+
identifier: markup.name,
|
|
654
|
+
type: returnType ?? exports.Untyped,
|
|
655
|
+
range: [node.position.end],
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
});
|
|
660
|
+
// Flatten array results (some visitors return TypeRange[])
|
|
661
|
+
const flattenedRanges = typeRanges.flat();
|
|
662
|
+
return flattenedRanges
|
|
663
|
+
.sort(({ range: [startA] }, { range: [startB] }) => startA - startB)
|
|
664
|
+
.reduce((table, typeRange) => {
|
|
665
|
+
table[typeRange.identifier] ??= [];
|
|
666
|
+
table[typeRange.identifier].push(typeRange);
|
|
667
|
+
return table;
|
|
668
|
+
}, seedSymbolsTable);
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Given a TypeRange['type'] (which may be lazy), resolve its type recursively.
|
|
672
|
+
*
|
|
673
|
+
* The output is a fully resolved PseudoType | ArrayType | ShapeType. Which means we
|
|
674
|
+
* could use it to power completions.
|
|
675
|
+
*/
|
|
676
|
+
function resolveTypeRangeType(typeRangeType, symbolsTable, objectMap, filtersMap) {
|
|
677
|
+
if (typeof typeRangeType === 'string') {
|
|
678
|
+
return typeRangeType;
|
|
679
|
+
}
|
|
680
|
+
switch (typeRangeType.kind) {
|
|
681
|
+
case 'array': {
|
|
682
|
+
return typeRangeType;
|
|
683
|
+
}
|
|
684
|
+
case 'shape': {
|
|
685
|
+
return typeRangeType;
|
|
686
|
+
}
|
|
687
|
+
case 'union': {
|
|
688
|
+
return typeRangeType;
|
|
689
|
+
}
|
|
690
|
+
case 'deconstructed': {
|
|
691
|
+
const deconstructedType = inferType(typeRangeType.node, symbolsTable, objectMap, filtersMap);
|
|
692
|
+
if (typeof deconstructedType === 'string') {
|
|
693
|
+
return exports.Untyped;
|
|
694
|
+
}
|
|
695
|
+
else if (isShapeType(deconstructedType)) {
|
|
696
|
+
// Deconstruct shape array
|
|
697
|
+
if (deconstructedType.shape.kind === 'array' && deconstructedType.shape.itemShape) {
|
|
698
|
+
return shapeType(deconstructedType.shape.itemShape);
|
|
699
|
+
}
|
|
700
|
+
return exports.Untyped;
|
|
701
|
+
}
|
|
702
|
+
else if (isUnionType(deconstructedType)) {
|
|
703
|
+
return exports.Untyped;
|
|
704
|
+
}
|
|
705
|
+
else {
|
|
706
|
+
return deconstructedType.valueType;
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
default: {
|
|
710
|
+
return inferType(typeRangeType.node, symbolsTable, objectMap, filtersMap);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function inferType(thing, symbolsTable, objectMap, filtersMap) {
|
|
715
|
+
if (typeof thing === 'string') {
|
|
716
|
+
return objectMap[thing]?.name ?? exports.Untyped;
|
|
717
|
+
}
|
|
718
|
+
switch (thing.type) {
|
|
719
|
+
case liquid_html_parser_1.NodeTypes.Number: {
|
|
720
|
+
return 'number';
|
|
721
|
+
}
|
|
722
|
+
case liquid_html_parser_1.NodeTypes.String: {
|
|
723
|
+
return 'string';
|
|
724
|
+
}
|
|
725
|
+
case liquid_html_parser_1.NodeTypes.LiquidLiteral: {
|
|
726
|
+
return 'boolean';
|
|
727
|
+
}
|
|
728
|
+
case liquid_html_parser_1.NodeTypes.BooleanExpression: {
|
|
729
|
+
return 'boolean';
|
|
730
|
+
}
|
|
731
|
+
case liquid_html_parser_1.NodeTypes.Range: {
|
|
732
|
+
return arrayType('number');
|
|
733
|
+
}
|
|
734
|
+
// The type of the assign markup is the type of the right hand side.
|
|
735
|
+
// {% assign x = y.property | filter1 | filter2 %}
|
|
736
|
+
case liquid_html_parser_1.NodeTypes.AssignMarkup: {
|
|
737
|
+
return inferType(thing.value, symbolsTable, objectMap, filtersMap);
|
|
738
|
+
}
|
|
739
|
+
// A variable lookup is expression[.lookup]*
|
|
740
|
+
// {{ y.property }}
|
|
741
|
+
case liquid_html_parser_1.NodeTypes.VariableLookup: {
|
|
742
|
+
return inferLookupType(thing, symbolsTable, objectMap, filtersMap);
|
|
743
|
+
}
|
|
744
|
+
// A variable is the VariableLookup + Filters
|
|
745
|
+
// The type is the return value of the last filter
|
|
746
|
+
// {{ y.property | filter1 | filter2 }}
|
|
747
|
+
case liquid_html_parser_1.NodeTypes.LiquidVariable: {
|
|
748
|
+
if (thing.filters.length > 0) {
|
|
749
|
+
const lastFilter = thing.filters.at(-1);
|
|
750
|
+
if (lastFilter.name === 'default') {
|
|
751
|
+
// default filter is a special case, we need to return the type of the expression
|
|
752
|
+
// instead of the filter.
|
|
753
|
+
if (lastFilter.args.length > 0 && lastFilter.args[0].type !== liquid_html_parser_1.NodeTypes.NamedArgument) {
|
|
754
|
+
return inferType(lastFilter.args[0], symbolsTable, objectMap, filtersMap);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const filterEntry = filtersMap[lastFilter.name];
|
|
758
|
+
return filterEntry ? filterEntryReturnType(filterEntry) : exports.Untyped;
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
return inferType(thing.expression, symbolsTable, objectMap, filtersMap);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
default: {
|
|
765
|
+
return exports.Untyped;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
function inferLiquidDocParamType(node, liquidDrops) {
|
|
770
|
+
const paramTypeValue = node.paramType?.value;
|
|
771
|
+
if (!paramTypeValue)
|
|
772
|
+
return exports.Untyped;
|
|
773
|
+
const validParamTypes = (0, platformos_check_common_1.getValidParamTypes)(liquidDrops);
|
|
774
|
+
const parsedParamType = (0, platformos_check_common_1.parseParamType)(new Set(validParamTypes.keys()), paramTypeValue);
|
|
775
|
+
if (!parsedParamType)
|
|
776
|
+
return exports.Untyped;
|
|
777
|
+
const [type, isArray] = parsedParamType;
|
|
778
|
+
let transformedParamType;
|
|
779
|
+
// BasicParamTypes.Object does not map to any specific type in the type system.
|
|
780
|
+
if (type === platformos_check_common_1.BasicParamTypes.Object) {
|
|
781
|
+
transformedParamType = exports.Untyped;
|
|
782
|
+
}
|
|
783
|
+
else {
|
|
784
|
+
transformedParamType = type;
|
|
785
|
+
}
|
|
786
|
+
if (isArray) {
|
|
787
|
+
return arrayType(transformedParamType);
|
|
788
|
+
}
|
|
789
|
+
return transformedParamType;
|
|
790
|
+
}
|
|
791
|
+
function inferLookupType(thing, symbolsTable, objectMap, filtersMap) {
|
|
792
|
+
// we return the type of the drop, so a.b.c
|
|
793
|
+
const node = thing;
|
|
794
|
+
// We don't complete global lookups. It's too much of an edge case.
|
|
795
|
+
if (node.name === null)
|
|
796
|
+
return exports.Untyped;
|
|
797
|
+
/**
|
|
798
|
+
* curr stores the type of the variable lookup starting at the beginning.
|
|
799
|
+
*
|
|
800
|
+
* It starts as the type of the top-level identifier, and the we
|
|
801
|
+
* recursively change it to the return type of the lookups.
|
|
802
|
+
*
|
|
803
|
+
* So, for x.images.first.src we do:
|
|
804
|
+
* - curr = infer type of x | x
|
|
805
|
+
* - curr = x.images -> ArrayType<image> | x.images
|
|
806
|
+
* - curr = images.first -> image | x.images.first
|
|
807
|
+
* - curr = first.src -> string | x.images.first.src
|
|
808
|
+
*
|
|
809
|
+
* Once were done iterating, the type of the lookup is curr.
|
|
810
|
+
*/
|
|
811
|
+
let curr = inferIdentifierType(node, symbolsTable, objectMap, filtersMap);
|
|
812
|
+
for (let lookup of node.lookups) {
|
|
813
|
+
// Here we redefine curr to be the returnType of the lookup.
|
|
814
|
+
// e.g. images[0] -> image
|
|
815
|
+
// e.g. images.first -> image
|
|
816
|
+
// e.g. images.size -> number
|
|
817
|
+
if (isArrayType(curr)) {
|
|
818
|
+
curr = inferArrayTypeLookupType(curr, lookup);
|
|
819
|
+
}
|
|
820
|
+
// Handle ShapeType from parse_json, graphql, hash_assign
|
|
821
|
+
else if (isShapeType(curr)) {
|
|
822
|
+
curr = inferShapeTypeLookupType(curr, lookup);
|
|
823
|
+
}
|
|
824
|
+
// Handle UnionType - for now, treat as Untyped for lookups
|
|
825
|
+
else if (isUnionType(curr)) {
|
|
826
|
+
return exports.Untyped;
|
|
827
|
+
}
|
|
828
|
+
// e.g. product.featured_image -> image
|
|
829
|
+
// e.g. product.images -> ArrayType<images>
|
|
830
|
+
// e.g. product.name -> string
|
|
831
|
+
else {
|
|
832
|
+
curr = inferPseudoTypePropertyType(curr, lookup, objectMap);
|
|
833
|
+
}
|
|
834
|
+
// Early return
|
|
835
|
+
if (curr === exports.Untyped) {
|
|
836
|
+
return exports.Untyped;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
return curr;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Given a VariableLookup node, infer the type of its root (position-relative).
|
|
843
|
+
*
|
|
844
|
+
* e.g. for the following
|
|
845
|
+
* {% assign x = product %}
|
|
846
|
+
* {{ x.images.first }}
|
|
847
|
+
*
|
|
848
|
+
* This function infers the type of `x`.
|
|
849
|
+
*/
|
|
850
|
+
function inferIdentifierType(node, symbolsTable, objectMap, filtersMap) {
|
|
851
|
+
// The name of a variable
|
|
852
|
+
const identifier = node.name;
|
|
853
|
+
// We don't complete the global access edge case
|
|
854
|
+
// e.g. {{ ['all_products'] }}
|
|
855
|
+
if (!identifier) {
|
|
856
|
+
return exports.Untyped;
|
|
857
|
+
}
|
|
858
|
+
const typeRanges = symbolsTable[identifier];
|
|
859
|
+
if (!typeRanges) {
|
|
860
|
+
return exports.Unknown;
|
|
861
|
+
}
|
|
862
|
+
const typeRange = (0, utils_1.findLast)(typeRanges, (tr) => isCorrectTypeRange(tr, node));
|
|
863
|
+
return typeRange
|
|
864
|
+
? resolveTypeRangeType(typeRange.type, symbolsTable, objectMap, filtersMap)
|
|
865
|
+
: exports.Unknown;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* infers the type of a lookup on an ArrayType
|
|
869
|
+
* - images[0] becomes 'image'
|
|
870
|
+
* - images[index] becomes 'image'
|
|
871
|
+
* - images.first becomes 'image'
|
|
872
|
+
* - images.last becomes 'image'
|
|
873
|
+
* - images.size becomes 'number'
|
|
874
|
+
* - anything else becomes 'untyped'
|
|
875
|
+
*/
|
|
876
|
+
function inferArrayTypeLookupType(curr, lookup) {
|
|
877
|
+
// images[0]
|
|
878
|
+
// images[index]
|
|
879
|
+
if (lookup.type === liquid_html_parser_1.NodeTypes.Number || lookup.type === liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
880
|
+
return curr.valueType;
|
|
881
|
+
}
|
|
882
|
+
// images.first
|
|
883
|
+
// images.last
|
|
884
|
+
// images.size
|
|
885
|
+
// anything else is undef
|
|
886
|
+
else if (lookup.type === liquid_html_parser_1.NodeTypes.String) {
|
|
887
|
+
switch (lookup.value) {
|
|
888
|
+
case 'first':
|
|
889
|
+
case 'last': {
|
|
890
|
+
return curr.valueType;
|
|
891
|
+
}
|
|
892
|
+
case 'size': {
|
|
893
|
+
return 'number';
|
|
894
|
+
}
|
|
895
|
+
default: {
|
|
896
|
+
return exports.Unknown;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
// images[true]
|
|
901
|
+
// images[(0..2)]
|
|
902
|
+
else {
|
|
903
|
+
return exports.Untyped;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Infers the type of a lookup on a ShapeType (from parse_json, graphql, hash_assign)
|
|
908
|
+
*/
|
|
909
|
+
function inferShapeTypeLookupType(curr, lookup) {
|
|
910
|
+
const shape = curr.shape;
|
|
911
|
+
// Handle array shape lookups
|
|
912
|
+
if (shape.kind === 'array') {
|
|
913
|
+
// array[0] or array[variable] -> item type
|
|
914
|
+
if (lookup.type === liquid_html_parser_1.NodeTypes.Number || lookup.type === liquid_html_parser_1.NodeTypes.VariableLookup) {
|
|
915
|
+
if (shape.itemShape) {
|
|
916
|
+
return shapeToType(shape.itemShape);
|
|
917
|
+
}
|
|
918
|
+
return exports.Untyped;
|
|
919
|
+
}
|
|
920
|
+
// array.first, array.last, array.size
|
|
921
|
+
if (lookup.type === liquid_html_parser_1.NodeTypes.String) {
|
|
922
|
+
switch (lookup.value) {
|
|
923
|
+
case 'first':
|
|
924
|
+
case 'last':
|
|
925
|
+
if (shape.itemShape) {
|
|
926
|
+
return shapeToType(shape.itemShape);
|
|
927
|
+
}
|
|
928
|
+
return exports.Untyped;
|
|
929
|
+
case 'size':
|
|
930
|
+
return 'number';
|
|
931
|
+
default:
|
|
932
|
+
return exports.Unknown;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return exports.Untyped;
|
|
936
|
+
}
|
|
937
|
+
// Handle object shape lookups
|
|
938
|
+
if (shape.kind === 'object') {
|
|
939
|
+
// Object lookups must be strings
|
|
940
|
+
if (lookup.type !== liquid_html_parser_1.NodeTypes.String) {
|
|
941
|
+
return exports.Untyped;
|
|
942
|
+
}
|
|
943
|
+
const propertyName = lookup.value;
|
|
944
|
+
const propertyShape = shape.properties?.get(propertyName);
|
|
945
|
+
if (propertyShape) {
|
|
946
|
+
return shapeToType(propertyShape);
|
|
947
|
+
}
|
|
948
|
+
return exports.Unknown;
|
|
949
|
+
}
|
|
950
|
+
// Primitive shapes don't support lookups (except string.size, string.first, string.last)
|
|
951
|
+
if (shape.kind === 'primitive') {
|
|
952
|
+
if (shape.primitiveType === 'string' && lookup.type === liquid_html_parser_1.NodeTypes.String) {
|
|
953
|
+
switch (lookup.value) {
|
|
954
|
+
case 'first':
|
|
955
|
+
case 'last':
|
|
956
|
+
return 'string';
|
|
957
|
+
case 'size':
|
|
958
|
+
return 'number';
|
|
959
|
+
default:
|
|
960
|
+
return exports.Unknown;
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
return exports.Unknown;
|
|
964
|
+
}
|
|
965
|
+
return exports.Untyped;
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Convert a PropertyShape to a PseudoType, ArrayType, or ShapeType
|
|
969
|
+
*/
|
|
970
|
+
function shapeToType(shape) {
|
|
971
|
+
if (shape.kind === 'primitive') {
|
|
972
|
+
switch (shape.primitiveType) {
|
|
973
|
+
case 'string':
|
|
974
|
+
return 'string';
|
|
975
|
+
case 'number':
|
|
976
|
+
return 'number';
|
|
977
|
+
case 'boolean':
|
|
978
|
+
return 'boolean';
|
|
979
|
+
default:
|
|
980
|
+
return exports.Untyped;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (shape.kind === 'array') {
|
|
984
|
+
// If array items are primitives, return ArrayType
|
|
985
|
+
if (shape.itemShape?.kind === 'primitive') {
|
|
986
|
+
const primitiveType = shape.itemShape.primitiveType;
|
|
987
|
+
if (primitiveType === 'string' || primitiveType === 'number' || primitiveType === 'boolean') {
|
|
988
|
+
return arrayType(primitiveType);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
// Otherwise return ShapeType to preserve nested structure
|
|
992
|
+
return shapeType(shape);
|
|
993
|
+
}
|
|
994
|
+
if (shape.kind === 'object') {
|
|
995
|
+
return shapeType(shape);
|
|
996
|
+
}
|
|
997
|
+
return exports.Untyped;
|
|
998
|
+
}
|
|
999
|
+
function inferPseudoTypePropertyType(curr, // settings
|
|
1000
|
+
lookup, objectMap) {
|
|
1001
|
+
const parentEntry = objectMap[curr];
|
|
1002
|
+
// When doing a non string lookup, we don't really know the type. e.g.
|
|
1003
|
+
// products[0]
|
|
1004
|
+
// products[true]
|
|
1005
|
+
// products[(0..10)]
|
|
1006
|
+
if (lookup.type !== liquid_html_parser_1.NodeTypes.String) {
|
|
1007
|
+
return exports.Untyped;
|
|
1008
|
+
}
|
|
1009
|
+
// When we don't have docs for the parent entry
|
|
1010
|
+
if (!parentEntry) {
|
|
1011
|
+
// It might be that the parent entry is a string.
|
|
1012
|
+
// We do support a couple of properties for those
|
|
1013
|
+
if (curr === 'string') {
|
|
1014
|
+
switch (lookup.value) {
|
|
1015
|
+
// some_string.first
|
|
1016
|
+
// some_string.last
|
|
1017
|
+
case 'first':
|
|
1018
|
+
case 'last':
|
|
1019
|
+
return 'string';
|
|
1020
|
+
// some_string.size
|
|
1021
|
+
case 'size':
|
|
1022
|
+
return 'number';
|
|
1023
|
+
default: {
|
|
1024
|
+
// For the string type, any property access other than first/last/size
|
|
1025
|
+
// is unknown. This is different from an untyped/any object where any
|
|
1026
|
+
// property access would return untyped.
|
|
1027
|
+
// String is a known type with specific properties, so accessing
|
|
1028
|
+
// undefined properties returns an unknown.
|
|
1029
|
+
return exports.Unknown;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
// Or it might be that the parent entry is untyped, so its subproperty
|
|
1034
|
+
// could also be untyped (kind of like if `foo` is `any`, then `foo.bar` is `any`)
|
|
1035
|
+
return exports.Untyped;
|
|
1036
|
+
}
|
|
1037
|
+
const propertyName = lookup.value;
|
|
1038
|
+
const property = parentEntry.properties?.find((property) => property.name === propertyName);
|
|
1039
|
+
// When the propety is not known, return Untyped. e.g.
|
|
1040
|
+
// product.foo
|
|
1041
|
+
// product.bar
|
|
1042
|
+
if (!property) {
|
|
1043
|
+
// Debating between returning Untyped or Unknown here
|
|
1044
|
+
// Might be that we have outdated docs. Prob better to return Untyped.
|
|
1045
|
+
return exports.Untyped;
|
|
1046
|
+
}
|
|
1047
|
+
// When the property is known & we have docs for it, return its type. e.g.
|
|
1048
|
+
// product.image
|
|
1049
|
+
// product.images
|
|
1050
|
+
return objectEntryType(property);
|
|
1051
|
+
}
|
|
1052
|
+
function filterEntryReturnType(entry) {
|
|
1053
|
+
return docsetEntryReturnType(entry, 'string');
|
|
1054
|
+
}
|
|
1055
|
+
function objectEntryType(entry) {
|
|
1056
|
+
return docsetEntryReturnType(entry, entry.name);
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* This function converts the return_type property in one of the .json
|
|
1060
|
+
* files into a PseudoType or ArrayType.
|
|
1061
|
+
*/
|
|
1062
|
+
function docsetEntryReturnType(entry, defaultValue) {
|
|
1063
|
+
const returnTypes = entry.return_type;
|
|
1064
|
+
if (returnTypes && returnTypes.length > 0) {
|
|
1065
|
+
const returnType = returnTypes[0];
|
|
1066
|
+
if (isArrayReturnType(returnType)) {
|
|
1067
|
+
return arrayType(returnType.array_value);
|
|
1068
|
+
}
|
|
1069
|
+
else {
|
|
1070
|
+
return returnType.type;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
return defaultValue;
|
|
1074
|
+
}
|
|
1075
|
+
function isArrayReturnType(rt) {
|
|
1076
|
+
return rt.type === 'array';
|
|
1077
|
+
}
|
|
1078
|
+
function isArrayType(thing) {
|
|
1079
|
+
return typeof thing !== 'string' && thing.kind === 'array';
|
|
1080
|
+
}
|
|
1081
|
+
function isShapeType(thing) {
|
|
1082
|
+
return typeof thing !== 'string' && thing.kind === 'shape';
|
|
1083
|
+
}
|
|
1084
|
+
/** Assumes findLast */
|
|
1085
|
+
function isCorrectTypeRange(typeRange, node) {
|
|
1086
|
+
const [start, end] = typeRange.range;
|
|
1087
|
+
if (end && node.position.start > end)
|
|
1088
|
+
return false;
|
|
1089
|
+
return node.position.start > start;
|
|
1090
|
+
}
|
|
1091
|
+
function end(offset) {
|
|
1092
|
+
if (offset === -1)
|
|
1093
|
+
return undefined;
|
|
1094
|
+
return offset;
|
|
1095
|
+
}
|
|
1096
|
+
function isLiquidTagIncrement(node) {
|
|
1097
|
+
return node.name === liquid_html_parser_1.NamedTags.increment && typeof node.markup !== 'string';
|
|
1098
|
+
}
|
|
1099
|
+
function isLiquidTagDecrement(node) {
|
|
1100
|
+
return node.name === liquid_html_parser_1.NamedTags.decrement && typeof node.markup !== 'string';
|
|
1101
|
+
}
|
|
1102
|
+
function isLiquidTagParseJson(node) {
|
|
1103
|
+
return node.name === liquid_html_parser_1.NamedTags.parse_json && typeof node.markup !== 'string';
|
|
1104
|
+
}
|
|
1105
|
+
function isLiquidTagGraphQL(node) {
|
|
1106
|
+
return node.name === liquid_html_parser_1.NamedTags.graphql && typeof node.markup !== 'string';
|
|
1107
|
+
}
|
|
1108
|
+
function isGraphQLInlineMarkup(markup) {
|
|
1109
|
+
return markup.type === liquid_html_parser_1.NodeTypes.GraphQLInlineMarkup;
|
|
1110
|
+
}
|
|
1111
|
+
function isGraphQLFileMarkup(markup) {
|
|
1112
|
+
return markup.type === liquid_html_parser_1.NodeTypes.GraphQLMarkup;
|
|
1113
|
+
}
|
|
1114
|
+
function isLiquidString(node) {
|
|
1115
|
+
return node.type === liquid_html_parser_1.NodeTypes.String;
|
|
1116
|
+
}
|
|
1117
|
+
function isLiquidTagHashAssign(node) {
|
|
1118
|
+
return node.name === liquid_html_parser_1.NamedTags.hash_assign && typeof node.markup !== 'string';
|
|
1119
|
+
}
|
|
1120
|
+
function isLiquidTagFunction(node) {
|
|
1121
|
+
return node.name === liquid_html_parser_1.NamedTags.function && typeof node.markup !== 'string';
|
|
1122
|
+
}
|
|
1123
|
+
function isUnionType(thing) {
|
|
1124
|
+
return typeof thing !== 'string' && thing.kind === 'union';
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Infer the return type of a function partial by analyzing its {% return %} statements.
|
|
1128
|
+
*/
|
|
1129
|
+
async function inferFunctionReturnType(partialPath, fs, documentsLocator, rootUri, seedSymbolsTable, liquidDrops, graphqlSchema, processingFiles, objectMap, filtersMap) {
|
|
1130
|
+
// 1. Locate the file
|
|
1131
|
+
const located = await documentsLocator.locate(vscode_uri_1.URI.parse(rootUri), 'function', partialPath);
|
|
1132
|
+
if (!located)
|
|
1133
|
+
return undefined;
|
|
1134
|
+
// 2. Check for circular references
|
|
1135
|
+
const trackingSet = processingFiles ?? new Set();
|
|
1136
|
+
if (trackingSet.has(located))
|
|
1137
|
+
return exports.Untyped;
|
|
1138
|
+
trackingSet.add(located);
|
|
1139
|
+
try {
|
|
1140
|
+
// 3. Read and parse the partial
|
|
1141
|
+
const content = await fs.readFile(located);
|
|
1142
|
+
const partialAst = (0, liquid_html_parser_1.toLiquidHtmlAST)(content);
|
|
1143
|
+
// 4. Build symbols table for the partial (recursive)
|
|
1144
|
+
const partialSymbolsTable = await buildSymbolsTable(partialAst, { ...seedSymbolsTable }, // Clone to avoid pollution
|
|
1145
|
+
liquidDrops, graphqlSchema, fs, documentsLocator, rootUri, trackingSet, objectMap, filtersMap);
|
|
1146
|
+
// 5. Find all return statements and infer their types
|
|
1147
|
+
const returnTypes = [];
|
|
1148
|
+
await (0, platformos_check_common_2.visit)(partialAst, {
|
|
1149
|
+
async LiquidTag(node) {
|
|
1150
|
+
if (node.name === liquid_html_parser_1.NamedTags.return && typeof node.markup !== 'string') {
|
|
1151
|
+
// markup is LiquidVariable - infer its type
|
|
1152
|
+
const type = inferType(node.markup, partialSymbolsTable, objectMap, filtersMap);
|
|
1153
|
+
// Flatten union types into individual types
|
|
1154
|
+
if (isUnionType(type)) {
|
|
1155
|
+
returnTypes.push(...type.types);
|
|
1156
|
+
}
|
|
1157
|
+
else {
|
|
1158
|
+
returnTypes.push(type);
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
},
|
|
1162
|
+
});
|
|
1163
|
+
if (returnTypes.length === 0)
|
|
1164
|
+
return undefined;
|
|
1165
|
+
if (returnTypes.length === 1)
|
|
1166
|
+
return returnTypes[0];
|
|
1167
|
+
// Dedupe types (same type appearing multiple times)
|
|
1168
|
+
const uniqueTypes = dedupeTypes(returnTypes);
|
|
1169
|
+
if (uniqueTypes.length === 1)
|
|
1170
|
+
return uniqueTypes[0];
|
|
1171
|
+
return unionType(uniqueTypes);
|
|
1172
|
+
}
|
|
1173
|
+
finally {
|
|
1174
|
+
trackingSet.delete(located);
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Deduplicate types by comparing their structure.
|
|
1179
|
+
*/
|
|
1180
|
+
function dedupeTypes(types) {
|
|
1181
|
+
const seen = new Set();
|
|
1182
|
+
const result = [];
|
|
1183
|
+
for (const type of types) {
|
|
1184
|
+
const key = typeToKey(type);
|
|
1185
|
+
if (!seen.has(key)) {
|
|
1186
|
+
seen.add(key);
|
|
1187
|
+
result.push(type);
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return result;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Convert a type to a string key for deduplication.
|
|
1194
|
+
*/
|
|
1195
|
+
function typeToKey(type) {
|
|
1196
|
+
if (typeof type === 'string')
|
|
1197
|
+
return type;
|
|
1198
|
+
if (type.kind === 'array')
|
|
1199
|
+
return `array:${type.valueType}`;
|
|
1200
|
+
if (type.kind === 'shape')
|
|
1201
|
+
return `shape:${JSON.stringify(shapeToSimpleObject(type.shape))}`;
|
|
1202
|
+
return 'unknown';
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Convert a PropertyShape to a simple object for JSON serialization.
|
|
1206
|
+
*/
|
|
1207
|
+
function shapeToSimpleObject(shape) {
|
|
1208
|
+
if (shape.kind === 'primitive') {
|
|
1209
|
+
return { kind: 'primitive', type: shape.primitiveType };
|
|
1210
|
+
}
|
|
1211
|
+
if (shape.kind === 'array') {
|
|
1212
|
+
return {
|
|
1213
|
+
kind: 'array',
|
|
1214
|
+
itemShape: shape.itemShape ? shapeToSimpleObject(shape.itemShape) : null,
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
if (shape.kind === 'object') {
|
|
1218
|
+
const props = {};
|
|
1219
|
+
if (shape.properties) {
|
|
1220
|
+
for (const [key, value] of shape.properties) {
|
|
1221
|
+
props[key] = shapeToSimpleObject(value);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
return { kind: 'object', properties: props };
|
|
1225
|
+
}
|
|
1226
|
+
return { kind: 'unknown' };
|
|
1227
|
+
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Convert a type to a display string for hover/completions.
|
|
1230
|
+
*/
|
|
1231
|
+
function typeToDisplayString(type) {
|
|
1232
|
+
if (typeof type === 'string')
|
|
1233
|
+
return type;
|
|
1234
|
+
if (type.kind === 'array')
|
|
1235
|
+
return `Array<${type.valueType}>`;
|
|
1236
|
+
if (type.kind === 'shape')
|
|
1237
|
+
return (0, PropertyShapeInference_1.shapeToTypeString)(type.shape);
|
|
1238
|
+
if (type.kind === 'union')
|
|
1239
|
+
return type.types.map((t) => typeToDisplayString(t)).join(' | ');
|
|
1240
|
+
return 'unknown';
|
|
1241
|
+
}
|
|
1242
|
+
/**
|
|
1243
|
+
* Extract the lookup path from a hash_assign target.
|
|
1244
|
+
* For {% hash_assign a['key1']['key2'] = value %}, returns ['key1', 'key2']
|
|
1245
|
+
*/
|
|
1246
|
+
function getHashAssignLookupPath(markup) {
|
|
1247
|
+
const path = [];
|
|
1248
|
+
for (const lookup of markup.target.lookups) {
|
|
1249
|
+
if (lookup.type === liquid_html_parser_1.NodeTypes.String) {
|
|
1250
|
+
path.push(lookup.value);
|
|
1251
|
+
}
|
|
1252
|
+
else if (lookup.type === liquid_html_parser_1.NodeTypes.Number) {
|
|
1253
|
+
path.push(`${lookup.value}`);
|
|
1254
|
+
}
|
|
1255
|
+
else {
|
|
1256
|
+
// Dynamic lookup - can't determine statically
|
|
1257
|
+
return undefined;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
return path.length > 0 ? path : undefined;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Merge a nested property into a shape following a path.
|
|
1264
|
+
* For path ['a', 'b'] and valueShape, creates/updates shape.a.b = valueShape
|
|
1265
|
+
*/
|
|
1266
|
+
function mergeNestedPropertyIntoShape(shape, path, valueShape) {
|
|
1267
|
+
if (path.length === 0) {
|
|
1268
|
+
return valueShape;
|
|
1269
|
+
}
|
|
1270
|
+
const [key, ...rest] = path;
|
|
1271
|
+
if (shape.kind !== 'object') {
|
|
1272
|
+
// Convert to object
|
|
1273
|
+
const properties = new Map();
|
|
1274
|
+
if (rest.length === 0) {
|
|
1275
|
+
properties.set(key, valueShape);
|
|
1276
|
+
}
|
|
1277
|
+
else {
|
|
1278
|
+
properties.set(key, mergeNestedPropertyIntoShape({ kind: 'object', properties: new Map() }, rest, valueShape));
|
|
1279
|
+
}
|
|
1280
|
+
return { kind: 'object', properties };
|
|
1281
|
+
}
|
|
1282
|
+
const newProperties = new Map(shape.properties);
|
|
1283
|
+
if (rest.length === 0) {
|
|
1284
|
+
newProperties.set(key, valueShape);
|
|
1285
|
+
}
|
|
1286
|
+
else {
|
|
1287
|
+
const existingNested = newProperties.get(key) || { kind: 'object', properties: new Map() };
|
|
1288
|
+
newProperties.set(key, mergeNestedPropertyIntoShape(existingNested, rest, valueShape));
|
|
1289
|
+
}
|
|
1290
|
+
return { kind: 'object', properties: newProperties };
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Find the last applicable shape for a variable at a given position
|
|
1294
|
+
*/
|
|
1295
|
+
function findLastApplicableShape(shapes, position) {
|
|
1296
|
+
let result;
|
|
1297
|
+
for (const entry of shapes) {
|
|
1298
|
+
if (entry.rangeEnd < position) {
|
|
1299
|
+
result = entry;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
return result;
|
|
1303
|
+
}
|
|
1304
|
+
function settingReturnType(setting) {
|
|
1305
|
+
switch (setting.type) {
|
|
1306
|
+
// basic settings
|
|
1307
|
+
case 'checkbox':
|
|
1308
|
+
return [{ type: 'boolean', name: '' }];
|
|
1309
|
+
case 'range':
|
|
1310
|
+
case 'number':
|
|
1311
|
+
return [{ type: 'number', name: '' }];
|
|
1312
|
+
case 'radio':
|
|
1313
|
+
case 'select':
|
|
1314
|
+
case 'text':
|
|
1315
|
+
case 'textarea':
|
|
1316
|
+
return [{ type: 'string', name: '' }];
|
|
1317
|
+
// specialized settings
|
|
1318
|
+
case 'article':
|
|
1319
|
+
return [{ type: 'article', name: '' }];
|
|
1320
|
+
case 'blog':
|
|
1321
|
+
return [{ type: 'blog', name: '' }];
|
|
1322
|
+
case 'collection':
|
|
1323
|
+
return [{ type: 'collection', name: '' }];
|
|
1324
|
+
case 'collection_list':
|
|
1325
|
+
return [{ type: 'array', array_value: 'collection' }];
|
|
1326
|
+
case 'color':
|
|
1327
|
+
return [{ type: 'color', name: '' }];
|
|
1328
|
+
case 'color_background':
|
|
1329
|
+
return [{ type: 'string', name: '' }];
|
|
1330
|
+
case 'color_scheme':
|
|
1331
|
+
return [{ type: 'color_scheme', name: '' }];
|
|
1332
|
+
// TODO ??
|
|
1333
|
+
case 'color_scheme_group':
|
|
1334
|
+
return [];
|
|
1335
|
+
case 'font_picker':
|
|
1336
|
+
return [{ type: 'font', name: '' }];
|
|
1337
|
+
case 'html':
|
|
1338
|
+
return [{ type: 'string', name: '' }];
|
|
1339
|
+
case 'image_picker':
|
|
1340
|
+
return [{ type: 'image', name: '' }];
|
|
1341
|
+
case 'inline_richtext':
|
|
1342
|
+
return [{ type: 'string', name: '' }];
|
|
1343
|
+
case 'link_list':
|
|
1344
|
+
return [{ type: 'linklist', name: '' }];
|
|
1345
|
+
case 'liquid':
|
|
1346
|
+
return [{ type: 'string', name: '' }];
|
|
1347
|
+
case 'page':
|
|
1348
|
+
return [{ type: 'page', name: '' }];
|
|
1349
|
+
case 'product':
|
|
1350
|
+
return [{ type: 'product', name: '' }];
|
|
1351
|
+
case 'product_list':
|
|
1352
|
+
return [{ type: 'array', array_value: 'product' }];
|
|
1353
|
+
case 'richtext':
|
|
1354
|
+
return [{ type: 'string', name: '' }];
|
|
1355
|
+
case 'text_alignment':
|
|
1356
|
+
return [{ type: 'string', name: '' }];
|
|
1357
|
+
case 'url':
|
|
1358
|
+
return [{ type: 'string', name: '' }];
|
|
1359
|
+
case 'video':
|
|
1360
|
+
return [{ type: 'video', name: '' }];
|
|
1361
|
+
case 'video_url':
|
|
1362
|
+
return [{ type: 'string', name: '' }];
|
|
1363
|
+
default:
|
|
1364
|
+
return [];
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
const METAFIELD_TYPE_TO_TYPE = Object.freeze({
|
|
1368
|
+
single_line_text_field: String,
|
|
1369
|
+
multi_line_text_field: String,
|
|
1370
|
+
url_reference: String,
|
|
1371
|
+
date: String,
|
|
1372
|
+
date_time: String,
|
|
1373
|
+
number_integer: 'number',
|
|
1374
|
+
number_decimal: 'number',
|
|
1375
|
+
product_reference: 'product',
|
|
1376
|
+
collection_reference: 'collection',
|
|
1377
|
+
variant_reference: 'variant',
|
|
1378
|
+
page_reference: 'page',
|
|
1379
|
+
boolean: 'boolean',
|
|
1380
|
+
color: 'color',
|
|
1381
|
+
weight: 'measurement',
|
|
1382
|
+
volume: 'measurement',
|
|
1383
|
+
dimension: 'measurement',
|
|
1384
|
+
rating: 'rating',
|
|
1385
|
+
money: 'money',
|
|
1386
|
+
json: exports.Untyped,
|
|
1387
|
+
metaobject_reference: 'metaobject',
|
|
1388
|
+
mixed_reference: exports.Untyped,
|
|
1389
|
+
rich_text_field: exports.Untyped,
|
|
1390
|
+
file_reference: exports.Untyped,
|
|
1391
|
+
});
|
|
1392
|
+
const REFERENCE_TYPE_METAFIELDS = Object.entries(METAFIELD_TYPE_TO_TYPE)
|
|
1393
|
+
.filter(([metafieldType, _type]) => metafieldType.endsWith('_reference'))
|
|
1394
|
+
.map(([_metafieldType, type]) => type);
|
|
1395
|
+
function metafieldReturnType(metafieldType) {
|
|
1396
|
+
let isArray = metafieldType.startsWith('list.');
|
|
1397
|
+
if (isArray) {
|
|
1398
|
+
metafieldType = metafieldType.split('.')[1];
|
|
1399
|
+
}
|
|
1400
|
+
let type = 'metafield_' + (METAFIELD_TYPE_TO_TYPE[metafieldType] ?? exports.Untyped);
|
|
1401
|
+
if (isArray) {
|
|
1402
|
+
return [{ type: `${type}_array`, name: '' }];
|
|
1403
|
+
}
|
|
1404
|
+
return [{ type: type, name: '' }];
|
|
1405
|
+
}
|
|
1406
|
+
// The default `metafield` type has an untyped `value` property.
|
|
1407
|
+
// We need to create new metafield types with the labels `metafield_x` and `metafield_x_array`
|
|
1408
|
+
// where x is the type of metafield inside the `value` property. The metafields ending with `x_array`
|
|
1409
|
+
// is where the value is an array of type x.
|
|
1410
|
+
const customMetafieldTypeEntries = (0, utils_1.memo)((baseMetafieldEntry) => {
|
|
1411
|
+
if (!baseMetafieldEntry)
|
|
1412
|
+
return {};
|
|
1413
|
+
return [
|
|
1414
|
+
...new Set([...Object.values(METAFIELD_TYPE_TO_TYPE), ...platformos_check_common_1.FETCHED_METAFIELD_CATEGORIES]),
|
|
1415
|
+
].reduce((map, type) => {
|
|
1416
|
+
{
|
|
1417
|
+
const metafieldEntry = JSON.parse(JSON.stringify(baseMetafieldEntry)); // easy deep clone
|
|
1418
|
+
const metafieldValueProp = metafieldEntry.properties?.find((prop) => prop.name === 'value');
|
|
1419
|
+
if (metafieldValueProp) {
|
|
1420
|
+
metafieldValueProp.return_type = [{ type: type, name: '' }];
|
|
1421
|
+
metafieldValueProp.description = '';
|
|
1422
|
+
metafieldEntry.name = `metafield_${type}`;
|
|
1423
|
+
map[metafieldEntry.name] = metafieldEntry;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
{
|
|
1427
|
+
const metafieldArrayEntry = JSON.parse(JSON.stringify(baseMetafieldEntry)); // easy deep clone
|
|
1428
|
+
const metafieldArrayValueProp = metafieldArrayEntry.properties?.find((prop) => prop.name === 'value');
|
|
1429
|
+
if (metafieldArrayValueProp) {
|
|
1430
|
+
// A metafield definition using a list of references does not use an array, but a separate type of collection.
|
|
1431
|
+
// For auto-completion purposes, we can't use the array type
|
|
1432
|
+
// https://shopify.dev/docs/api/liquid/objects/metafield#metafield-determining-the-length-of-a-list-metafield
|
|
1433
|
+
if (REFERENCE_TYPE_METAFIELDS.includes(type)) {
|
|
1434
|
+
metafieldArrayValueProp.return_type = [{ type: 'untyped', name: '' }];
|
|
1435
|
+
}
|
|
1436
|
+
else {
|
|
1437
|
+
metafieldArrayValueProp.return_type = [{ type: 'array', name: '', array_value: type }];
|
|
1438
|
+
}
|
|
1439
|
+
metafieldArrayValueProp.description = '';
|
|
1440
|
+
metafieldArrayEntry.name = `metafield_${type}_array`;
|
|
1441
|
+
map[metafieldArrayEntry.name] = metafieldArrayEntry;
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
return map;
|
|
1445
|
+
}, {});
|
|
1446
|
+
});
|
|
1447
|
+
function schemaSettingsAsProperties(ast) {
|
|
1448
|
+
if (ast.type !== liquid_html_parser_1.NodeTypes.Document)
|
|
1449
|
+
return [];
|
|
1450
|
+
try {
|
|
1451
|
+
const source = ast._source; // (the unfixed source)
|
|
1452
|
+
const start = /\{%\s*schema\s*%\}/m.exec(source);
|
|
1453
|
+
const end = /\{%\s*endschema\s*%\}/m.exec(source);
|
|
1454
|
+
if (!start || !end)
|
|
1455
|
+
return [];
|
|
1456
|
+
const schema = source.slice(start.index + start[0].length, end.index);
|
|
1457
|
+
const json = (0, platformos_check_common_1.parseJSON)(schema);
|
|
1458
|
+
if ((0, platformos_check_common_1.isError)(json) || !('settings' in json) || !Array.isArray(json.settings))
|
|
1459
|
+
return [];
|
|
1460
|
+
const result = [];
|
|
1461
|
+
const inputSettings = json.settings.filter(settings_1.isInputSetting);
|
|
1462
|
+
for (const setting of inputSettings) {
|
|
1463
|
+
result.push({
|
|
1464
|
+
name: setting.id,
|
|
1465
|
+
summary: '', // TODO, this should lookup the locale file for settings... setting.label
|
|
1466
|
+
description: '', // TODO , this should lookup the locale file as well... setting.info,
|
|
1467
|
+
return_type: settingReturnType(setting),
|
|
1468
|
+
access: {
|
|
1469
|
+
global: false,
|
|
1470
|
+
parents: [],
|
|
1471
|
+
template: [],
|
|
1472
|
+
},
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1475
|
+
return result;
|
|
1476
|
+
}
|
|
1477
|
+
catch (_) {
|
|
1478
|
+
return [];
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
//# sourceMappingURL=TypeSystem.js.map
|