@cratis/screenplay-language 4.216.0 → 4.216.1
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/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js +1 -1
- package/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js.map +1 -1
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js +1 -1
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js.map +1 -1
- package/dist/bundles/compiler/Files/PlayFolderMerge.js +1 -1
- package/dist/bundles/compiler/Files/PlayFolderMerge.js.map +1 -1
- package/dist/bundles/compiler/Parsing/GuardedActionInputs.js +2 -0
- package/dist/bundles/compiler/Parsing/GuardedActionInputs.js.map +1 -0
- package/dist/bundles/compiler/Parsing/GuardedActionValidator.js +1 -1
- package/dist/bundles/compiler/Parsing/GuardedActionValidator.js.map +1 -1
- package/dist/bundles/compiler/Parsing/GuardedInteractions.js +2 -0
- package/dist/bundles/compiler/Parsing/GuardedInteractions.js.map +1 -0
- package/dist/bundles/compiler/Parsing/InteractionAlternatives.js +1 -1
- package/dist/bundles/compiler/Parsing/InteractionAlternatives.js.map +1 -1
- package/dist/bundles/compiler/Parsing/InteractionExecutions.js +2 -0
- package/dist/bundles/compiler/Parsing/InteractionExecutions.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ParserContext.js +1 -1
- package/dist/bundles/compiler/Parsing/ParserContext.js.map +1 -1
- package/dist/bundles/compiler/Parsing/RefusalDeclarations.js.map +1 -1
- package/dist/bundles/compiler/Parsing/ScreenParser.js +1 -1
- package/dist/bundles/compiler/Parsing/ScreenParser.js.map +1 -1
- package/dist/bundles/compiler/Parsing/StructuralInteractionSites.js +3 -0
- package/dist/bundles/compiler/Parsing/StructuralInteractionSites.js.map +1 -0
- package/dist/bundles/compiler/ScreenplayCompiler.js +1 -1
- package/dist/bundles/compiler/ScreenplayCompiler.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuardedActionValidator.js","names":["primitives","declarations","RefusalDeclarations","application","structural","context","binding","ancestor","validateAlternativeShadowing","screen","slice","local","directives","directive","subjects","inherited","slot","structuralChildren","groups","group","depth","key","order","parent","keyword","first","second","entry","bindings","attachment","container","location","outlet","name","candidate","properties","DiagnosticCodes","action","alternative","comparison","validateGuardedActionShadowing","command","commandName","argument","arguments_","inputs","property","subjectProperty","path","segments","index","segment","matches","allowTerminalCollection","type","concept","composite","condition"],"sources":["../../../../../../Compiler/Parsing/GuardedActionValidator.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { ComparisonConditionSyntax, ConditionSyntax } from '../Syntax/Conditions';\nimport { PropertySyntax } from '../Syntax/Declarations';\nimport { InteractionArgumentSyntax, ScreenDataSyntax, ScreenDirectiveSyntax, ScreenGuardedActionSyntax } from '../Syntax/Screens';\nimport { ApplicationSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { validateAlternativeShadowing, validateGuardedActionShadowing } from './GuardedActionShadowing';\nimport { GuardedInteractionBinding, InteractionAncestor } from './InteractionAlternatives';\nimport { ParserContext } from './ParserContext';\nimport { RefusalDeclarations } from './RefusalDeclarations';\n\nconst primitives = new Set(['Uuid', 'String', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime']);\n\n// Resolves known subject and input shapes without guessing imported or ambiguous declarations.\nexport function validateGuardedActions(application: ApplicationSyntax, context: ParserContext): void {\n const declarations = new RefusalDeclarations(application);\n // C# walks structural attachments (including named behaviors) before screen directives.\n const structural = context.guardedInteractions.filter(binding => !binding.ancestors.some(ancestor => ancestor.keyword === 'screen'));\n for (const binding of orderStructuralInteractions(structural)) validateAlternativeShadowing(binding.alternatives, context);\n for (const { slice } of declarations.slices) {\n for (const screen of slice.screens) validateContainer(screen.directives, [], slice, declarations, context);\n }\n}\n\nfunction validateContainer(directives: readonly ScreenDirectiveSyntax[], inherited: readonly ScreenDataSyntax[], slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext): void {\n const local = directives.filter(directive => directive.kind === 'ScreenDataSyntax');\n const subjects = local.length === 0 ? inherited : local;\n for (const directive of directives) {\n switch (directive.kind) {\n case 'ScreenGuardedActionSyntax':\n validateAction(directive, subjects, slice, declarations, context);\n break;\n case 'ScreenBehaviorSyntax':\n validateInteractionAt(directive.location, context);\n break;\n case 'ScreenTableSyntax':\n case 'ScreenComponentSyntax':\n validateInteractionDirectives([directive], context);\n break;\n case 'ScreenSectionSyntax':\n validateContainer(directive.directives, subjects, slice, declarations, context);\n break;\n case 'ScreenTemplateReferenceSyntax':\n for (const slot of directive.slots) validateContainer(slot.directives, subjects, slice, declarations, context);\n break;\n }\n }\n}\n\n// Match the C# walker's child-collection order, not the source order of opaque attachments.\nconst structuralChildren: Readonly<Record<string, readonly string[]>> = {\n application: ['behavior', 'layout', 'module'],\n module: ['screen template', 'dialog', 'form', 'contribute', 'feature', 'on'],\n feature: ['feature', 'slice', 'contribute', 'on'],\n layout: ['slot', 'arrangement', 'on'],\n 'screen template': ['slot', 'arrangement', 'on'],\n dialog: ['slot', 'arrangement', 'on'],\n};\n\nfunction orderStructuralInteractions(bindings: readonly GuardedInteractionBinding[]): readonly GuardedInteractionBinding[] {\n const children = (group: readonly GuardedInteractionBinding[], depth: number, parent: string): GuardedInteractionBinding[] => {\n const groups = new Map<string, { ancestor: InteractionAncestor; bindings: GuardedInteractionBinding[] }>();\n for (const binding of group) {\n const ancestor = binding.ancestors[depth] ?? { keyword: 'on', location: binding.location };\n const key = JSON.stringify(ancestor.location);\n if (!groups.has(key)) groups.set(key, { ancestor, bindings: [] });\n groups.get(key)!.bindings.push(binding);\n }\n const order = structuralChildren[parent] ?? [];\n const rank = (keyword: string) => order.includes(keyword) ? order.indexOf(keyword) : order.length;\n return [...groups.values()].sort((first, second) => rank(first.ancestor.keyword) - rank(second.ancestor.keyword))\n .flatMap(entry => entry.ancestor.keyword === 'on' ? entry.bindings : children(entry.bindings, depth + 1, entry.ancestor.keyword));\n };\n return children(bindings, 0, 'application');\n}\n\nfunction sameLocation(first: SourceLocation, second: SourceLocation): boolean {\n return first.path === second.path && first.line === second.line && first.column === second.column;\n}\n\nfunction validateInteractionAt(location: SourceLocation, context: ParserContext, container = false): void {\n for (const binding of context.guardedInteractions) {\n const attachment = container ? binding.ancestors.at(-1)?.location : binding.location;\n if (attachment !== undefined && sameLocation(attachment, location)) validateAlternativeShadowing(binding.alternatives, context);\n }\n}\n\n// Components validate their attached bindings before their outlets, regardless of authored order.\n// Do not extend the existing guarded-action subject/path checks into previously opaque attachments.\nfunction validateInteractionDirectives(directives: readonly ScreenDirectiveSyntax[], context: ParserContext): void {\n for (const directive of directives) {\n switch (directive.kind) {\n case 'ScreenBehaviorSyntax':\n validateInteractionAt(directive.location, context);\n break;\n case 'ScreenTableSyntax':\n validateInteractionAt(directive.location, context, true);\n break;\n case 'ScreenComponentSyntax':\n validateInteractionAt(directive.location, context, true);\n for (const outlet of directive.outlets) validateInteractionDirectives(outlet.directives, context);\n break;\n case 'ScreenSectionSyntax':\n validateInteractionDirectives(directive.directives, context);\n break;\n case 'ScreenTemplateReferenceSyntax':\n for (const slot of directive.slots) validateInteractionDirectives(slot.directives, context);\n break;\n }\n }\n}\n\nfunction viewProperties(name: string, slice: SliceSyntax, declarations: RefusalDeclarations): readonly PropertySyntax[] | null {\n return declarations.resolve(name, slice, candidate => candidate.readModels)?.node.properties ?? null;\n}\n\nfunction validateAction(action: ScreenGuardedActionSyntax, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext): void {\n const properties = subjects.length === 1 ? viewProperties(subjects[0].type.name, slice, declarations) : null;\n if (subjects.length !== 1) {\n context.warning(DiagnosticCodes.UnresolvedActionSubject, \"A guarded action requires exactly one nearest 'data' subject; no data or equally near data bindings leave 'item' unresolved\", action.location);\n }\n for (const alternative of action.alternatives) {\n for (const comparison of comparisons(alternative.condition)) validateItemPath(comparison.left, comparison.location, properties, slice, declarations, context);\n validateArguments(alternative.command, alternative.arguments, properties, slice, declarations, context);\n }\n if (action.otherwise?.command != null) validateArguments(action.otherwise.command, action.otherwise.arguments, properties, slice, declarations, context);\n validateGuardedActionShadowing(action, context);\n}\n\nfunction validateArguments(commandName: string, arguments_: readonly InteractionArgumentSyntax[], properties: readonly PropertySyntax[] | null, slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext): void {\n const command = declarations.resolve(commandName, slice, candidate => candidate.commands)?.node;\n for (const argument of arguments_) {\n const inputs = command?.properties.filter(property => property.name === argument.name);\n if (inputs?.length === 0) context.warning(DiagnosticCodes.UnknownActionArgumentProperty, `Command '${commandName}' has no argument property '${argument.name}'`, argument.location);\n const subjectProperty = validateItemPath(argument.binding, argument.location, properties, slice, declarations, context, true);\n if (inputs?.length === 1 && subjectProperty !== null && inputs[0].type.isCollection !== subjectProperty.type.isCollection) {\n context.warning(DiagnosticCodes.UnknownActionArgumentProperty, `Command argument '${commandName}.${argument.name}' and subject field '${argument.binding}' must have matching collection cardinality`, argument.location);\n }\n }\n}\n\nfunction validateItemPath(path: string, location: SourceLocation, properties: readonly PropertySyntax[] | null, slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext, allowTerminalCollection = false): PropertySyntax | null {\n if (!path.startsWith('item.') || properties === null) return null;\n const segments = path.substring('item.'.length).split('.');\n for (const [index, segment] of segments.entries()) {\n const matches: readonly PropertySyntax[] = properties.filter(property => property.name === segment);\n if (matches.length === 0 || (matches.length === 1 && matches[0].type.isCollection && (!allowTerminalCollection || index < segments.length - 1))) {\n context.warning(DiagnosticCodes.UnknownActionSubjectField, `Unknown or collection-valued subject field '${path}' - guarded actions require an item field path`, location);\n return null;\n }\n if (matches.length !== 1) return null;\n if (index === segments.length - 1) return matches[0];\n const type = matches[0].type;\n properties = declarations.types.get(type.name)?.properties ?? viewProperties(type.name, slice, declarations);\n if (properties === null) {\n if (primitives.has(type.name) || declarations.application.concepts.some(concept => concept.name === type.name) && !declarations.application.types.some(composite => composite.name === type.name)) {\n context.warning(DiagnosticCodes.UnknownActionSubjectField, `Subject field '${path}' continues past scalar '${segment}'`, location);\n }\n return null;\n }\n }\n return null;\n}\n\nfunction comparisons(condition: ConditionSyntax): readonly ComparisonConditionSyntax[] {\n return condition.kind === 'ComparisonConditionSyntax' ? [condition] : [...comparisons(condition.left), ...comparisons(condition.right)];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"GuardedActionValidator.js","names":["declarations","RefusalDeclarations","application","interactions","GuardedInteractions","context","screen","slice","direct","subjects","subject","table","source","fields","viewProperties","property","local","directives","directive","inherited","outlet","slot","properties","DiagnosticCodes","action","alternative","comparison","comparisons","validateItemPath","validateArguments","validateGuardedActionShadowing"],"sources":["../../../../../../Compiler/Parsing/GuardedActionValidator.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { ScreenDataSyntax, ScreenDirectiveSyntax, ScreenGuardedActionSyntax, ScreenTableSyntax } from '../Syntax/Screens';\nimport { ApplicationSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { comparisons, validateArguments, validateItemPath, viewProperties } from './GuardedActionInputs';\nimport { validateGuardedActionShadowing } from './GuardedActionShadowing';\nimport { GuardedInteractions } from './GuardedInteractions';\nimport { ParserContext } from './ParserContext';\nimport { RefusalDeclarations } from './RefusalDeclarations';\n\n// Resolves known subject and input shapes without guessing imported or ambiguous declarations.\nexport function validateGuardedActions(application: ApplicationSyntax, context: ParserContext): void {\n const declarations = new RefusalDeclarations(application);\n const interactions = new GuardedInteractions(declarations, context);\n interactions.structural(application);\n for (const { slice } of declarations.slices) {\n for (const screen of slice.screens) validateContainer(screen.directives, [], slice, declarations, context, interactions);\n }\n}\n\nfunction tableSubjects(table: ScreenTableSyntax, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax, declarations: RefusalDeclarations): readonly ScreenDataSyntax[] {\n const direct = subjects.filter(subject => subject.type.name === table.target);\n if (direct.length > 0 || subjects.length !== 1) return direct;\n const source = subjects[0];\n const fields = viewProperties(source.type.name, slice, declarations)?.filter(property => property.name === table.target && property.type.isCollection);\n return fields?.length === 1 ? [{ ...source, type: fields[0].type, by: null, location: table.location }] : [];\n}\n\nfunction validateContainer(directives: readonly ScreenDirectiveSyntax[], inherited: readonly ScreenDataSyntax[], slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext, interactions: GuardedInteractions): void {\n const local = directives.filter(directive => directive.kind === 'ScreenDataSyntax');\n const subjects = local.length === 0 ? inherited : local;\n for (const directive of directives) {\n switch (directive.kind) {\n case 'ScreenGuardedActionSyntax':\n validateAction(directive, subjects, slice, declarations, context);\n break;\n case 'ScreenBehaviorSyntax':\n interactions.at(directive.location, subjects, slice);\n break;\n case 'ScreenUsesBehaviorSyntax':\n interactions.useAt(directive.location, subjects, slice);\n break;\n case 'ScreenTableSyntax':\n interactions.at(directive.location, tableSubjects(directive, subjects, slice, declarations), slice, true);\n break;\n case 'ScreenComponentSyntax':\n interactions.at(directive.location, subjects, slice, true);\n for (const outlet of directive.outlets) validateContainer(outlet.directives, subjects, slice, declarations, context, interactions);\n break;\n case 'ScreenSectionSyntax':\n validateContainer(directive.directives, subjects, slice, declarations, context, interactions);\n break;\n case 'ScreenTemplateReferenceSyntax':\n for (const slot of directive.slots) validateContainer(slot.directives, subjects, slice, declarations, context, interactions);\n break;\n }\n }\n}\n\nfunction validateAction(action: ScreenGuardedActionSyntax, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax, declarations: RefusalDeclarations, context: ParserContext): void {\n const properties = subjects.length === 1 ? viewProperties(subjects[0].type.name, slice, declarations) : null;\n if (subjects.length !== 1) {\n context.warning(DiagnosticCodes.UnresolvedActionSubject, \"A guarded action requires exactly one nearest 'data' subject; no data or equally near data bindings leave 'item' unresolved\", action.location);\n }\n for (const alternative of action.alternatives) {\n for (const comparison of comparisons(alternative.condition)) validateItemPath(comparison.left, comparison.location, properties, slice, declarations, context);\n validateArguments(alternative.command, alternative.arguments, properties, slice, declarations, context);\n }\n if (action.otherwise?.command != null) validateArguments(action.otherwise.command, action.otherwise.arguments, properties, slice, declarations, context);\n validateGuardedActionShadowing(action, context);\n}\n"],"mappings":"4bAaA,SAAgB,uBAAuB,EAAgC,EAA8B,CACjG,IAAMA,EAAe,IAAIC,EAAoBC,CAAW,EAClDC,EAAe,IAAIC,EAAoBJ,EAAcK,CAAO,EAClEF,EAAa,WAAWD,CAAW,EACnC,IAAK,GAAM,CAAE,WAAWF,EAAa,OACjC,IAAK,IAAMM,KAAUC,EAAM,QAAS,kBAAkBD,EAAO,WAAY,CAAC,EAAGC,EAAOP,EAAcK,EAASF,CAAY,CAE/H,CAEA,SAAS,cAAc,EAA0B,EAAuC,EAAoB,EAAgE,CACxK,IAAMK,EAASC,EAAS,OAAO,GAAWC,EAAQ,KAAK,OAASC,EAAM,MAAM,EAC5E,GAAIH,EAAO,OAAS,GAAKC,EAAS,SAAW,EAAG,OAAOD,EACvD,IAAMI,EAASH,EAAS,GAClBI,EAASC,EAAeF,EAAO,KAAK,KAAML,EAAOP,CAAY,CAAC,EAAE,OAAO,GAAYe,EAAS,OAASJ,EAAM,QAAUI,EAAS,KAAK,YAAY,EACrJ,OAAOF,GAAQ,SAAW,EAAI,CAAC,CAAE,GAAGD,EAAQ,KAAMC,EAAO,EAAE,CAAC,KAAM,GAAI,KAAM,SAAUF,EAAM,QAAS,CAAC,EAAI,CAAC,CAC/G,CAEA,SAAS,kBAAkB,EAA8C,EAAwC,EAAoB,EAAmC,EAAwB,EAAyC,CACrO,IAAMK,EAAQC,EAAW,OAAO,GAAaC,EAAU,OAAS,kBAAkB,EAC5ET,EAAWO,EAAM,SAAW,EAAIG,EAAYH,EAClD,IAAK,IAAME,KAAaD,EACpB,OAAQC,EAAU,KAAlB,CACI,IAAK,4BACD,eAAeA,EAAWT,EAAUF,EAAOP,EAAcK,CAAO,EAChE,MACJ,IAAK,uBACDF,EAAa,GAAGe,EAAU,SAAUT,EAAUF,CAAK,EACnD,MACJ,IAAK,2BACDJ,EAAa,MAAMe,EAAU,SAAUT,EAAUF,CAAK,EACtD,MACJ,IAAK,oBACDJ,EAAa,GAAGe,EAAU,SAAU,cAAcA,EAAWT,EAAUF,EAAOP,CAAY,EAAGO,EAAO,EAAI,EACxG,MACJ,IAAK,wBACDJ,EAAa,GAAGe,EAAU,SAAUT,EAAUF,EAAO,EAAI,EACzD,IAAK,IAAMa,KAAUF,EAAU,QAAS,kBAAkBE,EAAO,WAAYX,EAAUF,EAAOP,EAAcK,EAASF,CAAY,EACjI,MACJ,IAAK,sBACD,kBAAkBe,EAAU,WAAYT,EAAUF,EAAOP,EAAcK,EAASF,CAAY,EAC5F,MACJ,IAAK,gCACD,IAAK,IAAMkB,KAAQH,EAAU,MAAO,kBAAkBG,EAAK,WAAYZ,EAAUF,EAAOP,EAAcK,EAASF,CAAY,CAEnI,CAER,CAEA,SAAS,eAAe,EAAmC,EAAuC,EAAoB,EAAmC,EAA8B,CACnL,IAAMmB,EAAab,EAAS,SAAW,EAAIK,EAAeL,EAAS,EAAE,CAAC,KAAK,KAAMF,EAAOP,CAAY,EAAI,KACpGS,EAAS,SAAW,GACpBJ,EAAQ,QAAQkB,EAAgB,wBAAyB,8HAA+HC,EAAO,QAAQ,EAE3M,IAAK,IAAMC,KAAeD,EAAO,aAAc,CAC3C,IAAK,IAAME,KAAcC,EAAYF,EAAY,SAAS,EAAGG,EAAiBF,EAAW,KAAMA,EAAW,SAAUJ,EAAYf,EAAOP,EAAcK,CAAO,EAC5JwB,EAAkBJ,EAAY,QAASA,EAAY,UAAWH,EAAYf,EAAOP,EAAcK,CAAO,CAC1G,CACImB,EAAO,WAAW,SAAW,MAAMK,EAAkBL,EAAO,UAAU,QAASA,EAAO,UAAU,UAAWF,EAAYf,EAAOP,EAAcK,CAAO,EACvJyB,EAA+BN,EAAQnB,CAAO,CAClD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{effectiveStructuralInteractions as t,sameInteractionLocation as n}from"./StructuralInteractionSites.js";import{ParserContext as r}from"./ParserContext.js";import{comparisons as i,validateArguments as a,validateItemPath as o,viewProperties as s}from"./GuardedActionInputs.js";import{validateAlternativeShadowing as c}from"./GuardedActionShadowing.js";var GuardedInteractions=class{declarations;context;constructor(e,t){this.declarations=e,this.context=t}structural(e){for(let n of t(e))`behavior`in n?this.validateUse(n,[],void 0):n.ancestors.some(e=>e.keyword===`behavior`)?c(n.alternatives,this.context):this.validate(n,[],void 0,this.context)}at(e,t,r,i=!1){for(let a of this.context.guardedInteractions){let o=i?a.ancestors.at(-1)?.location:a.location;o!==void 0&&n(o,e)&&this.validate(a,t,r,this.context)}if(i)for(let i of this.context.interactionUses){let a=i.ancestors.at(-1)?.location;a!==void 0&&n(a,e)&&this.validateUse(i,t,r)}}useAt(e,t,r){for(let i of this.context.interactionUses.filter(t=>n(t.location,e)))this.validateUse(i,t,r)}validateUse(e,t,i){let a=this.context.interactionBehaviors.filter(t=>t.name===e.behavior);if(a.length!==1)return;let o=new r(this.context.reader);for(let r of this.context.guardedInteractions)r.ancestors.some(e=>e.keyword===`behavior`&&n(e.location,a[0].location))&&this.validate(r,t,i,o,e.location);for(let e of o.diagnostics)this.context.diagnostics.some(t=>t.code===e.code&&t.message===e.message&&t.severity===e.severity&&n(t.location,e.location))||this.context.warning(e.code,e.message,e.location,e.arguments)}validate(t,n,r,l,u){let d=n.length===1?s(n[0].type.name,r,this.declarations)??this.declarations.types.get(n[0].type.name)?.properties??null:null;n.length!==1&&l.warning(e.UnresolvedActionSubject,`A guarded interaction requires exactly one nearest 'data' subject; component context and selection do not supply 'item'`,u??t.location);for(let e of t.alternatives){for(let t of i(e.condition))o(t.left,t.location,d,r,this.declarations,l);for(let t of e.executions)a(t.command,t.arguments,d,r,this.declarations,l)}for(let e of t.otherwise)a(e.command,e.arguments,d,r,this.declarations,l);u===void 0&&c(t.alternatives,l)}};export{GuardedInteractions};
|
|
2
|
+
//# sourceMappingURL=GuardedInteractions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedInteractions.js","names":["declarations","context","site","effectiveStructuralInteractions","application","ancestor","validateAlternativeShadowing","binding","attachment","container","sameInteractionLocation","location","subjects","slice","uses","matches","behavior","ParserContext","diagnostic","existing","properties","viewProperties","DiagnosticCodes","alternative","comparison","comparisons","validateItemPath","execution","validateArguments"],"sources":["../../../../../../Compiler/Parsing/GuardedInteractions.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { ScreenDataSyntax } from '../Syntax/Screens';\nimport { ApplicationSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { comparisons, validateArguments, validateItemPath, viewProperties } from './GuardedActionInputs';\nimport { validateAlternativeShadowing } from './GuardedActionShadowing';\nimport { GuardedInteractionBinding } from './InteractionAlternatives';\nimport { effectiveStructuralInteractions, sameInteractionLocation } from './StructuralInteractionSites';\nimport { InteractionUse } from './InteractionUse';\nimport { ParserContext } from './ParserContext';\nimport { RefusalDeclarations } from './RefusalDeclarations';\n\n// Subject-dependent interaction checks share the guarded screen-action path and input validators.\nexport class GuardedInteractions {\n constructor(private readonly declarations: RefusalDeclarations, private readonly context: ParserContext) {}\n\n structural(application: ApplicationSyntax): void {\n for (const site of effectiveStructuralInteractions(application)) {\n if ('behavior' in site) this.validateUse(site, [], undefined);\n else if (site.ancestors.some(ancestor => ancestor.keyword === 'behavior')) validateAlternativeShadowing(site.alternatives, this.context);\n else this.validate(site, [], undefined, this.context);\n }\n }\n\n at(location: SourceLocation, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax, container = false): void {\n for (const binding of this.context.guardedInteractions) {\n const attachment = container ? binding.ancestors.at(-1)?.location : binding.location;\n if (attachment !== undefined && sameInteractionLocation(attachment, location)) this.validate(binding, subjects, slice, this.context);\n }\n if (container) {\n for (const uses of this.context.interactionUses) {\n const attachment = uses.ancestors.at(-1)?.location;\n if (attachment !== undefined && sameInteractionLocation(attachment, location)) this.validateUse(uses, subjects, slice);\n }\n }\n }\n\n useAt(location: SourceLocation, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax): void {\n for (const uses of this.context.interactionUses.filter(uses => sameInteractionLocation(uses.location, location))) this.validateUse(uses, subjects, slice);\n }\n\n private validateUse(uses: InteractionUse, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax | undefined): void {\n const matches = this.context.interactionBehaviors.filter(behavior => behavior.name === uses.behavior);\n if (matches.length !== 1) return;\n const site = new ParserContext(this.context.reader);\n for (const binding of this.context.guardedInteractions) {\n if (binding.ancestors.some(ancestor => ancestor.keyword === 'behavior' && sameInteractionLocation(ancestor.location, matches[0].location))) {\n this.validate(binding, subjects, slice, site, uses.location);\n }\n }\n for (const diagnostic of site.diagnostics) {\n if (!this.context.diagnostics.some(existing => existing.code === diagnostic.code && existing.message === diagnostic.message && existing.severity === diagnostic.severity && sameInteractionLocation(existing.location, diagnostic.location))) {\n this.context.warning(diagnostic.code, diagnostic.message, diagnostic.location, diagnostic.arguments);\n }\n }\n }\n\n private validate(binding: GuardedInteractionBinding, subjects: readonly ScreenDataSyntax[], slice: SliceSyntax | undefined, context: ParserContext, attachment?: SourceLocation): void {\n const properties = subjects.length === 1 ? viewProperties(subjects[0].type.name, slice, this.declarations) ?? this.declarations.types.get(subjects[0].type.name)?.properties ?? null : null;\n if (subjects.length !== 1) {\n context.warning(DiagnosticCodes.UnresolvedActionSubject, \"A guarded interaction requires exactly one nearest 'data' subject; component context and selection do not supply 'item'\", attachment ?? binding.location);\n }\n for (const alternative of binding.alternatives) {\n for (const comparison of comparisons(alternative.condition)) validateItemPath(comparison.left, comparison.location, properties, slice, this.declarations, context);\n for (const execution of alternative.executions) validateArguments(execution.command, execution.arguments, properties, slice, this.declarations, context);\n }\n for (const execution of binding.otherwise) validateArguments(execution.command, execution.arguments, properties, slice, this.declarations, context);\n if (attachment === undefined) validateAlternativeShadowing(binding.alternatives, context);\n }\n}\n"],"mappings":"8dAgBA,IAAa,oBAAb,KAAiC,CACA,aAAoD,QAAjF,YAAY,EAAoD,EAAyC,CAA5E,KAAA,aAAAA,EAAoD,KAAA,QAAAC,CAAyB,CAE1G,WAAW,EAAsC,CAC7C,IAAK,IAAMC,KAAQC,EAAgCC,CAAW,EACtD,aAAcF,EAAM,KAAK,YAAYA,EAAM,CAAC,EAAG,IAAA,EAAS,EACnDA,EAAK,UAAU,KAAK,GAAYG,EAAS,UAAY,UAAU,EAAGC,EAA6BJ,EAAK,aAAc,KAAK,OAAO,EAClI,KAAK,SAASA,EAAM,CAAC,EAAG,IAAA,GAAW,KAAK,OAAO,CAE5D,CAEA,GAAG,EAA0B,EAAuC,EAAoB,EAAY,GAAa,CAC7G,IAAK,IAAMK,KAAW,KAAK,QAAQ,oBAAqB,CACpD,IAAMC,EAAaC,EAAYF,EAAQ,UAAU,GAAG,EAAE,CAAC,EAAE,SAAWA,EAAQ,SACxEC,IAAe,IAAA,IAAaE,EAAwBF,EAAYG,CAAQ,GAAG,KAAK,SAASJ,EAASK,EAAUC,EAAO,KAAK,OAAO,CACvI,CACA,GAAIJ,EACA,IAAK,IAAMK,KAAQ,KAAK,QAAQ,gBAAiB,CAC7C,IAAMN,EAAaM,EAAK,UAAU,GAAG,EAAE,CAAC,EAAE,SACtCN,IAAe,IAAA,IAAaE,EAAwBF,EAAYG,CAAQ,GAAG,KAAK,YAAYG,EAAMF,EAAUC,CAAK,CACzH,CAER,CAEA,MAAM,EAA0B,EAAuC,EAA0B,CAC7F,IAAK,IAAMC,KAAQ,KAAK,QAAQ,gBAAgB,OAAO,GAAQJ,EAAwBI,EAAK,SAAUH,CAAQ,CAAC,EAAG,KAAK,YAAYG,EAAMF,EAAUC,CAAK,CAC5J,CAEA,YAAoB,EAAsB,EAAuC,EAAsC,CACnH,IAAME,EAAU,KAAK,QAAQ,qBAAqB,OAAO,GAAYC,EAAS,OAASF,EAAK,QAAQ,EACpG,GAAIC,EAAQ,SAAW,EAAG,OAC1B,IAAMb,EAAO,IAAIe,EAAc,KAAK,QAAQ,MAAM,EAClD,IAAK,IAAMV,KAAW,KAAK,QAAQ,oBAC3BA,EAAQ,UAAU,KAAK,GAAYF,EAAS,UAAY,YAAcK,EAAwBL,EAAS,SAAUU,EAAQ,EAAE,CAAC,QAAQ,CAAC,GACrI,KAAK,SAASR,EAASK,EAAUC,EAAOX,EAAMY,EAAK,QAAQ,EAGnE,IAAK,IAAMI,KAAchB,EAAK,YACrB,KAAK,QAAQ,YAAY,KAAK,GAAYiB,EAAS,OAASD,EAAW,MAAQC,EAAS,UAAYD,EAAW,SAAWC,EAAS,WAAaD,EAAW,UAAYR,EAAwBS,EAAS,SAAUD,EAAW,QAAQ,CAAC,GACvO,KAAK,QAAQ,QAAQA,EAAW,KAAMA,EAAW,QAASA,EAAW,SAAUA,EAAW,SAAS,CAG/G,CAEA,SAAiB,EAAoC,EAAuC,EAAgC,EAAwB,EAAmC,CACnL,IAAME,EAAaR,EAAS,SAAW,EAAIS,EAAeT,EAAS,EAAE,CAAC,KAAK,KAAMC,EAAO,KAAK,YAAY,GAAK,KAAK,aAAa,MAAM,IAAID,EAAS,EAAE,CAAC,KAAK,IAAI,CAAC,EAAE,YAAc,KAAO,KACnLA,EAAS,SAAW,GACpBX,EAAQ,QAAQqB,EAAgB,wBAAyB,0HAA2Hd,GAAcD,EAAQ,QAAQ,EAEtN,IAAK,IAAMgB,KAAehB,EAAQ,aAAc,CAC5C,IAAK,IAAMiB,KAAcC,EAAYF,EAAY,SAAS,EAAGG,EAAiBF,EAAW,KAAMA,EAAW,SAAUJ,EAAYP,EAAO,KAAK,aAAcZ,CAAO,EACjK,IAAK,IAAM0B,KAAaJ,EAAY,WAAYK,EAAkBD,EAAU,QAASA,EAAU,UAAWP,EAAYP,EAAO,KAAK,aAAcZ,CAAO,CAC3J,CACA,IAAK,IAAM0B,KAAapB,EAAQ,UAAWqB,EAAkBD,EAAU,QAASA,EAAU,UAAWP,EAAYP,EAAO,KAAK,aAAcZ,CAAO,EAC9IO,IAAe,IAAA,IAAWF,EAA6BC,EAAQ,aAAcN,CAAO,CAC5F,CACJ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{dotNetWhitespace as t,pattern as n}from"../Text/patterns.js";import{locationOf as r}from"./SourceLine.js";import{firstWord as i}from"./LineText.js";import{
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{dotNetWhitespace as t,pattern as n}from"../Text/patterns.js";import{locationOf as r}from"./SourceLine.js";import{firstWord as i}from"./LineText.js";import{interactionBody as a,interactionExecutions as o}from"./InteractionExecutions.js";import{parseCondition as s}from"./ConditionParser.js";import{validateCondition as c}from"./GuardedActionParser.js";import{LineReader as l}from"./LineReader.js";import{ParserContext as u}from"./ParserContext.js";const d=n(`^screen${t}+template(?:${t}|$)`);function interactionAncestry(e){let t=/* @__PURE__ */ new Map,n=[],a=!1;for(let o of e)if(o.content.startsWith("```"))a=!a;else if(!(a||o.content.length===0||o.content.startsWith(`//`))){for(;n.length>0&&n[n.length-1].indent>=o.indent;)n.pop();[`on`,`uses`].includes(i(o.content))&&t.set(o.number,n.map(e=>({keyword:d.test(e.content)?`screen template`:i(e.content),location:r(e)}))),n.push(o)}return t}const f=n(`^when${t}+([^\\n]+)${t}+execute${t}+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),p=n(`^on${t}+([^\\n]+)$`),m=n(`^where${t}+([^\\n]+)$`),h=/* @__PURE__ */ new Set([`execute`,`navigate`,`open`,`close`,`refresh`,`set`,`notify`,`confirm`,`raise`]),g=n(`^behavior${t}+([A-Za-z_]\\w*)$`),_=n(`^uses${t}+([A-Za-z_]\\w*)$`),v=n(`^([A-Za-z_]\\w*)${t}+([^\\n]+)$`);function validateInteractionBodies(t,n){let l=g.exec(n[0]?.content??``);l!==null&&t.interactionBehaviors.push({name:l[1],location:r(n[0])});for(let l=0;l<n.length;l++){let u=n[l],d=_.exec(u.content);d!==null&&t.interactionUses.push({behavior:d[1],location:r(u),ancestors:t.interactionAncestors.get(u.number)??[],arguments:a(n,u).flatMap(e=>{let t=v.exec(e.content);return t===null?[]:[{name:t[1],value:t[2].trim()}]})});let g=p.exec(u.content);if(g===null||g[1].startsWith(`row-click `))continue;let y=[];for(let e=l+1;e<n.length&&n[e].indent>u.indent;e++)y.push(n[e]);let b=y.filter(e=>e.indent===y[0]?.indent),x=b.filter(e=>[`when`,`otherwise`].includes(i(e.content))),S=[`click`,`double click`,`select`].includes(g[1].trim()),C=b.filter(e=>m.test(e.content)),w=[],T=[],E=!1;for(let n of x){let l=i(n.content)===`when`,u=l?f.exec(n.content):null;if(l){E&&t.error(e.MisplacedActionOtherwise,`A 'when' alternative must precede 'otherwise'`,r(n));let i=s(t,u?.[1]??n.content.slice(4).trim(),r(n),!0);if(i!==null){c(t,i);let e=o(u===null?a(y,n):[{...n,content:`execute ${u[2]}`},...a(y,n)]);w.push({condition:i,executions:e,location:r(n),message:`This 'when' alternative is shadowed by earlier alternatives in this interaction`})}u!==null&&t.error(e.InlineInteractionAlternative,`Interaction alternatives require an indented action list, not 'when <condition> execute <Command>'`,r(n))}else(E||n.content!==`otherwise`)&&t.error(e.MisplacedActionOtherwise,`An interaction permits one final block-form 'otherwise'`,r(n)),E=!0,T=o(a(y,n));let d=y[y.indexOf(n)+1];u===null&&(d===void 0||d.indent<=n.indent||!h.has(i(d.content)))&&t.error(e.InteractionAlternativeWithoutActions,`An interaction alternative requires a non-empty action list`,r(n))}if(x.length>0&&(S||t.error(e.UnsupportedInteractionAlternatives,`Interaction alternatives are only supported on click, double click and select`,r(u)),(C.length>0||b.some(e=>h.has(i(e.content))))&&t.error(e.MixedInteractionAlternatives,`Interaction alternatives cannot mix with plain actions or 'where'`,r(u)),x.some(e=>i(e.content)===`when`)||t.error(e.GuardedActionWithoutAlternatives,`A guarded interaction requires at least one 'when' alternative`,r(u))),S)for(let e of C)deprecateWhere(t,e);w.length>0&&t.guardedInteractions.push({location:r(u),ancestors:t.interactionAncestors.get(u.number)??[],alternatives:w,otherwise:T})}}function deprecateWhere(t,n){let i=new u(new l([]));i.sourceOptions=t.sourceOptions;let a=s(i,m.exec(n.content)[1].trim(),r(n),!0);a!==null&&c(i,a);let o=`Opaque 'where' on click, double click and select is deprecated; use block-form 'when' item conditions`;a!==null&&i.diagnostics.length===0?t.warning(e.LegacyInteractionWhere,o,r(n)):t.information(e.LegacyInteractionWhere,o,r(n))}export{interactionAncestry,validateInteractionBodies};
|
|
2
2
|
//# sourceMappingURL=InteractionAlternatives.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractionAlternatives.js","names":["screenTemplate","pattern","dotNetWhitespace","result","ancestors","fenced","line","lines","firstWord","ancestor","locationOf","inline","trigger","where","actions","index","header","on","body","child","children","branches","supported","guards","alternatives","sawOtherwise","branch","isWhen","match","context","DiagnosticCodes","condition","parseCondition","validateCondition","nested","guard","probe","ParserContext","LineReader","message"],"sources":["../../../../../../Compiler/Parsing/InteractionAlternatives.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { ShadowingAlternative } from './GuardedActionShadowing';\nimport { dotNetWhitespace, pattern } from '../Text/patterns';\nimport { parseCondition } from './ConditionParser';\nimport { validateCondition } from './GuardedActionParser';\nimport { firstWord } from './LineText';\nimport { LineReader } from './LineReader';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Authoring facts only: interaction bodies are still opaque in the serialized TS AST.\nexport interface InteractionAncestor {\n readonly keyword: string;\n readonly location: SourceLocation;\n}\n\nexport interface GuardedInteractionBinding {\n readonly location: SourceLocation;\n readonly ancestors: readonly InteractionAncestor[];\n readonly alternatives: readonly ShadowingAlternative[];\n}\n\nconst screenTemplate = pattern(`^screen${dotNetWhitespace}+template(?:${dotNetWhitespace}|$)`);\n\n// Capture attachment ancestry before parsing consumes opaque bodies. Fenced code is not Screenplay.\nexport function interactionAncestry(lines: readonly SourceLine[]): ReadonlyMap<number, readonly InteractionAncestor[]> {\n const result = new Map<number, readonly InteractionAncestor[]>();\n const ancestors: SourceLine[] = [];\n let fenced = false;\n for (const line of lines) {\n if (line.content.startsWith('```')) {\n fenced = !fenced;\n continue;\n }\n if (fenced || line.content.length === 0 || line.content.startsWith('//')) continue;\n while (ancestors.length > 0 && ancestors[ancestors.length - 1].indent >= line.indent) ancestors.pop();\n if (firstWord(line.content) === 'on') result.set(line.number, ancestors.map(ancestor => ({ keyword: screenTemplate.test(ancestor.content) ? 'screen template' : firstWord(ancestor.content), location: locationOf(ancestor) })));\n ancestors.push(line);\n }\n return result;\n}\n\nconst inline = pattern(`^when${dotNetWhitespace}+([^\\\\n]+)${dotNetWhitespace}+execute${dotNetWhitespace}+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$`);\nconst trigger = pattern(`^on${dotNetWhitespace}+([^\\\\n]+)$`);\nconst where = pattern(`^where${dotNetWhitespace}+([^\\\\n]+)$`);\nconst actions = new Set(['execute', 'navigate', 'open', 'close', 'refresh', 'set', 'notify', 'confirm', 'raise']);\n\n// Interaction bodies remain opaque in the TS AST. Check their structure instead of silently accepting\n// alternatives the C# compiler refuses. Input collection supplies only significant, non-fenced lines.\nexport function validateInteractionBodies(context: ParserContext, lines: readonly SourceLine[]): void {\n for (let index = 0; index < lines.length; index++) {\n const header = lines[index];\n const on = trigger.exec(header.content);\n if (on === null || on[1].startsWith('row-click ')) continue;\n const body: SourceLine[] = [];\n for (let child = index + 1; child < lines.length && lines[child].indent > header.indent; child++) body.push(lines[child]);\n const children = body.filter(line => line.indent === body[0]?.indent);\n const branches = children.filter(line => ['when', 'otherwise'].includes(firstWord(line.content)));\n const supported = ['click', 'double click', 'select'].includes(on[1].trim());\n const guards = children.filter(line => where.test(line.content));\n const alternatives: ShadowingAlternative[] = [];\n let sawOtherwise = false;\n for (const branch of branches) {\n const isWhen = firstWord(branch.content) === 'when';\n const match = isWhen ? inline.exec(branch.content) : null;\n if (isWhen) {\n if (sawOtherwise) context.error(DiagnosticCodes.MisplacedActionOtherwise, \"A 'when' alternative must precede 'otherwise'\", locationOf(branch));\n const condition = parseCondition(context, match?.[1] ?? branch.content.slice(4).trim(), locationOf(branch), true);\n if (condition !== null) {\n validateCondition(context, condition);\n alternatives.push({ condition, location: locationOf(branch), message: \"This 'when' alternative is shadowed by earlier alternatives in this interaction\" });\n }\n if (match !== null) context.error(DiagnosticCodes.InlineInteractionAlternative, \"Interaction alternatives require an indented action list, not 'when <condition> execute <Command>'\", locationOf(branch));\n } else {\n if (sawOtherwise || branch.content !== 'otherwise') context.error(DiagnosticCodes.MisplacedActionOtherwise, \"An interaction permits one final block-form 'otherwise'\", locationOf(branch));\n sawOtherwise = true;\n }\n const position = body.indexOf(branch);\n const nested = body[position + 1];\n if (match === null && (nested === undefined || nested.indent <= branch.indent || !actions.has(firstWord(nested.content)))) {\n context.error(DiagnosticCodes.InteractionAlternativeWithoutActions, 'An interaction alternative requires a non-empty action list', locationOf(branch));\n }\n }\n if (branches.length > 0) {\n if (!supported) context.error(DiagnosticCodes.UnsupportedInteractionAlternatives, 'Interaction alternatives are only supported on click, double click and select', locationOf(header));\n if (guards.length > 0 || children.some(line => actions.has(firstWord(line.content)))) {\n context.error(DiagnosticCodes.MixedInteractionAlternatives, \"Interaction alternatives cannot mix with plain actions or 'where'\", locationOf(header));\n }\n if (!branches.some(line => firstWord(line.content) === 'when')) context.error(DiagnosticCodes.GuardedActionWithoutAlternatives, \"A guarded interaction requires at least one 'when' alternative\", locationOf(header));\n }\n if (supported) for (const guard of guards) deprecateWhere(context, guard);\n if (alternatives.length > 0) context.guardedInteractions.push({ location: locationOf(header), ancestors: context.interactionAncestors.get(header.number) ?? [], alternatives });\n }\n}\n\nfunction deprecateWhere(context: ParserContext, line: SourceLine): void {\n const probe = new ParserContext(new LineReader([]));\n probe.sourceOptions = context.sourceOptions;\n const condition = parseCondition(probe, where.exec(line.content)![1].trim(), locationOf(line), true);\n if (condition !== null) validateCondition(probe, condition);\n const message = \"Opaque 'where' on click, double click and select is deprecated; use block-form 'when' item conditions\";\n if (condition !== null && probe.diagnostics.length === 0) context.warning(DiagnosticCodes.LegacyInteractionWhere, message, locationOf(line));\n else context.information(DiagnosticCodes.LegacyInteractionWhere, message, locationOf(line));\n}\n"],"mappings":"ueA0BA,MAAMA,EAAiBC,EAAQ,UAAUC,EAAiB,cAAcA,EAAiB,IAAI,EAG7F,SAAgB,oBAAoB,EAAmF,CACnH,IAAMC,kBAAS,IAAI,IACbC,EAA0B,CAAC,EAC7BC,EAAS,GACb,IAAK,IAAMC,KAAQC,EACf,GAAID,EAAK,QAAQ,WAAW,KAAK,EAC7B,EAAS,CAACD,OAGd,GAAI,KAAUC,EAAK,QAAQ,SAAW,GAAKA,EAAK,QAAQ,WAAW,IAAI,GACvE,MAAOF,EAAU,OAAS,GAAKA,EAAUA,EAAU,OAAS,EAAE,CAAC,QAAUE,EAAK,QAAQF,EAAU,IAAI,EAChGI,EAAUF,EAAK,OAAO,IAAM,MAAMH,EAAO,IAAIG,EAAK,OAAQF,EAAU,IAAI,IAAa,CAAE,QAASJ,EAAe,KAAKS,EAAS,OAAO,EAAI,kBAAoBD,EAAUC,EAAS,OAAO,EAAG,SAAUC,EAAWD,CAAQ,CAAE,EAAE,CAAC,EAC/NL,EAAU,KAAKE,CAAI,CAFiF,CAIxG,OAAOH,CACX,CAEA,MAAMQ,EAASV,EAAQ,QAAQC,EAAiB,YAAYA,EAAiB,UAAUA,EAAiB,8BAA8B,EAChIU,EAAUX,EAAQ,MAAMC,EAAiB,YAAY,EACrDW,EAAQZ,EAAQ,SAASC,EAAiB,YAAY,EACtDY,kBAAU,IAAI,IAAI,CAAC,UAAW,WAAY,OAAQ,QAAS,UAAW,MAAO,SAAU,UAAW,OAAO,CAAC,EAIhH,SAAgB,0BAA0B,EAAwB,EAAoC,CAClG,IAAK,IAAIC,EAAQ,EAAGA,EAAQR,EAAM,OAAQ,IAAS,CAC/C,IAAMS,EAAST,EAAMQ,GACfE,EAAKL,EAAQ,KAAKI,EAAO,OAAO,EACtC,GAAIC,IAAO,MAAQA,EAAG,EAAE,CAAC,WAAW,YAAY,EAAG,SACnD,IAAMC,EAAqB,CAAC,EAC5B,IAAK,IAAIC,EAAQJ,EAAQ,EAAGI,EAAQZ,EAAM,QAAUA,EAAMY,EAAM,CAAC,OAASH,EAAO,OAAQ,IAASE,EAAK,KAAKX,EAAMY,EAAM,EACxH,IAAMC,EAAWF,EAAK,OAAO,GAAQZ,EAAK,SAAWY,EAAK,EAAE,EAAE,MAAM,EAC9DG,EAAWD,EAAS,OAAO,GAAQ,CAAC,OAAQ,WAAW,CAAC,CAAC,SAASZ,EAAUF,EAAK,OAAO,CAAC,CAAC,EAC1FgB,EAAY,CAAC,QAAS,eAAgB,QAAQ,CAAC,CAAC,SAASL,EAAG,EAAE,CAAC,KAAK,CAAC,EACrEM,EAASH,EAAS,OAAO,GAAQP,EAAM,KAAKP,EAAK,OAAO,CAAC,EACzDkB,EAAuC,CAAC,EAC1CC,EAAe,GACnB,IAAK,IAAMC,KAAUL,EAAU,CAC3B,IAAMM,EAASnB,EAAUkB,EAAO,OAAO,IAAM,OACvCE,EAAQD,EAAShB,EAAO,KAAKe,EAAO,OAAO,EAAI,KACrD,GAAIC,EAAQ,CACJF,GAAcI,EAAQ,MAAMC,EAAgB,yBAA0B,gDAAiDpB,EAAWgB,CAAM,CAAC,EAC7I,IAAMK,EAAYC,EAAeH,EAASD,IAAQ,IAAMF,EAAO,QAAQ,MAAM,CAAC,CAAC,CAAC,KAAK,EAAGhB,EAAWgB,CAAM,EAAG,EAAI,EAC5GK,IAAc,OACdE,EAAkBJ,EAASE,CAAS,EACpCP,EAAa,KAAK,CAAE,YAAW,SAAUd,EAAWgB,CAAM,EAAG,QAAS,iFAAkF,CAAC,GAEzJE,IAAU,MAAMC,EAAQ,MAAMC,EAAgB,6BAA8B,qGAAsGpB,EAAWgB,CAAM,CAAC,CAC5M,MACQD,GAAgBC,EAAO,UAAY,cAAaG,EAAQ,MAAMC,EAAgB,yBAA0B,0DAA2DpB,EAAWgB,CAAM,CAAC,EACzL,EAAe,GAGnB,IAAMQ,EAAShB,EADEA,EAAK,QAAQQ,CACH,EAAI,GAC3BE,IAAU,OAASM,IAAW,IAAA,IAAaA,EAAO,QAAUR,EAAO,QAAU,CAACZ,EAAQ,IAAIN,EAAU0B,EAAO,OAAO,CAAC,IACnHL,EAAQ,MAAMC,EAAgB,qCAAsC,8DAA+DpB,EAAWgB,CAAM,CAAC,CAE7J,CAQA,GAPIL,EAAS,OAAS,IACbC,GAAWO,EAAQ,MAAMC,EAAgB,mCAAoC,gFAAiFpB,EAAWM,CAAM,CAAC,GACjLO,EAAO,OAAS,GAAKH,EAAS,KAAK,GAAQN,EAAQ,IAAIN,EAAUF,EAAK,OAAO,CAAC,CAAC,IAC/EuB,EAAQ,MAAMC,EAAgB,6BAA8B,oEAAqEpB,EAAWM,CAAM,CAAC,EAElJK,EAAS,KAAK,GAAQb,EAAUF,EAAK,OAAO,IAAM,MAAM,GAAGuB,EAAQ,MAAMC,EAAgB,iCAAkC,iEAAkEpB,EAAWM,CAAM,CAAC,GAEpNM,EAAW,IAAK,IAAMa,KAASZ,EAAQ,eAAeM,EAASM,CAAK,EACpEX,EAAa,OAAS,GAAGK,EAAQ,oBAAoB,KAAK,CAAE,SAAUnB,EAAWM,CAAM,EAAG,UAAWa,EAAQ,qBAAqB,IAAIb,EAAO,MAAM,GAAK,CAAC,EAAG,cAAa,CAAC,CAClL,CACJ,CAEA,SAAS,eAAe,EAAwB,EAAwB,CACpE,IAAMoB,EAAQ,IAAIC,EAAc,IAAIC,EAAW,CAAC,CAAC,CAAC,EAClD,EAAM,cAAgBT,EAAQ,cAC9B,IAAME,EAAYC,EAAeI,EAAOvB,EAAM,KAAKP,EAAK,OAAO,CAAC,CAAE,EAAE,CAAC,KAAK,EAAGI,EAAWJ,CAAI,EAAG,EAAI,EAC/FyB,IAAc,MAAME,EAAkBG,EAAOL,CAAS,EAC1D,IAAMQ,EAAU,wGACZR,IAAc,MAAQK,EAAM,YAAY,SAAW,EAAGP,EAAQ,QAAQC,EAAgB,uBAAwBS,EAAS7B,EAAWJ,CAAI,CAAC,EACtIuB,EAAQ,YAAYC,EAAgB,uBAAwBS,EAAS7B,EAAWJ,CAAI,CAAC,CAC9F"}
|
|
1
|
+
{"version":3,"file":"InteractionAlternatives.js","names":["screenTemplate","pattern","dotNetWhitespace","result","ancestors","fenced","line","lines","firstWord","ancestor","locationOf","inline","trigger","where","actions","behavior","uses","behaviorArgument","declaration","context","index","header","attachment","interactionBody","match","on","body","child","children","branches","supported","guards","alternatives","otherwise","sawOtherwise","branch","isWhen","DiagnosticCodes","condition","parseCondition","validateCondition","executions","interactionExecutions","nested","guard","probe","ParserContext","LineReader","message"],"sources":["../../../../../../Compiler/Parsing/InteractionAlternatives.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticCodes } from '../Diagnostics/DiagnosticCodes';\nimport { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { GuardedInteractionAlternative } from './GuardedInteractionAlternative';\nimport { InteractionExecution } from './InteractionExecution';\nimport { interactionBody, interactionExecutions } from './InteractionExecutions';\nimport { dotNetWhitespace, pattern } from '../Text/patterns';\nimport { parseCondition } from './ConditionParser';\nimport { validateCondition } from './GuardedActionParser';\nimport { firstWord } from './LineText';\nimport { LineReader } from './LineReader';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Authoring facts only: interaction bodies are still opaque in the serialized TS AST.\nexport interface InteractionAncestor {\n readonly keyword: string;\n readonly location: SourceLocation;\n}\n\nexport interface GuardedInteractionBinding {\n readonly location: SourceLocation;\n readonly ancestors: readonly InteractionAncestor[];\n readonly alternatives: readonly GuardedInteractionAlternative[];\n readonly otherwise: readonly InteractionExecution[];\n}\n\nconst screenTemplate = pattern(`^screen${dotNetWhitespace}+template(?:${dotNetWhitespace}|$)`);\n\n// Capture attachment ancestry before parsing consumes opaque bodies. Fenced code is not Screenplay.\nexport function interactionAncestry(lines: readonly SourceLine[]): ReadonlyMap<number, readonly InteractionAncestor[]> {\n const result = new Map<number, readonly InteractionAncestor[]>();\n const ancestors: SourceLine[] = [];\n let fenced = false;\n for (const line of lines) {\n if (line.content.startsWith('```')) {\n fenced = !fenced;\n continue;\n }\n if (fenced || line.content.length === 0 || line.content.startsWith('//')) continue;\n while (ancestors.length > 0 && ancestors[ancestors.length - 1].indent >= line.indent) ancestors.pop();\n if (['on', 'uses'].includes(firstWord(line.content))) result.set(line.number, ancestors.map(ancestor => ({ keyword: screenTemplate.test(ancestor.content) ? 'screen template' : firstWord(ancestor.content), location: locationOf(ancestor) })));\n ancestors.push(line);\n }\n return result;\n}\n\nconst inline = pattern(`^when${dotNetWhitespace}+([^\\\\n]+)${dotNetWhitespace}+execute${dotNetWhitespace}+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$`);\nconst trigger = pattern(`^on${dotNetWhitespace}+([^\\\\n]+)$`);\nconst where = pattern(`^where${dotNetWhitespace}+([^\\\\n]+)$`);\nconst actions = new Set(['execute', 'navigate', 'open', 'close', 'refresh', 'set', 'notify', 'confirm', 'raise']);\nconst behavior = pattern(`^behavior${dotNetWhitespace}+([A-Za-z_]\\\\w*)$`);\nconst uses = pattern(`^uses${dotNetWhitespace}+([A-Za-z_]\\\\w*)$`);\nconst behaviorArgument = pattern(`^([A-Za-z_]\\\\w*)${dotNetWhitespace}+([^\\\\n]+)$`);\n\n// Interaction bodies remain opaque in the TS AST. Check their structure instead of silently accepting\n// alternatives the C# compiler refuses. Input collection supplies only significant, non-fenced lines.\nexport function validateInteractionBodies(context: ParserContext, lines: readonly SourceLine[]): void {\n const declaration = behavior.exec(lines[0]?.content ?? '');\n if (declaration !== null) context.interactionBehaviors.push({ name: declaration[1], location: locationOf(lines[0]) });\n for (let index = 0; index < lines.length; index++) {\n const header = lines[index];\n const attachment = uses.exec(header.content);\n if (attachment !== null) context.interactionUses.push({\n behavior: attachment[1], location: locationOf(header), ancestors: context.interactionAncestors.get(header.number) ?? [],\n arguments: interactionBody(lines, header).flatMap(line => {\n const match = behaviorArgument.exec(line.content);\n return match === null ? [] : [{ name: match[1], value: match[2].trim() }];\n }),\n });\n const on = trigger.exec(header.content);\n if (on === null || on[1].startsWith('row-click ')) continue;\n const body: SourceLine[] = [];\n for (let child = index + 1; child < lines.length && lines[child].indent > header.indent; child++) body.push(lines[child]);\n const children = body.filter(line => line.indent === body[0]?.indent);\n const branches = children.filter(line => ['when', 'otherwise'].includes(firstWord(line.content)));\n const supported = ['click', 'double click', 'select'].includes(on[1].trim());\n const guards = children.filter(line => where.test(line.content));\n const alternatives: GuardedInteractionAlternative[] = [];\n let otherwise: readonly InteractionExecution[] = [];\n let sawOtherwise = false;\n for (const branch of branches) {\n const isWhen = firstWord(branch.content) === 'when';\n const match = isWhen ? inline.exec(branch.content) : null;\n if (isWhen) {\n if (sawOtherwise) context.error(DiagnosticCodes.MisplacedActionOtherwise, \"A 'when' alternative must precede 'otherwise'\", locationOf(branch));\n const condition = parseCondition(context, match?.[1] ?? branch.content.slice(4).trim(), locationOf(branch), true);\n if (condition !== null) {\n validateCondition(context, condition);\n const executions = match === null ? interactionExecutions(interactionBody(body, branch))\n : interactionExecutions([{ ...branch, content: `execute ${match[2]}` }, ...interactionBody(body, branch)]);\n alternatives.push({ condition, executions, location: locationOf(branch), message: \"This 'when' alternative is shadowed by earlier alternatives in this interaction\" });\n }\n if (match !== null) context.error(DiagnosticCodes.InlineInteractionAlternative, \"Interaction alternatives require an indented action list, not 'when <condition> execute <Command>'\", locationOf(branch));\n } else {\n if (sawOtherwise || branch.content !== 'otherwise') context.error(DiagnosticCodes.MisplacedActionOtherwise, \"An interaction permits one final block-form 'otherwise'\", locationOf(branch));\n sawOtherwise = true;\n otherwise = interactionExecutions(interactionBody(body, branch));\n }\n const position = body.indexOf(branch);\n const nested = body[position + 1];\n if (match === null && (nested === undefined || nested.indent <= branch.indent || !actions.has(firstWord(nested.content)))) {\n context.error(DiagnosticCodes.InteractionAlternativeWithoutActions, 'An interaction alternative requires a non-empty action list', locationOf(branch));\n }\n }\n if (branches.length > 0) {\n if (!supported) context.error(DiagnosticCodes.UnsupportedInteractionAlternatives, 'Interaction alternatives are only supported on click, double click and select', locationOf(header));\n if (guards.length > 0 || children.some(line => actions.has(firstWord(line.content)))) {\n context.error(DiagnosticCodes.MixedInteractionAlternatives, \"Interaction alternatives cannot mix with plain actions or 'where'\", locationOf(header));\n }\n if (!branches.some(line => firstWord(line.content) === 'when')) context.error(DiagnosticCodes.GuardedActionWithoutAlternatives, \"A guarded interaction requires at least one 'when' alternative\", locationOf(header));\n }\n if (supported) for (const guard of guards) deprecateWhere(context, guard);\n if (alternatives.length > 0) context.guardedInteractions.push({ location: locationOf(header), ancestors: context.interactionAncestors.get(header.number) ?? [], alternatives, otherwise });\n }\n}\n\nfunction deprecateWhere(context: ParserContext, line: SourceLine): void {\n const probe = new ParserContext(new LineReader([]));\n probe.sourceOptions = context.sourceOptions;\n const condition = parseCondition(probe, where.exec(line.content)![1].trim(), locationOf(line), true);\n if (condition !== null) validateCondition(probe, condition);\n const message = \"Opaque 'where' on click, double click and select is deprecated; use block-form 'when' item conditions\";\n if (condition !== null && probe.diagnostics.length === 0) context.warning(DiagnosticCodes.LegacyInteractionWhere, message, locationOf(line));\n else context.information(DiagnosticCodes.LegacyInteractionWhere, message, locationOf(line));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{dotNetWhitespace as e,pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";import{firstWord as r}from"./LineText.js";const i=t(`^execute${e}+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),a=t(`^with${e}+([A-Za-z_]\\w*)${e}+from${e}+([^\\n]+)$`),o=RegExp(`^${e}+|${e}+$`,`gu`),s=t(`^on${e}+(success|failure|result)$`),c=/* @__PURE__ */ new Set([`execute`,`refresh`,`confirm`,`open`,`raise`]);function interactionBody(e,t){let n=e.indexOf(t)+1,r=n;for(;r<e.length&&e[r].indent>t.indent;)r++;return e.slice(n,r)}function interactionExecutions(e,l=1){if(l>16||e.length===0)return[];let u=[];for(let d of e.filter(t=>t.indent===e[0].indent)){let f=i.exec(d.content),p=r(d.content);if(f===null&&!c.has(p))continue;let m=interactionBody(e,d),h=m.filter(e=>e.indent===m[0]?.indent);if(f!==null){let e=h.flatMap(e=>{let t=a.exec(e.content);return t===null?[]:[{kind:`InteractionArgumentSyntax`,name:t[1],binding:t[2].replace(o,``),location:n(e)}]});u.push({command:f[1],arguments:e})}for(let e of[`success`,`failure`,`result`])if(e!==`result`||t(`^open[\\u0009-\\u000d\\u0020\\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]+dialog[\\u0009-\\u000d\\u0020\\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]+`).test(d.content))for(let t of h.filter(t=>s.exec(t.content)?.[1]===e))u.push(...interactionExecutions(interactionBody(m,t),l+1))}return u}export{interactionBody,interactionExecutions};
|
|
2
|
+
//# sourceMappingURL=InteractionExecutions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InteractionExecutions.js","names":["execute","pattern","dotNetWhitespace","argument","trim","continuation","failable","start","lines","header","end","depth","result","line","command","keyword","firstWord","body","children","arguments_","match","locationOf","outcome","child"],"sources":["../../../../../../Compiler/Parsing/InteractionExecutions.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { InteractionArgumentSyntax } from '../Syntax/Screens';\nimport { dotNetWhitespace, pattern } from '../Text/patterns';\nimport { InteractionExecution } from './InteractionExecution';\nimport { firstWord } from './LineText';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst execute = pattern(`^execute${dotNetWhitespace}+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$`);\nconst argument = pattern(`^with${dotNetWhitespace}+([A-Za-z_]\\\\w*)${dotNetWhitespace}+from${dotNetWhitespace}+([^\\\\n]+)$`);\nconst trim = new RegExp(`^${dotNetWhitespace}+|${dotNetWhitespace}+$`, 'gu');\nconst continuation = pattern(`^on${dotNetWhitespace}+(success|failure|result)$`);\nconst failable = new Set(['execute', 'refresh', 'confirm', 'open', 'raise']);\n\nexport function interactionBody(lines: readonly SourceLine[], header: SourceLine): readonly SourceLine[] {\n const start = lines.indexOf(header) + 1;\n let end = start;\n while (end < lines.length && lines[end].indent > header.indent) end++;\n return lines.slice(start, end);\n}\n\n// Preserve action, success, failure, result order even when continuations are authored out of order.\nexport function interactionExecutions(lines: readonly SourceLine[], depth = 1): readonly InteractionExecution[] {\n if (depth > 16 || lines.length === 0) return [];\n const result: InteractionExecution[] = [];\n for (const header of lines.filter(line => line.indent === lines[0].indent)) {\n const command = execute.exec(header.content);\n const keyword = firstWord(header.content);\n if (command === null && !failable.has(keyword)) continue;\n const body = interactionBody(lines, header);\n const children = body.filter(line => line.indent === body[0]?.indent);\n if (command !== null) {\n const arguments_: InteractionArgumentSyntax[] = children.flatMap(line => {\n const match = argument.exec(line.content);\n return match === null ? [] : [{ kind: 'InteractionArgumentSyntax', name: match[1], binding: match[2].replace(trim, ''), location: locationOf(line) }];\n });\n result.push({ command: command[1], arguments: arguments_ });\n }\n for (const outcome of ['success', 'failure', 'result']) {\n if (outcome === 'result' && !pattern(`^open${dotNetWhitespace}+dialog${dotNetWhitespace}+`).test(header.content)) continue;\n for (const child of children.filter(line => continuation.exec(line.content)?.[1] === outcome)) {\n result.push(...interactionExecutions(interactionBody(body, child), depth + 1));\n }\n }\n }\n return result;\n}\n"],"mappings":"gNASA,MAAMA,EAAUC,EAAQ,WAAWC,EAAiB,8BAA8B,EAC5EC,EAAWF,EAAQ,QAAQC,EAAiB,kBAAkBA,EAAiB,OAAOA,EAAiB,YAAY,EACnHE,EAAW,OAAO,IAAIF,EAAiB,IAAIA,EAAiB,IAAK,IAAI,EACrEG,EAAeJ,EAAQ,MAAMC,EAAiB,2BAA2B,EACzEI,kBAAW,IAAI,IAAI,CAAC,UAAW,UAAW,UAAW,OAAQ,OAAO,CAAC,EAE3E,SAAgB,gBAAgB,EAA8B,EAA2C,CACrG,IAAMC,EAAQC,EAAM,QAAQC,CAAM,EAAI,EAClCC,EAAMH,EACV,KAAOG,EAAMF,EAAM,QAAUA,EAAME,EAAI,CAAC,OAASD,EAAO,QAAQ,IAChE,OAAOD,EAAM,MAAMD,EAAOG,CAAG,CACjC,CAGA,SAAgB,sBAAsB,EAA8B,EAAQ,EAAoC,CAC5G,GAAIC,EAAQ,IAAMH,EAAM,SAAW,EAAG,MAAO,CAAC,EAC9C,IAAMI,EAAiC,CAAC,EACxC,IAAK,IAAMH,KAAUD,EAAM,OAAO,GAAQK,EAAK,SAAWL,EAAM,EAAE,CAAC,MAAM,EAAG,CACxE,IAAMM,EAAUd,EAAQ,KAAKS,EAAO,OAAO,EACrCM,EAAUC,EAAUP,EAAO,OAAO,EACxC,GAAIK,IAAY,MAAQ,CAACR,EAAS,IAAIS,CAAO,EAAG,SAChD,IAAME,EAAO,gBAAgBT,EAAOC,CAAM,EACpCS,EAAWD,EAAK,OAAO,GAAQJ,EAAK,SAAWI,EAAK,EAAE,EAAE,MAAM,EACpE,GAAIH,IAAY,KAAM,CAClB,IAAMK,EAA0CD,EAAS,QAAQ,GAAQ,CACrE,IAAME,EAAQjB,EAAS,KAAKU,EAAK,OAAO,EACxC,OAAOO,IAAU,KAAO,CAAC,EAAI,CAAC,CAAE,KAAM,4BAA6B,KAAMA,EAAM,GAAI,QAASA,EAAM,EAAE,CAAC,QAAQhB,EAAM,EAAE,EAAG,SAAUiB,EAAWR,CAAI,CAAE,CAAC,CACxJ,CAAC,EACDD,EAAO,KAAK,CAAE,QAASE,EAAQ,GAAI,UAAWK,CAAW,CAAC,CAC9D,CACA,IAAK,IAAMG,IAAW,CAAC,UAAW,UAAW,QAAQ,EACjD,GAAIA,IAAY,UAAarB,EAAQ,6MAAqD,CAAC,CAAC,KAAKQ,EAAO,OAAO,EAC/G,IAAK,IAAMc,KAASL,EAAS,OAAO,GAAQb,EAAa,KAAKQ,EAAK,OAAO,CAAC,GAAG,KAAOS,CAAO,EACxFV,EAAO,KAAK,GAAG,sBAAsB,gBAAgBK,EAAMM,CAAK,EAAGZ,EAAQ,CAAC,CAAC,CAGzF,CACA,OAAOC,CACX"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{sourceLocation as e}from"../Diagnostics/SourceLocation.js";import{legacySourceOptions as t}from"../Syntax/SourceOptions.js";var n=class ParserContext{reader;path;#e=[];triggerData=[];inputUses=[];continuationValues=[];guardedInteractions=[];interactionAncestors=/* @__PURE__ */ new Map;scope=[];languages;sourceOptions=t;authoredDeclarations=!1;deferIdentityValidation=!1;streamCandidates;get valueContext(){if(this.sourceOptions.numericMode===`exact`)return this;let e=new ParserContext(this.reader,this.path,this.languages);return e.sourceOptions=this.sourceOptions,e}constructor(e,t,n=/* @__PURE__ */ new Set([`csharp`,`typescript`,`react`,`html`,`sql`])){this.reader=e,this.path=t,this.languages=n}get start(){return e(1,1,this.path)}get diagnostics(){return this.nestedNumericDirectives.size>0&&this.sourceOptions.numericMode!==`legacy`&&this.reader.atEnd&&(this.#e.push(...[...this.nestedNumericDirectives].sort((e,t)=>e[0]-t[0]).map(e=>e[1])),this.nestedNumericDirectives.clear()),this.#e}nestedNumericDirectives=/* @__PURE__ */ new Map;claimField(e){this.nestedNumericDirectives.delete(e.number)}information(e,t,n,r={}){this.#e.push({severity:`information`,code:e,message:t,location:n,arguments:r})}error(e,t,n,r={}){this.#e.push({severity:`error`,code:e,message:t,location:n,arguments:r})}warning(e,t,n,r={}){this.#e.push({severity:`warning`,code:e,message:t,location:n,arguments:r})}peekChild(e){let t=this.reader.peekSignificant();return t!==void 0&&t.indent>e?t:void 0}skipBlock(e){for(;this.peekChild(e)!==void 0;)this.reader.takeSignificant()}skipOpaqueBlock(e){let t=this.peekChild(e);for(;t!==void 0;)this.reader.takeSignificant(),t.content.startsWith("```")&&this.skipFencedBody(),t=this.peekChild(e)}skipFencedBody(){for(let e=this.reader.takeRaw();e!==void 0;e=this.reader.takeRaw())if(e.raw.trim()==="```")return}};export{n as ParserContext};
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{sourceLocation as e}from"../Diagnostics/SourceLocation.js";import{legacySourceOptions as t}from"../Syntax/SourceOptions.js";var n=class ParserContext{reader;path;#e=[];triggerData=[];inputUses=[];continuationValues=[];guardedInteractions=[];interactionBehaviors=[];interactionUses=[];interactionAncestors=/* @__PURE__ */ new Map;scope=[];languages;sourceOptions=t;authoredDeclarations=!1;deferIdentityValidation=!1;streamCandidates;get valueContext(){if(this.sourceOptions.numericMode===`exact`)return this;let e=new ParserContext(this.reader,this.path,this.languages);return e.sourceOptions=this.sourceOptions,e}constructor(e,t,n=/* @__PURE__ */ new Set([`csharp`,`typescript`,`react`,`html`,`sql`])){this.reader=e,this.path=t,this.languages=n}get start(){return e(1,1,this.path)}get diagnostics(){return this.nestedNumericDirectives.size>0&&this.sourceOptions.numericMode!==`legacy`&&this.reader.atEnd&&(this.#e.push(...[...this.nestedNumericDirectives].sort((e,t)=>e[0]-t[0]).map(e=>e[1])),this.nestedNumericDirectives.clear()),this.#e}nestedNumericDirectives=/* @__PURE__ */ new Map;claimField(e){this.nestedNumericDirectives.delete(e.number)}information(e,t,n,r={}){this.#e.push({severity:`information`,code:e,message:t,location:n,arguments:r})}error(e,t,n,r={}){this.#e.push({severity:`error`,code:e,message:t,location:n,arguments:r})}warning(e,t,n,r={}){this.#e.push({severity:`warning`,code:e,message:t,location:n,arguments:r})}peekChild(e){let t=this.reader.peekSignificant();return t!==void 0&&t.indent>e?t:void 0}skipBlock(e){for(;this.peekChild(e)!==void 0;)this.reader.takeSignificant()}skipOpaqueBlock(e){let t=this.peekChild(e);for(;t!==void 0;)this.reader.takeSignificant(),t.content.startsWith("```")&&this.skipFencedBody(),t=this.peekChild(e)}skipFencedBody(){for(let e=this.reader.takeRaw();e!==void 0;e=this.reader.takeRaw())if(e.raw.trim()==="```")return}};export{n as ParserContext};
|
|
2
2
|
//# sourceMappingURL=ParserContext.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ParserContext.js","names":["ParserContext","legacySourceOptions","context","reader","path","languages","sourceLocation","#diagnostics","first","second","entry","line","arguments_","parentIndent","child"],"sources":["../../../../../../Compiler/Parsing/ParserContext.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticArgument } from '../Diagnostics/DiagnosticArgument';\nimport { Diagnostic } from '../Diagnostics/Diagnostic';\nimport { CommandStreamCandidates } from './CommandStreamCandidates';\nimport { SourceLocation, sourceLocation } from '../Diagnostics/SourceLocation';\nimport { PropertySyntax } from '../Syntax/Declarations';\nimport { legacySourceOptions, SourceOptions } from '../Syntax/SourceOptions';\nimport { InputUse } from './InputUses';\nimport { ContinuationValueUse } from './ContinuationValueUse';\nimport { GuardedInteractionBinding, InteractionAncestor } from './InteractionAlternatives';\nimport { LineReader } from './LineReader';\nimport { SourceLine } from './SourceLine';\n\n// What every parser shares while it reads one document: the line reader, the diagnostics found so far and\n// the file the document came from.\nexport class ParserContext {\n readonly #diagnostics: Diagnostic[] = [];\n // Authoring verification needs these committed values even though SyntaxJson omits them.\n readonly triggerData: PropertySyntax[] = [];\n readonly inputUses: InputUse[] = [];\n readonly continuationValues: ContinuationValueUse[] = [];\n readonly guardedInteractions: GuardedInteractionBinding[] = [];\n interactionAncestors: ReadonlyMap<number, readonly InteractionAncestor[]> = new Map();\n scope: readonly string[] = [];\n readonly languages: ReadonlySet<string>;\n sourceOptions: SourceOptions = legacySourceOptions;\n authoredDeclarations = false;\n deferIdentityValidation = false;\n streamCandidates?: CommandStreamCandidates;\n\n // Structural enrichment of formerly opaque Legacy fields must not add diagnostics. Exact operands\n // use the owning context so representability failures cannot turn into successful opaque syntax.\n get valueContext(): ParserContext {\n if (this.sourceOptions.numericMode === 'exact') return this;\n const context = new ParserContext(this.reader, this.path, this.languages);\n context.sourceOptions = this.sourceOptions;\n return context;\n }\n\n constructor(readonly reader: LineReader, readonly path?: string, languages: ReadonlySet<string> = new Set(['csharp', 'typescript', 'react', 'html', 'sql'])) {\n this.languages = languages;\n }\n\n get start(): SourceLocation {\n return sourceLocation(1, 1, this.path);\n }\n\n get diagnostics(): readonly Diagnostic[] {\n // Directive-shaped lines nobody claimed as a field are errors, wherever they sit.\n if (this.nestedNumericDirectives.size > 0 && this.sourceOptions.numericMode !== 'legacy' && this.reader.atEnd) {\n this.#diagnostics.push(...[...this.nestedNumericDirectives].sort((first, second) => first[0] - second[0]).map(entry => entry[1]));\n this.nestedNumericDirectives.clear();\n }\n return this.#diagnostics;\n }\n\n // Directive-shaped lines below the top level, keyed by line number, still unclaimed as a field.\n nestedNumericDirectives = new Map<number, Diagnostic>();\n\n claimField(line: SourceLine): void {\n this.nestedNumericDirectives.delete(line.number);\n }\n\n information(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'information', code, message, location, arguments: arguments_ });\n }\n\n error(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'error', code, message, location, arguments: arguments_ });\n }\n\n warning(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'warning', code, message, location, arguments: arguments_ });\n }\n\n // The next significant line when it is indented deeper than its parent - that is, when it belongs to\n // the parent's body under the offside rule.\n peekChild(parentIndent: number): SourceLine | undefined {\n const line = this.reader.peekSignificant();\n return line !== undefined && line.indent > parentIndent ? line : undefined;\n }\n\n // Skips the body of a construct, the way the C# parser does after reporting it.\n skipBlock(parentIndent: number): void {\n while (this.peekChild(parentIndent) !== undefined) {\n this.reader.takeSignificant();\n }\n }\n\n // Skips the body of a construct this compiler deliberately does not model. Unlike skipBlock it steps\n // over fenced code blocks whole, because a fenced line may be indented less than the block it is in -\n // reading it as significant would end the skip early and misread the code as Screenplay.\n skipOpaqueBlock(parentIndent: number): void {\n let child = this.peekChild(parentIndent);\n while (child !== undefined) {\n this.reader.takeSignificant();\n if (child.content.startsWith('```')) {\n this.skipFencedBody();\n }\n child = this.peekChild(parentIndent);\n }\n }\n\n // Takes the raw lines of a fenced block up to and including its closing fence.\n skipFencedBody(): void {\n for (let line = this.reader.takeRaw(); line !== undefined; line = this.reader.takeRaw()) {\n if (line.raw.trim() === '```') {\n return;\n }\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"ParserContext.js","names":["ParserContext","legacySourceOptions","context","reader","path","languages","sourceLocation","#diagnostics","first","second","entry","line","arguments_","parentIndent","child"],"sources":["../../../../../../Compiler/Parsing/ParserContext.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { DiagnosticArgument } from '../Diagnostics/DiagnosticArgument';\nimport { Diagnostic } from '../Diagnostics/Diagnostic';\nimport { CommandStreamCandidates } from './CommandStreamCandidates';\nimport { SourceLocation, sourceLocation } from '../Diagnostics/SourceLocation';\nimport { PropertySyntax } from '../Syntax/Declarations';\nimport { legacySourceOptions, SourceOptions } from '../Syntax/SourceOptions';\nimport { InputUse } from './InputUses';\nimport { ContinuationValueUse } from './ContinuationValueUse';\nimport { GuardedInteractionBinding, InteractionAncestor } from './InteractionAlternatives';\nimport { InteractionBehavior } from './InteractionBehavior';\nimport { InteractionUse } from './InteractionUse';\nimport { LineReader } from './LineReader';\nimport { SourceLine } from './SourceLine';\n\n// What every parser shares while it reads one document: the line reader, the diagnostics found so far and\n// the file the document came from.\nexport class ParserContext {\n readonly #diagnostics: Diagnostic[] = [];\n // Authoring verification needs these committed values even though SyntaxJson omits them.\n readonly triggerData: PropertySyntax[] = [];\n readonly inputUses: InputUse[] = [];\n readonly continuationValues: ContinuationValueUse[] = [];\n readonly guardedInteractions: GuardedInteractionBinding[] = [];\n readonly interactionBehaviors: InteractionBehavior[] = [];\n readonly interactionUses: InteractionUse[] = [];\n interactionAncestors: ReadonlyMap<number, readonly InteractionAncestor[]> = new Map();\n scope: readonly string[] = [];\n readonly languages: ReadonlySet<string>;\n sourceOptions: SourceOptions = legacySourceOptions;\n authoredDeclarations = false;\n deferIdentityValidation = false;\n streamCandidates?: CommandStreamCandidates;\n\n // Structural enrichment of formerly opaque Legacy fields must not add diagnostics. Exact operands\n // use the owning context so representability failures cannot turn into successful opaque syntax.\n get valueContext(): ParserContext {\n if (this.sourceOptions.numericMode === 'exact') return this;\n const context = new ParserContext(this.reader, this.path, this.languages);\n context.sourceOptions = this.sourceOptions;\n return context;\n }\n\n constructor(readonly reader: LineReader, readonly path?: string, languages: ReadonlySet<string> = new Set(['csharp', 'typescript', 'react', 'html', 'sql'])) {\n this.languages = languages;\n }\n\n get start(): SourceLocation {\n return sourceLocation(1, 1, this.path);\n }\n\n get diagnostics(): readonly Diagnostic[] {\n // Directive-shaped lines nobody claimed as a field are errors, wherever they sit.\n if (this.nestedNumericDirectives.size > 0 && this.sourceOptions.numericMode !== 'legacy' && this.reader.atEnd) {\n this.#diagnostics.push(...[...this.nestedNumericDirectives].sort((first, second) => first[0] - second[0]).map(entry => entry[1]));\n this.nestedNumericDirectives.clear();\n }\n return this.#diagnostics;\n }\n\n // Directive-shaped lines below the top level, keyed by line number, still unclaimed as a field.\n nestedNumericDirectives = new Map<number, Diagnostic>();\n\n claimField(line: SourceLine): void {\n this.nestedNumericDirectives.delete(line.number);\n }\n\n information(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'information', code, message, location, arguments: arguments_ });\n }\n\n error(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'error', code, message, location, arguments: arguments_ });\n }\n\n warning(code: string, message: string, location: SourceLocation, arguments_: Readonly<Record<string, DiagnosticArgument>> = {}): void {\n this.#diagnostics.push({ severity: 'warning', code, message, location, arguments: arguments_ });\n }\n\n // The next significant line when it is indented deeper than its parent - that is, when it belongs to\n // the parent's body under the offside rule.\n peekChild(parentIndent: number): SourceLine | undefined {\n const line = this.reader.peekSignificant();\n return line !== undefined && line.indent > parentIndent ? line : undefined;\n }\n\n // Skips the body of a construct, the way the C# parser does after reporting it.\n skipBlock(parentIndent: number): void {\n while (this.peekChild(parentIndent) !== undefined) {\n this.reader.takeSignificant();\n }\n }\n\n // Skips the body of a construct this compiler deliberately does not model. Unlike skipBlock it steps\n // over fenced code blocks whole, because a fenced line may be indented less than the block it is in -\n // reading it as significant would end the skip early and misread the code as Screenplay.\n skipOpaqueBlock(parentIndent: number): void {\n let child = this.peekChild(parentIndent);\n while (child !== undefined) {\n this.reader.takeSignificant();\n if (child.content.startsWith('```')) {\n this.skipFencedBody();\n }\n child = this.peekChild(parentIndent);\n }\n }\n\n // Takes the raw lines of a fenced block up to and including its closing fence.\n skipFencedBody(): void {\n for (let line = this.reader.takeRaw(); line !== undefined; line = this.reader.takeRaw()) {\n if (line.raw.trim() === '```') {\n return;\n }\n }\n }\n}\n"],"mappings":"wLAmBA,IAAaA,EAAb,MAAa,aAAc,CA0BF,OAA6B,KAzBlD,GAAsC,CAAC,EAEvC,YAAyC,CAAC,EAC1C,UAAiC,CAAC,EAClC,mBAAsD,CAAC,EACvD,oBAA4D,CAAC,EAC7D,qBAAuD,CAAC,EACxD,gBAA6C,CAAC,EAC9C,qCAA4E,IAAI,IAChF,MAA2B,CAAC,EAC5B,UACA,cAA+BC,EAC/B,qBAAuB,GACvB,wBAA0B,GAC1B,iBAIA,IAAI,cAA8B,CAC9B,GAAI,KAAK,cAAc,cAAgB,QAAS,OAAO,KACvD,IAAMC,EAAU,IAAI,cAAc,KAAK,OAAQ,KAAK,KAAM,KAAK,SAAS,EAExE,MADA,GAAQ,cAAgB,KAAK,cACtBA,CACX,CAEA,YAAY,EAA6B,EAAwB,kBAAiC,IAAI,IAAI,CAAC,SAAU,aAAc,QAAS,OAAQ,KAAK,CAAC,EAAG,CAAxI,KAAA,OAAAC,EAA6B,KAAA,KAAAC,EAC9C,KAAK,UAAYC,CACrB,CAEA,IAAI,OAAwB,CACxB,OAAOC,EAAe,EAAG,EAAG,KAAK,IAAI,CACzC,CAEA,IAAI,aAAqC,CAMrC,OAJI,KAAK,wBAAwB,KAAO,GAAK,KAAK,cAAc,cAAgB,UAAY,KAAK,OAAO,QACpG,KAAKC,GAAa,KAAK,GAAG,CAAC,GAAG,KAAK,uBAAuB,CAAC,CAAC,MAAM,EAAO,IAAWC,EAAM,GAAKC,EAAO,EAAE,CAAC,CAAC,IAAI,GAASC,EAAM,EAAE,CAAC,EAChI,KAAK,wBAAwB,MAAM,GAEhC,KAAKH,EAChB,CAGA,wCAA0B,IAAI,IAE9B,WAAW,EAAwB,CAC/B,KAAK,wBAAwB,OAAOI,EAAK,MAAM,CACnD,CAEA,YAAY,EAAc,EAAiB,EAA0B,EAA2D,CAAC,EAAS,CACtI,KAAKJ,GAAa,KAAK,CAAE,SAAU,cAAe,OAAM,UAAS,WAAU,UAAWK,CAAW,CAAC,CACtG,CAEA,MAAM,EAAc,EAAiB,EAA0B,EAA2D,CAAC,EAAS,CAChI,KAAKL,GAAa,KAAK,CAAE,SAAU,QAAS,OAAM,UAAS,WAAU,UAAWK,CAAW,CAAC,CAChG,CAEA,QAAQ,EAAc,EAAiB,EAA0B,EAA2D,CAAC,EAAS,CAClI,KAAKL,GAAa,KAAK,CAAE,SAAU,UAAW,OAAM,UAAS,WAAU,UAAWK,CAAW,CAAC,CAClG,CAIA,UAAU,EAA8C,CACpD,IAAMD,EAAO,KAAK,OAAO,gBAAgB,EACzC,OAAOA,IAAS,IAAA,IAAaA,EAAK,OAASE,EAAeF,EAAO,IAAA,EACrE,CAGA,UAAU,EAA4B,CAClC,KAAO,KAAK,UAAUE,CAAY,IAAM,IAAA,IACpC,KAAK,OAAO,gBAAgB,CAEpC,CAKA,gBAAgB,EAA4B,CACxC,IAAIC,EAAQ,KAAK,UAAUD,CAAY,EACvC,KAAOC,IAAU,IAAA,IACb,KAAK,OAAO,gBAAgB,EACxBA,EAAM,QAAQ,WAAW,KAAK,GAC9B,KAAK,eAAe,EAExB,EAAQ,KAAK,UAAUD,CAAY,CAE3C,CAGA,gBAAuB,CACnB,IAAK,IAAIF,EAAO,KAAK,OAAO,QAAQ,EAAGA,IAAS,IAAA,GAAW,EAAO,KAAK,OAAO,QAAQ,EAClF,GAAIA,EAAK,IAAI,KAAK,IAAM,MACpB,MAGZ,CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RefusalDeclarations.js","names":["primitives","application","AuthoringProductionResolver","uniqueByName","type","concept","latest","event","eventDeclarations","slice","entries","select","scope","entry","from","parts","reference","named","qualifiers","index","part","depth","visible","matches","name","imports","imported","path","properties","property","source","target"],"sources":["../../../../../../Compiler/Parsing/RefusalDeclarations.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { PropertySyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { eventDeclarations } from '../Syntax/EventDeclarations';\nimport { ApplicationSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { uniqueByName } from './ResponseValidator';\n\nconst primitives = new Set(['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime']);\n\n// The scoped declaration facts used by the C# refusal and redelivery consistency validators.\nexport class RefusalDeclarations {\n readonly slices: AuthoringProductionResolver['slices'];\n readonly types;\n readonly concepts;\n private readonly events;\n private readonly knownTypes: Set<string>;\n\n constructor(readonly application: ApplicationSyntax) {\n this.slices = new AuthoringProductionResolver(application).slices;\n this.types = uniqueByName(application.types);\n this.concepts = uniqueByName(application.concepts);\n this.knownTypes = new Set([...primitives, ...application.types.map(type => type.name), ...application.concepts.map(concept => concept.name)]);\n this.events = new Map(this.slices.map(({ slice }) => {\n const latest = new Map<string, ReturnType<typeof eventDeclarations>[number]>();\n for (const event of eventDeclarations(slice)) {\n if (!latest.has(event.name) || latest.get(event.name)!.generation < event.generation) latest.set(event.name, event);\n }\n return [slice, [...latest.values()]];\n }));\n }\n\n resolve<T extends { readonly name: string }>(name: string, from: SliceSyntax, select: (slice: SliceSyntax) => readonly T[]): { node: T; slice: SliceSyntax } | null {\n const entries = this.slices.flatMap(({ slice, scope }) => select(slice).map(node => ({ node, slice, scope })));\n const scope = this.slices.find(entry => entry.slice === from)?.scope ?? [];\n const candidates = (reference: string) => {\n const parts = reference.split('.');\n const named = entries.filter(entry => entry.node.name === parts.at(-1));\n const qualifiers = parts.slice(0, -1);\n if (qualifiers.length > 0) return named.filter(entry => qualifiers.length <= entry.scope.length && qualifiers.every((part, index) => entry.scope[entry.scope.length - qualifiers.length + index] === part));\n for (let depth = scope.length; depth >= 0; depth--) {\n const visible = named.filter(entry => depth <= entry.scope.length && scope.slice(0, depth).every((part, index) => entry.scope[index] === part));\n if (visible.length > 0) return visible;\n }\n return [];\n };\n let matches = candidates(name);\n if (matches.length === 0) {\n const imports = this.application.imports.filter(imported => imported.qualifiedName.split('.').at(-1) === name);\n if (imports.length === 1) matches = candidates(imports[0].qualifiedName);\n }\n return matches.length === 1 ? matches[0] : null;\n }\n\n event(name: string, from: SliceSyntax) {\n return this.resolve(name, from, slice => this.events.get(slice) ?? [])?.node ?? null;\n }\n\n property(properties: readonly PropertySyntax[] | null, path: string): PropertySyntax | null {\n const parts = path.split('.');\n for (const [index, part] of parts.entries()) {\n const matches: readonly PropertySyntax[] = properties?.filter(property => property.name === part) ?? [];\n if (matches.length !== 1) return null;\n const property = matches[0];\n if (index === parts.length - 1) return property;\n if (primitives.has(property.type.name) || this.concepts.has(property.type.name) && !this.application.types.some(type => type.name === property.type.name)) return null;\n properties = this.types.get(property.type.name)?.properties ?? null;\n }\n return null;\n }\n\n compatible(source: TypeRefSyntax, target: TypeRefSyntax): boolean | null {\n return this.knownTypes.has(source.name) && this.knownTypes.has(target.name)\n ? source.name === target.name && source.isCollection === target.isCollection && (!source.isOptional || target.isOptional) : null;\n }\n}\n"],"mappings":"qQASA,MAAMA,kBAAa,IAAI,IAAI,CAAC,SAAU,OAAQ,MAAO,UAAW,OAAQ,OAAQ,UAAU,CAAC,EAG3F,IAAa,oBAAb,KAAiC,CAOR,YANrB,OACA,MACA,SACA,OACA,WAEA,YAAY,EAAyC,CAAhC,KAAA,YAAAC,EACjB,KAAK,OAAS,IAAIC,EAA4BD,CAAW,CAAC,CAAC,OAC3D,KAAK,MAAQE,EAAaF,EAAY,KAAK,EAC3C,KAAK,SAAWE,EAAaF,EAAY,QAAQ,EACjD,KAAK,2BAAa,IAAI,IAAI,CAAC,GAAGD,EAAY,GAAGC,EAAY,MAAM,IAAI,GAAQG,EAAK,IAAI,EAAG,GAAGH,EAAY,SAAS,IAAI,GAAWI,EAAQ,IAAI,CAAC,CAAC,EAC5I,KAAK,OAAS,IAAI,IAAI,KAAK,OAAO,KAAK,CAAE,WAAY,CACjD,IAAMC,kBAAS,IAAI,IACnB,IAAK,IAAMC,KAASC,EAAkBC,CAAK,GACnC,CAACH,EAAO,IAAIC,EAAM,IAAI,GAAKD,EAAO,IAAIC,EAAM,IAAI,CAAC,CAAE,WAAaA,EAAM,aAAYD,EAAO,IAAIC,EAAM,KAAMA,CAAK,EAEtH,MAAO,CAACE,EAAO,CAAC,GAAGH,EAAO,OAAO,CAAC,CAAC,CACvC,CAAC,CAAC,CACN,CAEA,QAA6C,EAAc,
|
|
1
|
+
{"version":3,"file":"RefusalDeclarations.js","names":["primitives","application","AuthoringProductionResolver","uniqueByName","type","concept","latest","event","eventDeclarations","slice","entries","select","scope","entry","from","parts","reference","named","qualifiers","index","part","depth","visible","matches","name","imports","imported","path","properties","property","source","target"],"sources":["../../../../../../Compiler/Parsing/RefusalDeclarations.ts"],"sourcesContent":["// Copyright (c) Cratis. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project root for full license information.\n\nimport { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { PropertySyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { eventDeclarations } from '../Syntax/EventDeclarations';\nimport { ApplicationSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { uniqueByName } from './ResponseValidator';\n\nconst primitives = new Set(['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime']);\n\n// The scoped declaration facts used by the C# refusal and redelivery consistency validators.\nexport class RefusalDeclarations {\n readonly slices: AuthoringProductionResolver['slices'];\n readonly types;\n readonly concepts;\n private readonly events;\n private readonly knownTypes: Set<string>;\n\n constructor(readonly application: ApplicationSyntax) {\n this.slices = new AuthoringProductionResolver(application).slices;\n this.types = uniqueByName(application.types);\n this.concepts = uniqueByName(application.concepts);\n this.knownTypes = new Set([...primitives, ...application.types.map(type => type.name), ...application.concepts.map(concept => concept.name)]);\n this.events = new Map(this.slices.map(({ slice }) => {\n const latest = new Map<string, ReturnType<typeof eventDeclarations>[number]>();\n for (const event of eventDeclarations(slice)) {\n if (!latest.has(event.name) || latest.get(event.name)!.generation < event.generation) latest.set(event.name, event);\n }\n return [slice, [...latest.values()]];\n }));\n }\n\n resolve<T extends { readonly name: string }>(name: string, from: SliceSyntax | undefined, select: (slice: SliceSyntax) => readonly T[]): { node: T; slice: SliceSyntax } | null {\n const entries = this.slices.flatMap(({ slice, scope }) => select(slice).map(node => ({ node, slice, scope })));\n const scope = this.slices.find(entry => entry.slice === from)?.scope ?? [];\n const candidates = (reference: string) => {\n const parts = reference.split('.');\n const named = entries.filter(entry => entry.node.name === parts.at(-1));\n const qualifiers = parts.slice(0, -1);\n if (qualifiers.length > 0) return named.filter(entry => qualifiers.length <= entry.scope.length && qualifiers.every((part, index) => entry.scope[entry.scope.length - qualifiers.length + index] === part));\n for (let depth = scope.length; depth >= 0; depth--) {\n const visible = named.filter(entry => depth <= entry.scope.length && scope.slice(0, depth).every((part, index) => entry.scope[index] === part));\n if (visible.length > 0) return visible;\n }\n return [];\n };\n let matches = candidates(name);\n if (matches.length === 0) {\n const imports = this.application.imports.filter(imported => imported.qualifiedName.split('.').at(-1) === name);\n if (imports.length === 1) matches = candidates(imports[0].qualifiedName);\n }\n return matches.length === 1 ? matches[0] : null;\n }\n\n event(name: string, from: SliceSyntax) {\n return this.resolve(name, from, slice => this.events.get(slice) ?? [])?.node ?? null;\n }\n\n property(properties: readonly PropertySyntax[] | null, path: string): PropertySyntax | null {\n const parts = path.split('.');\n for (const [index, part] of parts.entries()) {\n const matches: readonly PropertySyntax[] = properties?.filter(property => property.name === part) ?? [];\n if (matches.length !== 1) return null;\n const property = matches[0];\n if (index === parts.length - 1) return property;\n if (primitives.has(property.type.name) || this.concepts.has(property.type.name) && !this.application.types.some(type => type.name === property.type.name)) return null;\n properties = this.types.get(property.type.name)?.properties ?? null;\n }\n return null;\n }\n\n compatible(source: TypeRefSyntax, target: TypeRefSyntax): boolean | null {\n return this.knownTypes.has(source.name) && this.knownTypes.has(target.name)\n ? source.name === target.name && source.isCollection === target.isCollection && (!source.isOptional || target.isOptional) : null;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{stringBodyPattern as t,unescapeString as n}from"../Text/StringLiteral.js";import{pattern as r}from"../Text/patterns.js";import{locationOf as i}from"./SourceLine.js";import{parseMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseTypeRef as s}from"./PropertyLineParser.js";import{parseFencedText as c}from"./CodeBlockParser.js";import{parseDescription as l}from"./DescriptionParser.js";import{parseGuardedAction as u}from"./GuardedActionParser.js";import{collectInputUses as d}from"./InputUses.js";import{isFileDirective as f}from"./FileReferences.js";import{isValidTemplateVersionRange as p,parseBlueprintReference as m,startsBlueprintReference as h}from"./TemplateReferenceText.js";import{parseFromClause as g}from"./UiBindingParser.js";const _=`(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*))`,v=r(`^screen\\s+([A-Za-z_]\\w*)$`),y=r(`^data\\s+([\\w.]+(?:\\[\\])?)\\s+via\\s+query\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),b=r(`^action\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),x=r(`^label\\s+${_}$`),S=r(`^action\\s+${_}$`),C=r(`^navigate\\s+to\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),w=r(`^route\\s+${_}$`),T=r(`^outlet\\s+([A-Za-z_]\\w*)$`),E=r(`^contribute\\s+to\\s+([A-Za-z_]\\w*)(?:\\s+order\\s+(-?\\d+))?$`),D=r(`^parameter\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),O=r(`^component\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)\\s+([A-Za-z_]\\w*)$`),k=r(`^id\\s+(?:"(${t})"|(\\S+))$`),A=r(`^property\\s+([\\w.]+)\\s+from\\s+(.+)$`),j=r(`^property\\s+([\\w.]+)\\s*=\\s+(.+)$`),M=r(`^exposes\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),N=r(`^presentation\\s+([A-Za-z_]\\w*)\\s+${_}$`),P=r(`^item\\s+([A-Za-z_]\\w*)\\s+(action|navigate|dialog)(?:\\s+to)?\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),F=r(`^button\\s+(?:"(${t})"|([A-Za-z_][\\w-]*))(?:\\s+(.*))?$`),I=new RegExp(r(`\\s*(title|slice|emphasis|icon)\\s+(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*)|([A-Za-z_][\\w.-]*))(?=\\s|$)`).source,`uy`),L=r(`^[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*$`),R=r(`^[a-z_]\\w*$`),z=r(`^title\\s+${_}$`),B=r(`^column\\s+([\\w.]+)(?:\\s+label\\s+${_})?$`),V=r(`^on\\s+row-click\\s+(navigate\\s+to\\s+.+)$`),H=r(`^field\\s+([\\w.]+)\\s+label\\s+${_}$`),operandText=(e,t)=>e[t]===void 0?e[t+1]:n(e[t]),isInteraction=e=>[`on`,`uses`].includes(o(e.content)),isCodeLine=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseScreen(t,n){let r=v.exec(n.content);r===null&&t.error(e.InvalidScreenDeclaration,`Invalid screen declaration '${n.content}' - expected 'screen <Name>'`,i(n));let a=[],s=[],c=null;for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent))if(t.reader.takeSignificant(),o(e.content)===`contribute`){let n=parseScreenContribution(t,e);n!==void 0&&s.push(n)}else o(e.content)===`description`?c=l(t,e,c,`Screen '${r?.[1]??``}'`):f(e)||pushDirective(t,e,a);return{kind:`ScreenSyntax`,name:r?.[1]??``,directives:a,description:c,...s.length>0?{contributions:s}:{},location:i(n)}}function parseScreenContribution(t,n){let r=E.exec(n.content);if(r===null)t.error(e.UnknownScreenDirective,`Invalid screen contribution '${n.content}' - expected 'contribute to <Point> [order <n>]'`,i(n)),t.skipBlock(n.indent);else return{kind:`ScreenContributionSyntax`,contributionPoint:r[1],order:r[2]===void 0?null:Number(r[2]),directives:parseDirectives(t,n),location:i(n)}}function pushDirective(e,t,n){let r=parseDirective(e,t);r!==void 0&&n.push(r)}function parseDirectives(e,t){let n=[];for(let r=e.peekChild(t.indent);r!==void 0;r=e.peekChild(t.indent))e.reader.takeSignificant(),pushDirective(e,r,n);return n}function parseDirective(t,n){switch(o(n.content)){case`data`:return parseData(t,n);case`action`:return parseAction(t,n);case`template`:return parseTemplateReference(t,n);case`section`:return parseSection(t,n);case`title`:return parseTitle(t,n);case`table`:return parseTable(t,n);case`summary`:return parseSummary(t,n);case`component`:return parseComponent(t,n);case`toolbar`:return parseToolbar(t,n);case`navigate`:return parseNavigate(t,n.content,n);case`on`:return d(t,n),{kind:`ScreenBehaviorSyntax`,location:i(n)};case`uses`:return t.skipOpaqueBlock(n.indent),{kind:`ScreenUsesBehaviorSyntax`,location:i(n)};default:if(isCodeLine(t,n))return parseCode(t,n);t.error(e.UnknownScreenDirective,`Unexpected '${n.content}' in screen body`,i(n)),t.skipBlock(n.indent);return}}function parseData(t,n){let r=y.exec(n.content);if(r===null)t.error(e.InvalidDataDirective,`Invalid data directive '${n.content}' - expected 'data <ReadModel> via query <Query> [by <param>]'`,i(n));else return{kind:`ScreenDataSyntax`,type:s(r[1],i(n)),query:r[2],by:r[3]??null,location:i(n)}}function parseAction(t,n){let r=S.exec(n.content);if(r!==null)return u(t,n,operandText(r,1),parseNavigate);let a=b.exec(n.content);if(a===null){t.error(e.InvalidActionDirective,`Invalid action directive '${n.content}' - expected 'action <Command>'`,i(n)),t.skipBlock(n.indent);return}let s=null,c=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=x.exec(r.content);n===null?o(r.content)===`navigate`?c=parseNavigate(t,r.content,r)??null:t.error(e.UnknownActionDirective,`Unexpected '${r.content}' in action - expected 'label "..."' or 'navigate to ...'`,i(r)):s=operandText(n,1)}return{kind:`ScreenActionSyntax`,command:a[1],label:s,navigate:c,location:i(n)}}function parseNavigate(t,n,r){let a=C.exec(n);if(a===null){t.error(e.InvalidNavigation,`Invalid navigation '${n}' - expected 'navigate to <Screen> [by <param>]'`,i(r));return}let o=[],s=null,c=null;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){t.reader.takeSignificant();let r=D.exec(n.content);if(r!==null){o.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:g(t,r[2],i(n)),location:i(n)});continue}let a=w.exec(n.content);if(a!==null){s=operandText(a,1);continue}let l=T.exec(n.content);l===null?t.error(e.InvalidNavigation,`Unexpected '${n.content}' in navigation - expected 'route "..."', 'outlet <name>' or 'parameter <name> from <binding>'`,i(n)):c=l[1]}return{kind:`ScreenNavigateSyntax`,screen:a[1],by:a[2]??null,route:s,...c===null?{}:{outlet:c},parameters:o,location:i(r)}}function parseTemplateReference(t,n){let r=n.content.substring(8).trim(),a=null,o=null;if(h(r)){let s=m(r);s===void 0?t.error(e.UnknownLayoutDirective,`Invalid template reference '${n.content}' - expected 'template <Name>' or 'template blueprint <Blueprint> <Name> [version "<range>"]'`,i(n)):({blueprint:a,name:r,version:o}=s,o!==null&&!p(o)&&t.error(e.InvalidTemplateVersionRange,`The template version range '${o}' is not one Scene understands - use '*', an exact version or a ^, ~, >=, >, <= or < range such as "^1.2"`,i(n)))}let s=[];for(let a=t.peekChild(n.indent);a!==void 0;a=t.peekChild(n.indent))t.reader.takeSignificant(),R.test(a.content)?s.push({kind:`ScreenSlotSyntax`,name:a.content,directives:parseDirectives(t,a),location:i(a)}):(t.error(e.InvalidScreenLayoutSlot,`Expected a slot name in template '${r}', got '${a.content}'`,i(a)),t.skipBlock(a.indent));return{kind:`ScreenTemplateReferenceSyntax`,name:r,slots:s,...a===null?{}:{blueprint:a},...o===null?{}:{version:o},location:i(n)}}function parseSection(e,t){return{kind:`ScreenSectionSyntax`,name:t.content.substring(7).trim(),directives:parseDirectives(e,t),location:i(t)}}function parseTitle(t,n){let r=z.exec(n.content);return r===null?(t.error(e.InvalidTitleDirective,`Invalid title directive '${n.content}' - expected 'title "..."'`,i(n)),{kind:`ScreenTitleSyntax`,text:``,location:i(n)}):{kind:`ScreenTitleSyntax`,text:operandText(r,1),location:i(n)}}function parseTable(t,n){let r=n.content.substring(5).trim(),a=[],s=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=B.exec(r.content),c=V.exec(r.content);if(n!==null){let e=n[2]!==void 0||n[3]!==void 0;a.push({kind:`ScreenColumnSyntax`,property:n[1],label:e?operandText(n,2):null,location:i(r)})}else c===null?o(r.content)===`on`?d(t,r):isInteraction(r)?t.skipOpaqueBlock(r.indent):t.error(e.UnknownTableDirective,`Unexpected '${r.content}' in table - expected 'column ...', 'on row-click navigate to ...', 'on <trigger>' or 'uses <Behavior>'`,i(r)):s=parseNavigate(t,c[1],r)??null}return{kind:`ScreenTableSyntax`,target:r,columns:a,rowClick:s,location:i(n)}}function parseSummary(t,n){let r=n.content.substring(7).trim(),a=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=H.exec(r.content);n===null?t.error(e.UnknownSummaryDirective,`Unexpected '${r.content}' in summary - expected 'field <property> label "..."'`,i(r)):a.push({kind:`ScreenFieldSyntax`,property:n[1],label:operandText(n,2),location:i(r)})}return{kind:`ScreenSummarySyntax`,target:r,fields:a,location:i(n)}}function parseComponent(t,n){let r=O.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid component directive '${n.content}' - expected 'component <Package.Component> <name>'`,i(n)),t.skipBlock(n.indent);return}let a=null,s=null,c=null,l=[],u=[],f=[],p=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent))switch(t.reader.takeSignificant(),o(r.content)){case`context`:a=parseUiContext(t,r);break;case`id`:s=parseStableId(t,r);break;case`property`:parseComponentProperty(t,r,l);break;case`icon`:c=r.content.substring(4).trim();break;case`presentation`:parsePresentationValue(t,r,f);break;case`exposes`:parseExposedValue(t,r,u);break;case`outlet`:p.push({kind:`ComponentOutletSyntax`,name:r.content.substring(6).trim(),directives:parseDirectives(t,r),location:i(r)});break;case`on`:d(t,r);break;case`uses`:t.skipOpaqueBlock(r.indent);break;default:t.error(e.UnknownScreenDirective,`Unexpected '${r.content}' in component - expected context, id, property, icon, presentation, exposes, outlet, on or uses`,i(r)),t.skipBlock(r.indent)}return{kind:`ScreenComponentSyntax`,component:r[1],name:r[2],stableId:s,context:a,properties:l,exposes:u,presentation:f,icon:c,outlets:p,location:i(n)}}function parseUiContext(e,t){return parseUiBindingValue(e,t.content.substring(7).trim(),t)}function parseComponentProperty(t,n,r){let o=A.exec(n.content);if(o!==null){r.push({kind:`ComponentPropertySyntax`,property:o[1],binding:g(t,o[2],i(n)),value:null,location:i(n)});return}let s=j.exec(n.content);s===null?t.error(e.UnknownScreenDirective,`Invalid component property '${n.content}' - expected 'property <path> from <binding>' or 'property <path> = <literal|object|array|null>'`,i(n)):r.push({kind:`ComponentPropertySyntax`,property:s[1],binding:null,value:a(s[2],i(n),t),location:i(n)})}function parseStableId(t,n){let r=k.exec(n.content);return r===null?(t.error(e.UnknownScreenDirective,`Invalid component id '${n.content}' - expected 'id "stable-id"'`,i(n)),null):operandText(r,1)}function parseExposedValue(t,n,r){let a=M.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid exposed value '${n.content}' - expected 'exposes <name> from <binding>'`,i(n)):r.push({kind:`ComponentExposedValueSyntax`,name:a[1],binding:g(t,a[2],i(n)),location:i(n)})}function parsePresentationValue(t,n,r){let a=N.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid presentation value '${n.content}' - expected 'presentation <key> "value"'`,i(n)):r.push({kind:`PresentationValueSyntax`,name:a[1],value:operandText(a,2),location:i(n)})}function parseToolbar(e,t){let n=t.content.substring(7).trim(),r=[],a=[];for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent)){if(e.reader.takeSignificant(),o(n.content)===`button`){let t=parseToolbarButton(e,n);t!==void 0&&a.push(t);continue}let t=parseToolbarItem(e,n);t!==void 0&&r.push(t)}return{kind:`ScreenToolbarSyntax`,name:n,items:r,...a.length>0?{buttons:a}:{},location:i(t)}}const U=`button <id> title "<text>" [slice <Module>.<Feature>.<Slice>] [emphasis primary|secondary|quiet] [icon <name>]`;function parseToolbarButton(t,r){let a=F.exec(r.content);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - expected ${U}`,i(r)),t.skipBlock(r.indent);return}let o=a[1]===void 0?a[2]:n(a[1]),s=a[3]??``,c,l,u,d,f=!0,p=0;for(;p<s.length;){I.lastIndex=p;let a=I.exec(s);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - unexpected '${s.substring(p).trim()}'; expected ${U}`,i(r)),f=!1;break}p=a.index+a[0].length;let m=a[1],h=a[2]!==void 0,g=a[3]!==void 0,_=h?n(a[2]):g?a[3]:a[4];(m===`title`?c!==void 0:m===`slice`?l!==void 0:m===`icon`?u!==void 0:d!==void 0)?t.error(e.InvalidToolbarButton,`Toolbar button '${o}' states '${m}' more than once`,i(r)):m===`title`?h||g?c=_:(t.error(e.InvalidToolbarButton,`Invalid title '${_}' on toolbar button '${o}' - expected a quoted string or a $strings.<key> token`,i(r)),f=!1):m===`slice`?!h&&!g&&L.test(_)?l=_:(t.error(e.InvalidToolbarButton,`Invalid slice '${_}' on toolbar button '${o}' - expected <Module>.<Feature>.<Slice>`,i(r)),f=!1):m===`emphasis`?!h&&!g&&[`primary`,`secondary`,`quiet`].includes(_)?d=_===`primary`?`Primary`:_===`secondary`?`Secondary`:`Quiet`:(t.error(e.InvalidToolbarButton,`Invalid emphasis '${_}' on toolbar button '${o}' - expected primary, secondary or quiet`,i(r)),f=!1):u=_}return c===void 0&&f&&t.error(e.InvalidToolbarButton,`Toolbar button '${o}' has no title - expected 'button ${o} title "<text>"'`,i(r)),t.peekChild(r.indent)!==void 0&&(t.error(e.InvalidToolbarButton,`Unexpected block under toolbar button '${o}' - a button is one line`,i(r)),t.skipBlock(r.indent)),{kind:`ToolbarButtonSyntax`,id:o,title:c??``,...l===void 0?{}:{slice:l},...d===void 0?{}:{emphasis:d},...u===void 0?{}:{icon:u},location:i(r)}}function parseToolbarItem(t,n){let r=P.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid toolbar item '${n.content}' - expected 'item <name> action <Command>', 'item <name> navigate to <Screen>', 'item <name> dialog <DialogTemplate>' or 'button <id> title "<text>" slice <Slice>'`,i(n)),t.skipBlock(n.indent);return}let a=null,s=null,c=[],l=[];for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent)){t.reader.takeSignificant();let n=x.exec(e.content);if(n!==null){a=operandText(n,1);continue}let r=D.exec(e.content);r===null?o(e.content)===`icon`?s=e.content.substring(4).trim():parsePresentationValue(t,e,l):c.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:g(t,r[2],i(e)),location:i(e)})}let u=r[2]===`navigate`?`Navigate`:r[2]===`dialog`?`Dialog`:`Action`;return{kind:`ToolbarItemSyntax`,name:r[1],syntaxKind:u,target:r[3],label:a,icon:s,parameters:c,presentation:l,location:i(n)}}function parseUiBindingValue(e,t,n){return g(e,t,i(n))}function parseCode(t,n){let r=n.content.startsWith("```")?n.content.substring(3):n.content;if(!t.languages.has(r)){t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${n.content}'`,i(n));return}n.content.startsWith("```")||t.warning(e.LegacyInlineCodeFence,`'${r}' on its own line is deprecated - use '\`\`\`${r}' instead`,i(n));let a=c(t,r,n);return a===null?void 0:{kind:`ScreenCodeSyntax`,code:{kind:`CodeBlockSyntax`,language:r,code:a,location:i(n)},location:i(n)}}export{parseScreen};
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{stringBodyPattern as t,unescapeString as n}from"../Text/StringLiteral.js";import{pattern as r}from"../Text/patterns.js";import{locationOf as i}from"./SourceLine.js";import{parseMappingSource as a}from"./ExpressionParser.js";import{firstWord as o}from"./LineText.js";import{parseTypeRef as s}from"./PropertyLineParser.js";import{parseFencedText as c}from"./CodeBlockParser.js";import{parseDescription as l}from"./DescriptionParser.js";import{parseGuardedAction as u}from"./GuardedActionParser.js";import{collectInputUses as d}from"./InputUses.js";import{isFileDirective as f}from"./FileReferences.js";import{isValidTemplateVersionRange as p,parseBlueprintReference as m,startsBlueprintReference as h}from"./TemplateReferenceText.js";import{parseFromClause as g}from"./UiBindingParser.js";const _=`(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*))`,v=r(`^screen\\s+([A-Za-z_]\\w*)$`),y=r(`^data\\s+([\\w.]+(?:\\[\\])?)\\s+via\\s+query\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),b=r(`^action\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),x=r(`^label\\s+${_}$`),S=r(`^action\\s+${_}$`),C=r(`^navigate\\s+to\\s+(\\w+(?:\\.\\w+)*)(?:\\s+by\\s+(\\w+))?$`),w=r(`^route\\s+${_}$`),T=r(`^outlet\\s+([A-Za-z_]\\w*)$`),E=r(`^contribute\\s+to\\s+([A-Za-z_]\\w*)(?:\\s+order\\s+(-?\\d+))?$`),D=r(`^parameter\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),O=r(`^component\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)\\s+([A-Za-z_]\\w*)$`),k=r(`^id\\s+(?:"(${t})"|(\\S+))$`),A=r(`^property\\s+([\\w.]+)\\s+from\\s+(.+)$`),j=r(`^property\\s+([\\w.]+)\\s*=\\s+(.+)$`),M=r(`^exposes\\s+([A-Za-z_]\\w*)\\s+from\\s+(.+)$`),N=r(`^presentation\\s+([A-Za-z_]\\w*)\\s+${_}$`),P=r(`^item\\s+([A-Za-z_]\\w*)\\s+(action|navigate|dialog)(?:\\s+to)?\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),F=r(`^button\\s+(?:"(${t})"|([A-Za-z_][\\w-]*))(?:\\s+(.*))?$`),I=new RegExp(r(`\\s*(title|slice|emphasis|icon)\\s+(?:"(${t})"|(\\$strings\\.\\w+(?:\\.\\w+)*)|([A-Za-z_][\\w.-]*))(?=\\s|$)`).source,`uy`),L=r(`^[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*$`),R=r(`^[a-z_]\\w*$`),z=r(`^title\\s+${_}$`),B=r(`^column\\s+([\\w.]+)(?:\\s+label\\s+${_})?$`),V=r(`^on\\s+row-click\\s+(navigate\\s+to\\s+.+)$`),H=r(`^field\\s+([\\w.]+)\\s+label\\s+${_}$`),operandText=(e,t)=>e[t]===void 0?e[t+1]:n(e[t]),isInteraction=e=>[`on`,`uses`].includes(o(e.content)),isCodeLine=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseScreen(t,n){let r=v.exec(n.content);r===null&&t.error(e.InvalidScreenDeclaration,`Invalid screen declaration '${n.content}' - expected 'screen <Name>'`,i(n));let a=[],s=[],c=null;for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent))if(t.reader.takeSignificant(),o(e.content)===`contribute`){let n=parseScreenContribution(t,e);n!==void 0&&s.push(n)}else o(e.content)===`description`?c=l(t,e,c,`Screen '${r?.[1]??``}'`):f(e)||pushDirective(t,e,a);return{kind:`ScreenSyntax`,name:r?.[1]??``,directives:a,description:c,...s.length>0?{contributions:s}:{},location:i(n)}}function parseScreenContribution(t,n){let r=E.exec(n.content);if(r===null)t.error(e.UnknownScreenDirective,`Invalid screen contribution '${n.content}' - expected 'contribute to <Point> [order <n>]'`,i(n)),t.skipBlock(n.indent);else return{kind:`ScreenContributionSyntax`,contributionPoint:r[1],order:r[2]===void 0?null:Number(r[2]),directives:parseDirectives(t,n),location:i(n)}}function pushDirective(e,t,n){let r=parseDirective(e,t);r!==void 0&&n.push(r)}function parseDirectives(e,t){let n=[];for(let r=e.peekChild(t.indent);r!==void 0;r=e.peekChild(t.indent))e.reader.takeSignificant(),pushDirective(e,r,n);return n}function parseDirective(t,n){switch(o(n.content)){case`data`:return parseData(t,n);case`action`:return parseAction(t,n);case`template`:return parseTemplateReference(t,n);case`section`:return parseSection(t,n);case`title`:return parseTitle(t,n);case`table`:return parseTable(t,n);case`summary`:return parseSummary(t,n);case`component`:return parseComponent(t,n);case`toolbar`:return parseToolbar(t,n);case`navigate`:return parseNavigate(t,n.content,n);case`on`:return d(t,n),{kind:`ScreenBehaviorSyntax`,location:i(n)};case`uses`:return d(t,n),{kind:`ScreenUsesBehaviorSyntax`,location:i(n)};default:if(isCodeLine(t,n))return parseCode(t,n);t.error(e.UnknownScreenDirective,`Unexpected '${n.content}' in screen body`,i(n)),t.skipBlock(n.indent);return}}function parseData(t,n){let r=y.exec(n.content);if(r===null)t.error(e.InvalidDataDirective,`Invalid data directive '${n.content}' - expected 'data <ReadModel> via query <Query> [by <param>]'`,i(n));else return{kind:`ScreenDataSyntax`,type:s(r[1],i(n)),query:r[2],by:r[3]??null,location:i(n)}}function parseAction(t,n){let r=S.exec(n.content);if(r!==null)return u(t,n,operandText(r,1),parseNavigate);let a=b.exec(n.content);if(a===null){t.error(e.InvalidActionDirective,`Invalid action directive '${n.content}' - expected 'action <Command>'`,i(n)),t.skipBlock(n.indent);return}let s=null,c=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=x.exec(r.content);n===null?o(r.content)===`navigate`?c=parseNavigate(t,r.content,r)??null:t.error(e.UnknownActionDirective,`Unexpected '${r.content}' in action - expected 'label "..."' or 'navigate to ...'`,i(r)):s=operandText(n,1)}return{kind:`ScreenActionSyntax`,command:a[1],label:s,navigate:c,location:i(n)}}function parseNavigate(t,n,r){let a=C.exec(n);if(a===null){t.error(e.InvalidNavigation,`Invalid navigation '${n}' - expected 'navigate to <Screen> [by <param>]'`,i(r));return}let o=[],s=null,c=null;for(let n=t.peekChild(r.indent);n!==void 0;n=t.peekChild(r.indent)){t.reader.takeSignificant();let r=D.exec(n.content);if(r!==null){o.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:g(t,r[2],i(n)),location:i(n)});continue}let a=w.exec(n.content);if(a!==null){s=operandText(a,1);continue}let l=T.exec(n.content);l===null?t.error(e.InvalidNavigation,`Unexpected '${n.content}' in navigation - expected 'route "..."', 'outlet <name>' or 'parameter <name> from <binding>'`,i(n)):c=l[1]}return{kind:`ScreenNavigateSyntax`,screen:a[1],by:a[2]??null,route:s,...c===null?{}:{outlet:c},parameters:o,location:i(r)}}function parseTemplateReference(t,n){let r=n.content.substring(8).trim(),a=null,o=null;if(h(r)){let s=m(r);s===void 0?t.error(e.UnknownLayoutDirective,`Invalid template reference '${n.content}' - expected 'template <Name>' or 'template blueprint <Blueprint> <Name> [version "<range>"]'`,i(n)):({blueprint:a,name:r,version:o}=s,o!==null&&!p(o)&&t.error(e.InvalidTemplateVersionRange,`The template version range '${o}' is not one Scene understands - use '*', an exact version or a ^, ~, >=, >, <= or < range such as "^1.2"`,i(n)))}let s=[];for(let a=t.peekChild(n.indent);a!==void 0;a=t.peekChild(n.indent))t.reader.takeSignificant(),R.test(a.content)?s.push({kind:`ScreenSlotSyntax`,name:a.content,directives:parseDirectives(t,a),location:i(a)}):(t.error(e.InvalidScreenLayoutSlot,`Expected a slot name in template '${r}', got '${a.content}'`,i(a)),t.skipBlock(a.indent));return{kind:`ScreenTemplateReferenceSyntax`,name:r,slots:s,...a===null?{}:{blueprint:a},...o===null?{}:{version:o},location:i(n)}}function parseSection(e,t){return{kind:`ScreenSectionSyntax`,name:t.content.substring(7).trim(),directives:parseDirectives(e,t),location:i(t)}}function parseTitle(t,n){let r=z.exec(n.content);return r===null?(t.error(e.InvalidTitleDirective,`Invalid title directive '${n.content}' - expected 'title "..."'`,i(n)),{kind:`ScreenTitleSyntax`,text:``,location:i(n)}):{kind:`ScreenTitleSyntax`,text:operandText(r,1),location:i(n)}}function parseTable(t,n){let r=n.content.substring(5).trim(),a=[],s=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=B.exec(r.content),c=V.exec(r.content);if(n!==null){let e=n[2]!==void 0||n[3]!==void 0;a.push({kind:`ScreenColumnSyntax`,property:n[1],label:e?operandText(n,2):null,location:i(r)})}else c===null?o(r.content)===`on`||isInteraction(r)?d(t,r):t.error(e.UnknownTableDirective,`Unexpected '${r.content}' in table - expected 'column ...', 'on row-click navigate to ...', 'on <trigger>' or 'uses <Behavior>'`,i(r)):s=parseNavigate(t,c[1],r)??null}return{kind:`ScreenTableSyntax`,target:r,columns:a,rowClick:s,location:i(n)}}function parseSummary(t,n){let r=n.content.substring(7).trim(),a=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){t.reader.takeSignificant();let n=H.exec(r.content);n===null?t.error(e.UnknownSummaryDirective,`Unexpected '${r.content}' in summary - expected 'field <property> label "..."'`,i(r)):a.push({kind:`ScreenFieldSyntax`,property:n[1],label:operandText(n,2),location:i(r)})}return{kind:`ScreenSummarySyntax`,target:r,fields:a,location:i(n)}}function parseComponent(t,n){let r=O.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid component directive '${n.content}' - expected 'component <Package.Component> <name>'`,i(n)),t.skipBlock(n.indent);return}let a=null,s=null,c=null,l=[],u=[],f=[],p=[];for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent))switch(t.reader.takeSignificant(),o(r.content)){case`context`:a=parseUiContext(t,r);break;case`id`:s=parseStableId(t,r);break;case`property`:parseComponentProperty(t,r,l);break;case`icon`:c=r.content.substring(4).trim();break;case`presentation`:parsePresentationValue(t,r,f);break;case`exposes`:parseExposedValue(t,r,u);break;case`outlet`:p.push({kind:`ComponentOutletSyntax`,name:r.content.substring(6).trim(),directives:parseDirectives(t,r),location:i(r)});break;case`on`:d(t,r);break;case`uses`:d(t,r);break;default:t.error(e.UnknownScreenDirective,`Unexpected '${r.content}' in component - expected context, id, property, icon, presentation, exposes, outlet, on or uses`,i(r)),t.skipBlock(r.indent)}return{kind:`ScreenComponentSyntax`,component:r[1],name:r[2],stableId:s,context:a,properties:l,exposes:u,presentation:f,icon:c,outlets:p,location:i(n)}}function parseUiContext(e,t){return parseUiBindingValue(e,t.content.substring(7).trim(),t)}function parseComponentProperty(t,n,r){let o=A.exec(n.content);if(o!==null){r.push({kind:`ComponentPropertySyntax`,property:o[1],binding:g(t,o[2],i(n)),value:null,location:i(n)});return}let s=j.exec(n.content);s===null?t.error(e.UnknownScreenDirective,`Invalid component property '${n.content}' - expected 'property <path> from <binding>' or 'property <path> = <literal|object|array|null>'`,i(n)):r.push({kind:`ComponentPropertySyntax`,property:s[1],binding:null,value:a(s[2],i(n),t),location:i(n)})}function parseStableId(t,n){let r=k.exec(n.content);return r===null?(t.error(e.UnknownScreenDirective,`Invalid component id '${n.content}' - expected 'id "stable-id"'`,i(n)),null):operandText(r,1)}function parseExposedValue(t,n,r){let a=M.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid exposed value '${n.content}' - expected 'exposes <name> from <binding>'`,i(n)):r.push({kind:`ComponentExposedValueSyntax`,name:a[1],binding:g(t,a[2],i(n)),location:i(n)})}function parsePresentationValue(t,n,r){let a=N.exec(n.content);a===null?t.error(e.UnknownScreenDirective,`Invalid presentation value '${n.content}' - expected 'presentation <key> "value"'`,i(n)):r.push({kind:`PresentationValueSyntax`,name:a[1],value:operandText(a,2),location:i(n)})}function parseToolbar(e,t){let n=t.content.substring(7).trim(),r=[],a=[];for(let n=e.peekChild(t.indent);n!==void 0;n=e.peekChild(t.indent)){if(e.reader.takeSignificant(),o(n.content)===`button`){let t=parseToolbarButton(e,n);t!==void 0&&a.push(t);continue}let t=parseToolbarItem(e,n);t!==void 0&&r.push(t)}return{kind:`ScreenToolbarSyntax`,name:n,items:r,...a.length>0?{buttons:a}:{},location:i(t)}}const U=`button <id> title "<text>" [slice <Module>.<Feature>.<Slice>] [emphasis primary|secondary|quiet] [icon <name>]`;function parseToolbarButton(t,r){let a=F.exec(r.content);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - expected ${U}`,i(r)),t.skipBlock(r.indent);return}let o=a[1]===void 0?a[2]:n(a[1]),s=a[3]??``,c,l,u,d,f=!0,p=0;for(;p<s.length;){I.lastIndex=p;let a=I.exec(s);if(a===null){t.error(e.InvalidToolbarButton,`Invalid toolbar button '${r.content}' - unexpected '${s.substring(p).trim()}'; expected ${U}`,i(r)),f=!1;break}p=a.index+a[0].length;let m=a[1],h=a[2]!==void 0,g=a[3]!==void 0,_=h?n(a[2]):g?a[3]:a[4];(m===`title`?c!==void 0:m===`slice`?l!==void 0:m===`icon`?u!==void 0:d!==void 0)?t.error(e.InvalidToolbarButton,`Toolbar button '${o}' states '${m}' more than once`,i(r)):m===`title`?h||g?c=_:(t.error(e.InvalidToolbarButton,`Invalid title '${_}' on toolbar button '${o}' - expected a quoted string or a $strings.<key> token`,i(r)),f=!1):m===`slice`?!h&&!g&&L.test(_)?l=_:(t.error(e.InvalidToolbarButton,`Invalid slice '${_}' on toolbar button '${o}' - expected <Module>.<Feature>.<Slice>`,i(r)),f=!1):m===`emphasis`?!h&&!g&&[`primary`,`secondary`,`quiet`].includes(_)?d=_===`primary`?`Primary`:_===`secondary`?`Secondary`:`Quiet`:(t.error(e.InvalidToolbarButton,`Invalid emphasis '${_}' on toolbar button '${o}' - expected primary, secondary or quiet`,i(r)),f=!1):u=_}return c===void 0&&f&&t.error(e.InvalidToolbarButton,`Toolbar button '${o}' has no title - expected 'button ${o} title "<text>"'`,i(r)),t.peekChild(r.indent)!==void 0&&(t.error(e.InvalidToolbarButton,`Unexpected block under toolbar button '${o}' - a button is one line`,i(r)),t.skipBlock(r.indent)),{kind:`ToolbarButtonSyntax`,id:o,title:c??``,...l===void 0?{}:{slice:l},...d===void 0?{}:{emphasis:d},...u===void 0?{}:{icon:u},location:i(r)}}function parseToolbarItem(t,n){let r=P.exec(n.content);if(r===null){t.error(e.UnknownScreenDirective,`Invalid toolbar item '${n.content}' - expected 'item <name> action <Command>', 'item <name> navigate to <Screen>', 'item <name> dialog <DialogTemplate>' or 'button <id> title "<text>" slice <Slice>'`,i(n)),t.skipBlock(n.indent);return}let a=null,s=null,c=[],l=[];for(let e=t.peekChild(n.indent);e!==void 0;e=t.peekChild(n.indent)){t.reader.takeSignificant();let n=x.exec(e.content);if(n!==null){a=operandText(n,1);continue}let r=D.exec(e.content);r===null?o(e.content)===`icon`?s=e.content.substring(4).trim():parsePresentationValue(t,e,l):c.push({kind:`ScreenNavigationParameterSyntax`,name:r[1],binding:g(t,r[2],i(e)),location:i(e)})}let u=r[2]===`navigate`?`Navigate`:r[2]===`dialog`?`Dialog`:`Action`;return{kind:`ToolbarItemSyntax`,name:r[1],syntaxKind:u,target:r[3],label:a,icon:s,parameters:c,presentation:l,location:i(n)}}function parseUiBindingValue(e,t,n){return g(e,t,i(n))}function parseCode(t,n){let r=n.content.startsWith("```")?n.content.substring(3):n.content;if(!t.languages.has(r)){t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${n.content}'`,i(n));return}n.content.startsWith("```")||t.warning(e.LegacyInlineCodeFence,`'${r}' on its own line is deprecated - use '\`\`\`${r}' instead`,i(n));let a=c(t,r,n);return a===null?void 0:{kind:`ScreenCodeSyntax`,code:{kind:`CodeBlockSyntax`,language:r,code:a,location:i(n)},location:i(n)}}export{parseScreen};
|
|
2
2
|
//# sourceMappingURL=ScreenParser.js.map
|