@cratis/screenplay-language 4.123.0 → 4.124.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/README.md +50 -0
- package/dist/bundles/TypeReferenceSymbol.js +2 -0
- package/dist/bundles/TypeReferenceSymbol.js.map +1 -0
- package/dist/bundles/_virtual/_virtual/_rolldown/runtime.js +1 -0
- package/dist/bundles/bmp-word-characters.js +2 -0
- package/dist/bundles/bmp-word-characters.js.map +1 -0
- package/dist/bundles/case-authoring.js +3 -0
- package/dist/bundles/case-authoring.js.map +1 -0
- package/dist/bundles/code-actions.js +2 -0
- package/dist/bundles/code-actions.js.map +1 -0
- package/dist/bundles/compiler/Authoring/QuickFixes.js +5 -0
- package/dist/bundles/compiler/Authoring/QuickFixes.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/DeclaredDependencies.js +2 -0
- package/dist/bundles/compiler/Dependencies/DeclaredDependencies.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/DeclaredDependencyTargets.js +2 -0
- package/dist/bundles/compiler/Dependencies/DeclaredDependencyTargets.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/DependencyGraph.js +2 -0
- package/dist/bundles/compiler/Dependencies/DependencyGraph.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/DependencyKind.js +2 -0
- package/dist/bundles/compiler/Dependencies/DependencyKind.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/InvalidDependencyQuery.js +2 -0
- package/dist/bundles/compiler/Dependencies/InvalidDependencyQuery.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/SliceReferences.js +2 -0
- package/dist/bundles/compiler/Dependencies/SliceReferences.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/StronglyConnectedGroups.js +2 -0
- package/dist/bundles/compiler/Dependencies/StronglyConnectedGroups.js.map +1 -0
- package/dist/bundles/compiler/Dependencies/index.js +1 -0
- package/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js +2 -0
- package/dist/bundles/compiler/Diagnostics/DiagnosticCodes.js.map +1 -0
- package/dist/bundles/compiler/Diagnostics/ProductionDestinationDiagnostics.js +2 -0
- package/dist/bundles/compiler/Diagnostics/ProductionDestinationDiagnostics.js.map +1 -0
- package/dist/bundles/compiler/Diagnostics/SourceLocation.js +2 -0
- package/dist/bundles/compiler/Diagnostics/SourceLocation.js.map +1 -0
- package/dist/bundles/compiler/Files/AuthoredOrder.js +2 -0
- package/dist/bundles/compiler/Files/AuthoredOrder.js.map +1 -0
- package/dist/bundles/compiler/Files/OrderingRoot.js +1 -0
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js +2 -0
- package/dist/bundles/compiler/Files/PlayApplicationAssembly.js.map +1 -0
- package/dist/bundles/compiler/Files/PlayFolderMerge.js +2 -0
- package/dist/bundles/compiler/Files/PlayFolderMerge.js.map +1 -0
- package/dist/bundles/compiler/Files/PlayImports.js +1 -0
- package/dist/bundles/compiler/Files/PlayPlacement.js +2 -0
- package/dist/bundles/compiler/Files/PlayPlacement.js.map +1 -0
- package/dist/bundles/compiler/Files/TimelineOrder.js +2 -0
- package/dist/bundles/compiler/Files/TimelineOrder.js.map +1 -0
- package/dist/bundles/compiler/Parsing/AuthorizeParser.js +2 -0
- package/dist/bundles/compiler/Parsing/AuthorizeParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CaptureParser.js +2 -0
- package/dist/bundles/compiler/Parsing/CaptureParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CodeBlockParser.js +3 -0
- package/dist/bundles/compiler/Parsing/CodeBlockParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CommandDestinationTypes.js +2 -0
- package/dist/bundles/compiler/Parsing/CommandDestinationTypes.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CommandParser.js +2 -0
- package/dist/bundles/compiler/Parsing/CommandParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CommandReadSources.js +2 -0
- package/dist/bundles/compiler/Parsing/CommandReadSources.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CommandResponseParser.js +2 -0
- package/dist/bundles/compiler/Parsing/CommandResponseParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CommandStreamCandidates.js +2 -0
- package/dist/bundles/compiler/Parsing/CommandStreamCandidates.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CompositeStreamIdValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/CompositeStreamIdValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/CompositionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/CompositionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ConceptComplianceParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ConceptComplianceParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ConditionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ConditionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ConstraintParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ConstraintParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ConstraintPropertyValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ConstraintPropertyValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/DeclarationParsers.js +2 -0
- package/dist/bundles/compiler/Parsing/DeclarationParsers.js.map +1 -0
- package/dist/bundles/compiler/Parsing/DependencySourceParser.js +2 -0
- package/dist/bundles/compiler/Parsing/DependencySourceParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/DependsOnParser.js +2 -0
- package/dist/bundles/compiler/Parsing/DependsOnParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/DescriptionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/DescriptionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/DocumentationParser.js +2 -0
- package/dist/bundles/compiler/Parsing/DocumentationParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/EventMetadataParser.js +2 -0
- package/dist/bundles/compiler/Parsing/EventMetadataParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/EventSourceParser.js +2 -0
- package/dist/bundles/compiler/Parsing/EventSourceParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/EventSourceValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/EventSourceValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/EventSubjectValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/EventSubjectValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ExpressionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ExpressionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/FeatureBody.js +2 -0
- package/dist/bundles/compiler/Parsing/FeatureBody.js.map +1 -0
- package/dist/bundles/compiler/Parsing/FileImportParser.js +2 -0
- package/dist/bundles/compiler/Parsing/FileImportParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/FileReferences.js +2 -0
- package/dist/bundles/compiler/Parsing/FileReferences.js.map +1 -0
- package/dist/bundles/compiler/Parsing/GuardedActionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/GuardedActionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/GuardedActionShadowing.js +2 -0
- package/dist/bundles/compiler/Parsing/GuardedActionShadowing.js.map +1 -0
- package/dist/bundles/compiler/Parsing/GuardedActionValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/GuardedActionValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/IdentifierComplianceValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/IdentifierComplianceValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/IdentityParser.js +2 -0
- package/dist/bundles/compiler/Parsing/IdentityParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/IdentityValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/IdentityValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ImplementationParser.js +3 -0
- package/dist/bundles/compiler/Parsing/ImplementationParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ImportDiscovery.js +1 -0
- package/dist/bundles/compiler/Parsing/InlineEventValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/InlineEventValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/InputUses.js +2 -0
- package/dist/bundles/compiler/Parsing/InputUses.js.map +1 -0
- package/dist/bundles/compiler/Parsing/InteractionAlternatives.js +2 -0
- package/dist/bundles/compiler/Parsing/InteractionAlternatives.js.map +1 -0
- package/dist/bundles/compiler/Parsing/LineReader.js +2 -0
- package/dist/bundles/compiler/Parsing/LineReader.js.map +1 -0
- package/dist/bundles/compiler/Parsing/LineText.js +2 -0
- package/dist/bundles/compiler/Parsing/LineText.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ModuleBody.js +2 -0
- package/dist/bundles/compiler/Parsing/ModuleBody.js.map +1 -0
- package/dist/bundles/compiler/Parsing/OperationParser.js +2 -0
- package/dist/bundles/compiler/Parsing/OperationParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/OperationValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/OperationValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ParserContext.js +2 -0
- package/dist/bundles/compiler/Parsing/ParserContext.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PersonaCallerValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/PersonaCallerValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PolicyParser.js +2 -0
- package/dist/bundles/compiler/Parsing/PolicyParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProducesParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ProducesParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProjectionExpressionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ProjectionExpressionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProjectionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ProjectionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ProjectionTargetValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ProjectionTargetValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PropertyLineParser.js +2 -0
- package/dist/bundles/compiler/Parsing/PropertyLineParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PublicEventMetadataValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/PublicEventMetadataValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PublicEventUsageCollector.js +2 -0
- package/dist/bundles/compiler/Parsing/PublicEventUsageCollector.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PublicEventUsageValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/PublicEventUsageValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PurposeParser.js +2 -0
- package/dist/bundles/compiler/Parsing/PurposeParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/PurposeValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/PurposeValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/QueryParser.js +2 -0
- package/dist/bundles/compiler/Parsing/QueryParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ReactionIdentityParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ReactionIdentityParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ReactionParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ReactionParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ReactionRefusalValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ReactionRefusalValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/RedeliveryValues.js +2 -0
- package/dist/bundles/compiler/Parsing/RedeliveryValues.js.map +1 -0
- package/dist/bundles/compiler/Parsing/RefusalDeclarations.js +2 -0
- package/dist/bundles/compiler/Parsing/RefusalDeclarations.js.map +1 -0
- package/dist/bundles/compiler/Parsing/RefusalValueWalker.js +2 -0
- package/dist/bundles/compiler/Parsing/RefusalValueWalker.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ResponseDateValues.js +2 -0
- package/dist/bundles/compiler/Parsing/ResponseDateValues.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ResponseValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/ResponseValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ScreenParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ScreenParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/ScreenplayParser.js +2 -0
- package/dist/bundles/compiler/Parsing/ScreenplayParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SeedParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SeedParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SliceParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SliceParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SourceLine.js +2 -0
- package/dist/bundles/compiler/Parsing/SourceLine.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SourceLineSplitter.js +3 -0
- package/dist/bundles/compiler/Parsing/SourceLineSplitter.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SourceOptionsParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SourceOptionsParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationCaseParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationCaseParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationCaseValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationCaseValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationCommandExamples.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationCommandExamples.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationExampleParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationExampleParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationRedeliveryValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationRedeliveryValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationResponseParser.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationResponseParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationRouteComparison.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationRouteComparison.js.map +1 -0
- package/dist/bundles/compiler/Parsing/SpecificationStreamValidator.js +2 -0
- package/dist/bundles/compiler/Parsing/SpecificationStreamValidator.js.map +1 -0
- package/dist/bundles/compiler/Parsing/StructuredValueParser.js +3 -0
- package/dist/bundles/compiler/Parsing/StructuredValueParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/TriggerDataParser.js +2 -0
- package/dist/bundles/compiler/Parsing/TriggerDataParser.js.map +1 -0
- package/dist/bundles/compiler/Parsing/UiBindingParser.js +2 -0
- package/dist/bundles/compiler/Parsing/UiBindingParser.js.map +1 -0
- package/dist/bundles/compiler/ScreenplayCompiler.js +2 -0
- package/dist/bundles/compiler/ScreenplayCompiler.js.map +1 -0
- package/dist/bundles/compiler/Syntax/AuthoringProductionResolver.js +2 -0
- package/dist/bundles/compiler/Syntax/AuthoringProductionResolver.js.map +1 -0
- package/dist/bundles/compiler/Syntax/CaptureEventsSource.js +2 -0
- package/dist/bundles/compiler/Syntax/CaptureEventsSource.js.map +1 -0
- package/dist/bundles/compiler/Syntax/DependencySources.js +2 -0
- package/dist/bundles/compiler/Syntax/DependencySources.js.map +1 -0
- package/dist/bundles/compiler/Syntax/EventDeclarations.js +2 -0
- package/dist/bundles/compiler/Syntax/EventDeclarations.js.map +1 -0
- package/dist/bundles/compiler/Syntax/EventSourceCatalog.js +2 -0
- package/dist/bundles/compiler/Syntax/EventSourceCatalog.js.map +1 -0
- package/dist/bundles/compiler/Syntax/EventSourceReadConfidence.js +2 -0
- package/dist/bundles/compiler/Syntax/EventSourceReadConfidence.js.map +1 -0
- package/dist/bundles/compiler/Syntax/ExactMathFacts.js +2 -0
- package/dist/bundles/compiler/Syntax/ExactMathFacts.js.map +1 -0
- package/dist/bundles/compiler/Syntax/ExactNumber.js +2 -0
- package/dist/bundles/compiler/Syntax/ExactNumber.js.map +1 -0
- package/dist/bundles/compiler/Syntax/InvalidSyntaxJson.js +2 -0
- package/dist/bundles/compiler/Syntax/InvalidSyntaxJson.js.map +1 -0
- package/dist/bundles/compiler/Syntax/LegacyWireProjection.js +2 -0
- package/dist/bundles/compiler/Syntax/LegacyWireProjection.js.map +1 -0
- package/dist/bundles/compiler/Syntax/Operations.js +2 -0
- package/dist/bundles/compiler/Syntax/Operations.js.map +1 -0
- package/dist/bundles/compiler/Syntax/PersonaCallers.js +2 -0
- package/dist/bundles/compiler/Syntax/PersonaCallers.js.map +1 -0
- package/dist/bundles/compiler/Syntax/ProductionDestinations.js +2 -0
- package/dist/bundles/compiler/Syntax/ProductionDestinations.js.map +1 -0
- package/dist/bundles/compiler/Syntax/PublicEventInvariants.js +2 -0
- package/dist/bundles/compiler/Syntax/PublicEventInvariants.js.map +1 -0
- package/dist/bundles/compiler/Syntax/ScreenplaySyntaxWalker.js +2 -0
- package/dist/bundles/compiler/Syntax/ScreenplaySyntaxWalker.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SourceOptions.js +2 -0
- package/dist/bundles/compiler/Syntax/SourceOptions.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SpecificationCaseOrigin.js +2 -0
- package/dist/bundles/compiler/Syntax/SpecificationCaseOrigin.js.map +1 -0
- package/dist/bundles/compiler/Syntax/StreamIdFormatter.js +2 -0
- package/dist/bundles/compiler/Syntax/StreamIdFormatter.js.map +1 -0
- package/dist/bundles/compiler/Syntax/StrictSyntaxJson.js +1 -0
- package/dist/bundles/compiler/Syntax/Structure.js +2 -0
- package/dist/bundles/compiler/Syntax/Structure.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SyntaxCollections.js +2 -0
- package/dist/bundles/compiler/Syntax/SyntaxCollections.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SyntaxInvariants.js +2 -0
- package/dist/bundles/compiler/Syntax/SyntaxInvariants.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SyntaxJson.js +2 -0
- package/dist/bundles/compiler/Syntax/SyntaxJson.js.map +1 -0
- package/dist/bundles/compiler/Syntax/SyntaxMemberContracts.js +2 -0
- package/dist/bundles/compiler/Syntax/SyntaxMemberContracts.js.map +1 -0
- package/dist/bundles/compiler/Syntax/index.js +1 -0
- package/dist/bundles/compiler/Text/ImplementationHintText.js +2 -0
- package/dist/bundles/compiler/Text/ImplementationHintText.js.map +1 -0
- package/dist/bundles/compiler/Text/ReservedWords.js +2 -0
- package/dist/bundles/compiler/Text/ReservedWords.js.map +1 -0
- package/dist/bundles/compiler/Text/SourceStreamNames.js +2 -0
- package/dist/bundles/compiler/Text/SourceStreamNames.js.map +1 -0
- package/dist/bundles/compiler/Text/StringLiteral.js +3 -0
- package/dist/bundles/compiler/Text/StringLiteral.js.map +1 -0
- package/dist/bundles/compiler/Text/ordinalIgnoreCaseKey.js +2 -0
- package/dist/bundles/compiler/Text/ordinalIgnoreCaseKey.js.map +1 -0
- package/dist/bundles/compiler/Text/patterns.js +2 -0
- package/dist/bundles/compiler/Text/patterns.js.map +1 -0
- package/dist/bundles/compiler/index.js +1 -0
- package/dist/bundles/completion-items.js +21 -0
- package/dist/bundles/completion-items.js.map +1 -0
- package/dist/bundles/completion-planner.js +5 -0
- package/dist/bundles/completion-planner.js.map +1 -0
- package/dist/bundles/completions.js +2 -0
- package/dist/bundles/completions.js.map +1 -0
- package/dist/bundles/dependency-completions.js +3 -0
- package/dist/bundles/dependency-completions.js.map +1 -0
- package/dist/bundles/dependency-target-analysis.js +2 -0
- package/dist/bundles/dependency-target-analysis.js.map +1 -0
- package/dist/bundles/diagnostic-codes.js +2 -0
- package/dist/bundles/diagnostic-codes.js.map +1 -0
- package/dist/bundles/diagnostics.js +2 -0
- package/dist/bundles/diagnostics.js.map +1 -0
- package/dist/bundles/document-context.js +2 -0
- package/dist/bundles/document-context.js.map +1 -0
- package/dist/bundles/documentation-item.js +2 -0
- package/dist/bundles/documentation-item.js.map +1 -0
- package/dist/bundles/event-analysis-source.js +2 -0
- package/dist/bundles/event-analysis-source.js.map +1 -0
- package/dist/bundles/event-context-catalog.js +2 -0
- package/dist/bundles/event-context-catalog.js.map +1 -0
- package/dist/bundles/event-context.js +4 -0
- package/dist/bundles/event-context.js.map +1 -0
- package/dist/bundles/event-source-authoring.js +13 -0
- package/dist/bundles/event-source-authoring.js.map +1 -0
- package/dist/bundles/example-analysis.js +3 -0
- package/dist/bundles/example-analysis.js.map +1 -0
- package/dist/bundles/example-authoring.js +3 -0
- package/dist/bundles/example-authoring.js.map +1 -0
- package/dist/bundles/example-declaration-items.js +2 -0
- package/dist/bundles/example-declaration-items.js.map +1 -0
- package/dist/bundles/example-values.js +2 -0
- package/dist/bundles/example-values.js.map +1 -0
- package/dist/bundles/file-imports.js +2 -0
- package/dist/bundles/file-imports.js.map +1 -0
- package/dist/bundles/file-references.js +2 -0
- package/dist/bundles/file-references.js.map +1 -0
- package/dist/bundles/hover-content.js +6 -0
- package/dist/bundles/hover-content.js.map +1 -0
- package/dist/bundles/hover.js +2 -0
- package/dist/bundles/hover.js.map +1 -0
- package/dist/bundles/index.js +2 -104
- package/dist/bundles/index.js.map +1 -7
- package/dist/bundles/inlay-hints.js +2 -0
- package/dist/bundles/inlay-hints.js.map +1 -0
- package/dist/bundles/inline-completions.js +2 -0
- package/dist/bundles/inline-completions.js.map +1 -0
- package/dist/bundles/inline-event-validation.js +2 -0
- package/dist/bundles/inline-event-validation.js.map +1 -0
- package/dist/bundles/keyword-docs.js +2 -0
- package/dist/bundles/keyword-docs.js.map +1 -0
- package/dist/bundles/language.js +2 -0
- package/dist/bundles/language.js.map +1 -0
- package/dist/bundles/named-rule-context.js +2 -0
- package/dist/bundles/named-rule-context.js.map +1 -0
- package/dist/bundles/operation-authoring.js +7 -0
- package/dist/bundles/operation-authoring.js.map +1 -0
- package/dist/bundles/persona-analysis.js +2 -0
- package/dist/bundles/persona-analysis.js.map +1 -0
- package/dist/bundles/production-destinations.js +2 -0
- package/dist/bundles/production-destinations.js.map +1 -0
- package/dist/bundles/purpose-items.js +2 -0
- package/dist/bundles/purpose-items.js.map +1 -0
- package/dist/bundles/reaction-authoring.js +5 -0
- package/dist/bundles/reaction-authoring.js.map +1 -0
- package/dist/bundles/refusal-context.js +2 -0
- package/dist/bundles/refusal-context.js.map +1 -0
- package/dist/bundles/response-analysis.js +7 -0
- package/dist/bundles/response-analysis.js.map +1 -0
- package/dist/bundles/response-completions.js +2 -0
- package/dist/bundles/response-completions.js.map +1 -0
- package/dist/bundles/response-tokens.js +3 -0
- package/dist/bundles/response-tokens.js.map +1 -0
- package/dist/bundles/scope-items.js +18 -0
- package/dist/bundles/scope-items.js.map +1 -0
- package/dist/bundles/structure-completions.js +7 -0
- package/dist/bundles/structure-completions.js.map +1 -0
- package/dist/bundles/sub-language-registry.js +2 -0
- package/dist/bundles/sub-language-registry.js.map +1 -0
- package/dist/bundles/sub-languages/capture/CompletionProvider.js +2 -0
- package/dist/bundles/sub-languages/capture/CompletionProvider.js.map +1 -0
- package/dist/bundles/sub-languages/capture/HoverProvider.js +60 -0
- package/dist/bundles/sub-languages/capture/HoverProvider.js.map +1 -0
- package/dist/bundles/sub-languages/capture/Validator.js +2 -0
- package/dist/bundles/sub-languages/capture/Validator.js.map +1 -0
- package/dist/bundles/sub-languages/capture/index.js +2 -40
- package/dist/bundles/sub-languages/capture/index.js.map +1 -7
- package/dist/bundles/sub-languages/capture/language.js +2 -0
- package/dist/bundles/sub-languages/capture/language.js.map +1 -0
- package/dist/bundles/sub-languages/cdl.js +2 -0
- package/dist/bundles/sub-languages/cdl.js.map +1 -0
- package/dist/bundles/sub-languages/pdl.js +2 -0
- package/dist/bundles/sub-languages/pdl.js.map +1 -0
- package/dist/bundles/sub-languages/projection/CodeActionProvider.js +2 -0
- package/dist/bundles/sub-languages/projection/CodeActionProvider.js.map +1 -0
- package/dist/bundles/sub-languages/projection/CompletionProvider.js +2 -0
- package/dist/bundles/sub-languages/projection/CompletionProvider.js.map +1 -0
- package/dist/bundles/sub-languages/projection/HoverProvider.js +43 -0
- package/dist/bundles/sub-languages/projection/HoverProvider.js.map +1 -0
- package/dist/bundles/sub-languages/projection/Validator.js +5 -0
- package/dist/bundles/sub-languages/projection/Validator.js.map +1 -0
- package/dist/bundles/sub-languages/projection/index.js +3 -75
- package/dist/bundles/sub-languages/projection/index.js.map +1 -7
- package/dist/bundles/sub-languages/projection/language.js +2 -0
- package/dist/bundles/sub-languages/projection/language.js.map +1 -0
- package/dist/bundles/symbols.js +3 -0
- package/dist/bundles/symbols.js.map +1 -0
- package/dist/bundles/themes/screenplay-dark.js +2 -0
- package/dist/bundles/themes/screenplay-dark.js.map +1 -0
- package/dist/bundles/themes/screenplay-light.js +2 -0
- package/dist/bundles/themes/screenplay-light.js.map +1 -0
- package/dist/bundles/tokens.js +2 -0
- package/dist/bundles/tokens.js.map +1 -0
- package/dist/bundles/validation.js +3 -0
- package/dist/bundles/validation.js.map +1 -0
- package/dist/completion-items.d.ts.map +1 -1
- package/dist/diagnostic-codes.d.ts +6 -0
- package/dist/diagnostic-codes.d.ts.map +1 -1
- package/dist/keyword-docs.d.ts.map +1 -1
- package/dist/language.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/package.json +4 -3
- package/dist/bundles/chunk-4CLLEMBX.js +0 -42
- package/dist/bundles/chunk-4CLLEMBX.js.map +0 -7
- package/dist/bundles/chunk-AYDF3IFZ.js +0 -2
- package/dist/bundles/chunk-AYDF3IFZ.js.map +0 -7
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{AuthoringProductionResolver as t}from"../Syntax/AuthoringProductionResolver.js";import{EventSourceCatalog as n}from"../Syntax/EventSourceCatalog.js";import{compatibleValue as r,uniqueByName as i}from"./ResponseValidator.js";import{commandDestinationType as a}from"./CommandDestinationTypes.js";import{streamIdFailureMessage as o,tryFormatInteger as s,tryFormatText as c,tryFormatUuidText as l}from"../Syntax/StreamIdFormatter.js";import{validateStreamIdParts as u}from"./CompositeStreamIdValidator.js";import{validateSpecificationStreams as d}from"./SpecificationStreamValidator.js";const f=/* @__PURE__ */ new Set([`String`,`Uuid`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`]);function supportsStreamIdentity(e,t){let n=t.concepts.filter(t=>t.name===e.name),r=n.length===1?n[0].type:n.length===0&&f.has(e.name)?e.name:null;return r===`String`||r===`Uuid`||r===`Int`&&n.length===1&&n[0].values.length===0}function formatStreamIdLiteral(e,t,n){if(e?.kind!==`LiteralExpressionSyntax`)return null;let r=e.value,a=t===null?null:i(n.concepts).get(t.name)?.type??t.name;return typeof r==`string`?a===`Uuid`?l(r):c(r):typeof r==`number`?s(r):typeof r==`object`&&r&&r.literalType===`ExactNumber`?r.value.includes(`.`)?s(NaN):s(BigInt(r.value),!1):null}function validateEventSources(s,c){let l=i(s.concepts),p=i(s.types),m=/* @__PURE__ */ new Set([...f,...l.keys(),...p.keys()]),h=new Map([...p].map(([e,t])=>[e,i(t.properties)])),compatible=(e,t)=>m.has(e.name)&&m.has(t.name)?e.name===t.name&&e.isCollection===t.isCollection&&(!e.isOptional||t.isOptional):null,validateType=(t,n)=>{if(t===null)return;if(t.isOptional||t.isCollection||s.types.some(e=>e.name===t.name)){c.error(e.InvalidEventSourceDeclaration,`Identifier and streamId declarations require a nonoptional scalar value type.`,t.location);return}let r=s.concepts.filter(e=>e.name===t.name),i=r.length===1?r[0].type:r.length===0&&f.has(t.name)?t.name:null;n&&i!==null&&!supportsStreamIdentity(t,s)&&c.error(e.UnsupportedStreamIdType,`Stream ids support text and UUID values and their nominal concepts, plus integer-backed concepts; other types need a future portable formatter.`,t.location),i===null&&!s.imports.some(e=>e.qualifiedName===t.name||e.qualifiedName.split(`.`).at(-1)===t.name)&&c.warning(e.UnknownType,`Unknown type '${t.name}' in event source declaration.`,t.location)},g=/* @__PURE__ */ new Set;for(let t of s.eventSources??[]){g.has(t.name)&&c.error(e.InvalidEventSourceDeclaration,`Event source '${t.name}' has multiple physical declarations.`,t.location),g.add(t.name),validateType(t.identifier,!1);let n=/* @__PURE__ */ new Set;for(let r of t.streams){n.has(r.name)&&c.error(e.InvalidEventSourceDeclaration,`Stream '${t.name}.${r.name}' has multiple declarations under this source.`,r.location),n.add(r.name),validateType(r.streamId,!0);let i=r.streamIdParts;if(i.length>0){i.length<2&&c.error(e.InvalidEventSourceDeclaration,`A composite stream id requires at least two named parts.`,r.directiveLocations?.streamId??r.location);for(let t of new Set(i.map(e=>e.name)))for(let n of i.filter(e=>e.name===t).slice(1))c.error(e.InvalidEventSourceDeclaration,`Stream id part '${n.name}' is declared more than once.`,n.location);for(let e of i)validateType(e.type,!0)}}}let pathProperty=(e,t)=>{let[n,...r]=t.split(`.`);if(e===null)return{property:null,missing:!1};let i=e.filter(e=>e.name===n);if(i.length!==1)return{property:null,missing:i.length===0};let a=i[0];if(r.length===0)return{property:a,missing:!1};if(f.has(a.type.name)||l.has(a.type.name)&&!p.has(a.type.name))return{property:null,missing:!0};let o=pathProperty(p.get(a.type.name)?.properties??null,r.join(`.`));return o.property===null?o:{property:{...o.property,type:{...o.property.type,isCollection:a.type.isCollection||o.property.type.isCollection,isOptional:a.type.isOptional||o.property.type.isOptional}},missing:!1}},_=new n(s),v=new t(s);for(let{slice:t}of v.slices)for(let n of t.commands){let i=n.stream;if(i==null||i.propertyCandidate!==null)continue;let d=_.resolve(i.eventSource,i.stream);if(d.kind!==`unique`){let t={ambiguous:`Ambiguous`,notFound:`NotFound`,wrongKind:`WrongKind`}[d.kind];c.error(e.InvalidCommandStream,`Stream '${i.eventSource}.${i.stream}' is ${t}; routing requires one physical source and stream.`,i.location);continue}let p=d.sources[0],m=d.streams[0],g=n.properties.filter(e=>e.isIdentifier);p.identifier!==null&&g.length===1&&compatible(g[0].type,p.identifier)===!1&&c.error(e.InvalidCommandStream,`Command identifier '${g[0].name}' does not have the source's nominal identifier type '${p.identifier.name}'. The stream does not supply a destination.`,g[0].location);for(let r of n.produces.filter(e=>v.isEventProduction(e,t))){if(p.identifier===null)continue;let i=a(n,r,s,{resolver:v,slice:t});if(i===null||r.for===null&&r.inlineEvent!==null&&g.length===1&&compatible(g[0].type,p.identifier)===!1)continue;let o=r.for===null&&r.inlineEvent===null&&!n.properties.some(e=>e.isGenerated&&e.isIdentifier),u=l.get(p.identifier.name)?.type??(f.has(p.identifier.name)?p.identifier.name:null);(o?u===null?null:u===`Uuid`:compatible(i,p.identifier))===!1&&c.error(e.InvalidCommandStream,`Command production destination does not have the source's nominal identifier type '${p.identifier.name}'. The stream does not supply a destination.`,r.for?.location??r.location)}let validateMapping=(t,i)=>{let a=t.source;if(a.kind===`PathExpressionSyntax`){let t=pathProperty(n.properties,a.path);(t.missing||t.property!==null&&compatible(t.property.type,i)===!1)&&c.error(e.InvalidCommandStream,`Stream id source '${a.path}' is absent or incompatible with nominal type '${i.name}'.`,a.location)}else if(a.kind===`LiteralExpressionSyntax`&&a.value!==null){let t=formatStreamIdLiteral(a,i,s);t?.failure==null?r(a,i,l,h)||c.error(e.InvalidCommandStream,`Stream id value is incompatible with nominal type '${i.name}'.`,a.location):c.error(e.InvalidCommandStream,o(t.failure),a.location)}else([`RawExpressionSyntax`,`ObjectExpressionSyntax`,`ListExpressionSyntax`].includes(a.kind)||a.kind===`LiteralExpressionSyntax`&&a.value===null)&&c.error(e.InvalidCommandStream,`A stream id needs a scalar value source, not a raw expression, collection or absence.`,a.location)};m.streamIdParts.length>0?u(m,i.streamIdParts,i.streamId!==null,i.location,e.InvalidCommandStream,c,validateMapping):i.streamIdParts.length>0?c.error(e.InvalidCommandStream,`A streamId part block requires a composite stream.`,i.location):((m.streamId===null&&i.streamId!==null||m.streamId!==null&&i.streamId===null)&&c.error(e.InvalidCommandStream,m.streamId===null?`An unkeyed stream cannot take a streamId mapping.`:`This keyed stream requires a streamId mapping.`,i.location),m.streamId!==null&&i.streamId!==null&&validateMapping(i.streamId,m.streamId))}d(s,c)}export{formatStreamIdLiteral,supportsStreamIdentity,validateEventSources};
|
|
2
|
+
//# sourceMappingURL=EventSourceValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventSourceValidator.js","names":["primitives","concepts","application","concept","type","primitive","expression","value","uniqueByName","tryFormatUuidText","tryFormatText","tryFormatInteger","composites","known","compositeProperties","name","source","target","composite","context","DiagnosticCodes","named","streamId","imported","names","streams","stream","parts","part","duplicate","remaining","path","properties","matches","property","resolved","catalog","EventSourceCatalog","resolver","AuthoringProductionResolver","command","slice","route","resolution","state","identifiers","produced","destination","commandDestinationType","allocated","mapping","formatted","compatibleValue","streamIdFailureMessage","validateStreamIdParts","validateSpecificationStreams"],"sources":["../../../../../../Compiler/Parsing/EventSourceValidator.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 { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { PropertySyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { EventSourceCatalog } from '../Syntax/EventSourceCatalog';\nimport { EventSourceResolutionKind } from '../Syntax/EventSources';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { ExpressionSyntax, PropertyMappingSyntax } from '../Syntax/Expressions';\nimport { StreamIdFormatResult, streamIdFailureMessage, tryFormatInteger, tryFormatText, tryFormatUuidText } from '../Syntax/StreamIdFormatter';\nimport { commandDestinationType } from './CommandDestinationTypes';\nimport { validateStreamIdParts } from './CompositeStreamIdValidator';\nimport { ParserContext } from './ParserContext';\nimport { compatibleValue, uniqueByName } from './ResponseValidator';\nimport { validateSpecificationStreams } from './SpecificationStreamValidator';\n\nconst primitives = new Set(['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime']);\n\nexport function supportsStreamIdentity(type: TypeRefSyntax, application: ApplicationSyntax): boolean {\n const concepts = application.concepts.filter(concept => concept.name === type.name);\n const primitive = concepts.length === 1 ? concepts[0].type : concepts.length === 0 && primitives.has(type.name) ? type.name : null;\n return primitive === 'String' || primitive === 'Uuid' || primitive === 'Int' && concepts.length === 1 && concepts[0].values.length === 0;\n}\n\nexport function formatStreamIdLiteral(expression: ExpressionSyntax | null | undefined, type: TypeRefSyntax | null, application: ApplicationSyntax): StreamIdFormatResult | null {\n if (expression?.kind !== 'LiteralExpressionSyntax') return null;\n const value = expression.value;\n const primitive = type === null ? null : uniqueByName(application.concepts).get(type.name)?.type ?? type.name;\n if (typeof value === 'string') return primitive === 'Uuid' ? tryFormatUuidText(value) : tryFormatText(value);\n if (typeof value === 'number') return tryFormatInteger(value);\n if (typeof value === 'object' && value !== null && value.literalType === 'ExactNumber') {\n if (value.value.includes('.')) return tryFormatInteger(NaN);\n return tryFormatInteger(BigInt(value.value), false);\n }\n return null;\n}\n\nexport function validateEventSources(application: ApplicationSyntax, context: ParserContext): void {\n const concepts = uniqueByName(application.concepts);\n const composites = uniqueByName(application.types);\n const known = new Set([...primitives, ...concepts.keys(), ...composites.keys()]);\n const compositeProperties = new Map([...composites].map(([name, type]) => [name, uniqueByName(type.properties)]));\n const compatible = (source: TypeRefSyntax, target: TypeRefSyntax): boolean | null => known.has(source.name) && known.has(target.name)\n ? source.name === target.name && source.isCollection === target.isCollection && (!source.isOptional || target.isOptional) : null;\n const validateType = (type: TypeRefSyntax | null, streamId: boolean): void => {\n if (type === null) return;\n if (type.isOptional || type.isCollection || application.types.some(composite => composite.name === type.name)) {\n context.error(DiagnosticCodes.InvalidEventSourceDeclaration, 'Identifier and streamId declarations require a nonoptional scalar value type.', type.location);\n return;\n }\n const named = application.concepts.filter(concept => concept.name === type.name);\n const primitive = named.length === 1 ? named[0].type : named.length === 0 && primitives.has(type.name) ? type.name : null;\n if (streamId && primitive !== null && !supportsStreamIdentity(type, application))\n context.error(DiagnosticCodes.UnsupportedStreamIdType, 'Stream ids support text and UUID values and their nominal concepts, plus integer-backed concepts; other types need a future portable formatter.', type.location);\n if (primitive === null && !application.imports.some(imported => imported.qualifiedName === type.name || imported.qualifiedName.split('.').at(-1) === type.name))\n context.warning(DiagnosticCodes.UnknownType, `Unknown type '${type.name}' in event source declaration.`, type.location);\n };\n const names = new Set<string>();\n for (const source of application.eventSources ?? []) {\n if (names.has(source.name)) context.error(DiagnosticCodes.InvalidEventSourceDeclaration, `Event source '${source.name}' has multiple physical declarations.`, source.location);\n names.add(source.name);\n validateType(source.identifier, false);\n const streams = new Set<string>();\n for (const stream of source.streams) {\n if (streams.has(stream.name)) context.error(DiagnosticCodes.InvalidEventSourceDeclaration, `Stream '${source.name}.${stream.name}' has multiple declarations under this source.`, stream.location);\n streams.add(stream.name);\n validateType(stream.streamId, true);\n const parts = stream.streamIdParts;\n if (parts.length > 0) {\n if (parts.length < 2) context.error(DiagnosticCodes.InvalidEventSourceDeclaration, 'A composite stream id requires at least two named parts.', stream.directiveLocations?.streamId ?? stream.location);\n for (const name of new Set(parts.map(part => part.name))) {\n for (const duplicate of parts.filter(part => part.name === name).slice(1))\n context.error(DiagnosticCodes.InvalidEventSourceDeclaration, `Stream id part '${duplicate.name}' is declared more than once.`, duplicate.location);\n }\n for (const part of parts) validateType(part.type, true);\n }\n }\n }\n const pathProperty = (properties: readonly PropertySyntax[] | null, path: string): { property: PropertySyntax | null; missing: boolean } => {\n const [name, ...remaining] = path.split('.');\n if (properties === null) return { property: null, missing: false };\n const matches = properties.filter(property => property.name === name);\n if (matches.length !== 1) return { property: null, missing: matches.length === 0 };\n const property = matches[0];\n if (remaining.length === 0) return { property, missing: false };\n if (primitives.has(property.type.name) || concepts.has(property.type.name) && !composites.has(property.type.name)) return { property: null, missing: true };\n const resolved = pathProperty(composites.get(property.type.name)?.properties ?? null, remaining.join('.'));\n return resolved.property === null ? resolved : { property: { ...resolved.property, type: { ...resolved.property.type, isCollection: property.type.isCollection || resolved.property.type.isCollection, isOptional: property.type.isOptional || resolved.property.type.isOptional } }, missing: false };\n };\n const catalog = new EventSourceCatalog(application);\n const resolver = new AuthoringProductionResolver(application);\n for (const { slice } of resolver.slices) for (const command of slice.commands) {\n const route = command.stream;\n if (route == null || route.propertyCandidate !== null) continue;\n const resolution = catalog.resolve(route.eventSource, route.stream);\n if (resolution.kind !== EventSourceResolutionKind.Unique) {\n const state = { ambiguous: 'Ambiguous', notFound: 'NotFound', wrongKind: 'WrongKind' }[resolution.kind];\n context.error(DiagnosticCodes.InvalidCommandStream, `Stream '${route.eventSource}.${route.stream}' is ${state}; routing requires one physical source and stream.`, route.location);\n continue;\n }\n const source = resolution.sources[0];\n const stream = resolution.streams[0];\n const identifiers = command.properties.filter(property => property.isIdentifier);\n if (source.identifier !== null && identifiers.length === 1 && compatible(identifiers[0].type, source.identifier) === false)\n context.error(DiagnosticCodes.InvalidCommandStream, `Command identifier '${identifiers[0].name}' does not have the source's nominal identifier type '${source.identifier.name}'. The stream does not supply a destination.`, identifiers[0].location);\n for (const produced of command.produces.filter(produced => resolver.isEventProduction(produced, slice))) {\n if (source.identifier === null) continue;\n const destination = commandDestinationType(command, produced, application, { resolver, slice });\n if (destination === null) continue;\n if (produced.for === null && produced.inlineEvent !== null && identifiers.length === 1 && compatible(identifiers[0].type, source.identifier) === false) continue;\n const allocated = produced.for === null && produced.inlineEvent === null && !command.properties.some(property => property.isGenerated && property.isIdentifier);\n const primitive = concepts.get(source.identifier.name)?.type ?? (primitives.has(source.identifier.name) ? source.identifier.name : null);\n const matches = allocated ? primitive === null ? null : primitive === 'Uuid' : compatible(destination, source.identifier);\n if (matches === false) context.error(DiagnosticCodes.InvalidCommandStream, `Command production destination does not have the source's nominal identifier type '${source.identifier.name}'. The stream does not supply a destination.`, produced.for?.location ?? produced.location);\n }\n const validateMapping = (mapping: PropertyMappingSyntax, target: TypeRefSyntax): void => {\n const expression = mapping.source;\n if (expression.kind === 'PathExpressionSyntax') {\n const resolved = pathProperty(command.properties, expression.path);\n if (resolved.missing || resolved.property !== null && compatible(resolved.property.type, target) === false)\n context.error(DiagnosticCodes.InvalidCommandStream, `Stream id source '${expression.path}' is absent or incompatible with nominal type '${target.name}'.`, expression.location);\n } else if (expression.kind === 'LiteralExpressionSyntax' && expression.value !== null) {\n const formatted = formatStreamIdLiteral(expression, target, application);\n if (formatted?.failure != null) context.error(DiagnosticCodes.InvalidCommandStream, streamIdFailureMessage(formatted.failure), expression.location);\n else if (!compatibleValue(expression, target, concepts, compositeProperties)) context.error(DiagnosticCodes.InvalidCommandStream, `Stream id value is incompatible with nominal type '${target.name}'.`, expression.location);\n } else if (['RawExpressionSyntax', 'ObjectExpressionSyntax', 'ListExpressionSyntax'].includes(expression.kind) || expression.kind === 'LiteralExpressionSyntax' && expression.value === null)\n context.error(DiagnosticCodes.InvalidCommandStream, 'A stream id needs a scalar value source, not a raw expression, collection or absence.', expression.location);\n };\n if (stream.streamIdParts.length > 0) {\n validateStreamIdParts(stream, route.streamIdParts, route.streamId !== null, route.location, DiagnosticCodes.InvalidCommandStream, context, validateMapping);\n continue;\n }\n if (route.streamIdParts.length > 0) {\n context.error(DiagnosticCodes.InvalidCommandStream, 'A streamId part block requires a composite stream.', route.location);\n continue;\n }\n if (stream.streamId === null && route.streamId !== null || stream.streamId !== null && route.streamId === null)\n context.error(DiagnosticCodes.InvalidCommandStream, stream.streamId === null ? 'An unkeyed stream cannot take a streamId mapping.' : 'This keyed stream requires a streamId mapping.', route.location);\n if (stream.streamId === null || route.streamId === null) continue;\n validateMapping(route.streamId, stream.streamId);\n }\n validateSpecificationStreams(application, context);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{eventDeclarations as t}from"../Syntax/EventDeclarations.js";import{AuthoringProductionResolver as n}from"../Syntax/AuthoringProductionResolver.js";import{supportsStreamIdentity as r}from"./EventSourceValidator.js";function validateEventSubjects(i,a){let refuse=(t,n)=>{for(let r of t.filter(e=>e.isSubject))a.error(e.InvalidSubjectOwner,`The subject modifier is only valid on event properties, not ${n} properties (decision 0008: one data subject per event).`,r.location)};for(let e of i.types)refuse(e.properties,`type`);for(let{slice:o}of new n(i).slices){for(let e of o.commands)refuse(e.properties,`command`);for(let t of o.readModels)for(let n of t.properties.filter(e=>e.isSubject))a.error(e.ReadModelSubjectNotSupported,`Read model subject marks are not yet supported. Chronicle resolves read model subjects and reserves _subject, __subject and __subjects; Screenplay support is tracked in #559.`,n.location);for(let n of t(o)){let t=n.properties.filter(e=>e.isSubject);for(let r of t.slice(1))a.error(e.DuplicateEventSubject,`Event '${n.name}' has one data subject (decision 0008); '${r.name}' is an extra mark after '${t[0].name}'. Choose one subject; no automatic repair is safe.`,r.location);for(let n of t){let t=n.type;if(t.isOptional){a.error(e.InvalidSubjectType,`A subject must be required: a null value silently falls back to the event source.`,n.location);continue}if(t.isCollection||i.types.some(e=>e.name===t.name)){a.error(e.InvalidSubjectType,`A subject must be a scalar identity, not a collection or composite type.`,n.location);continue}let o=i.concepts.filter(e=>e.name===t.name);o.some(e=>e.attributes.some(e=>[`pii`,`sensitive`].includes(e.name)))&&a.error(e.ProtectedSubjectType,`Subject concept '${t.name}' is pii or secret. EventContext.Subject is stored in plaintext; use a surrogate Uuid identity.`,n.location);let s=o.length===1?o[0].type:o.length===0&&[`String`,`Uuid`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`].includes(t.name)?t.name:null;o.length===0&&s===null&&i.imports.some(e=>e.qualifiedName===t.name||e.qualifiedName.split(`.`).at(-1)===t.name)&&a.warning(e.UnknownType,`Unknown type shape '${t.name}' for subject property '${n.name}'; imported subject identity rules cannot be verified.`,n.location),(o.some(e=>e.type===`Enum`)||s!==null&&!r(t,i))&&a.error(e.InvalidSubjectType,`Subjects support String, Uuid and their concepts, plus Int-backed concepts; bare Int, enums, Decimal, Bool, Date and DateTime are refused.`,n.location)}}}}export{validateEventSubjects};
|
|
2
|
+
//# sourceMappingURL=EventSubjectValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventSubjectValidator.js","names":["property","properties","context","DiagnosticCodes","owner","type","application","AuthoringProductionResolver","command","slice","model","event","eventDeclarations","subjects","extra","composite","concepts","concept","attribute","primitive","imported","supportsStreamIdentity"],"sources":["../../../../../../Compiler/Parsing/EventSubjectValidator.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 { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { PropertySyntax } from '../Syntax/Declarations';\nimport { eventDeclarations } from '../Syntax/EventDeclarations';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { supportsStreamIdentity } from './EventSourceValidator';\nimport { ParserContext } from './ParserContext';\n\nexport function validateEventSubjects(application: ApplicationSyntax, context: ParserContext): void {\n const refuse = (properties: readonly PropertySyntax[], owner: string): void => {\n for (const property of properties.filter(property => property.isSubject))\n context.error(DiagnosticCodes.InvalidSubjectOwner, `The subject modifier is only valid on event properties, not ${owner} properties (decision 0008: one data subject per event).`, property.location);\n };\n for (const type of application.types) refuse(type.properties, 'type');\n for (const { slice } of new AuthoringProductionResolver(application).slices) {\n for (const command of slice.commands) refuse(command.properties, 'command');\n for (const model of slice.readModels) for (const property of model.properties.filter(property => property.isSubject))\n context.error(DiagnosticCodes.ReadModelSubjectNotSupported, 'Read model subject marks are not yet supported. Chronicle resolves read model subjects and reserves _subject, __subject and __subjects; Screenplay support is tracked in #559.', property.location);\n for (const event of eventDeclarations(slice)) {\n const subjects = event.properties.filter(property => property.isSubject);\n for (const extra of subjects.slice(1))\n context.error(DiagnosticCodes.DuplicateEventSubject, `Event '${event.name}' has one data subject (decision 0008); '${extra.name}' is an extra mark after '${subjects[0].name}'. Choose one subject; no automatic repair is safe.`, extra.location);\n for (const property of subjects) {\n const type = property.type;\n if (type.isOptional) {\n context.error(DiagnosticCodes.InvalidSubjectType, 'A subject must be required: a null value silently falls back to the event source.', property.location);\n continue;\n }\n if (type.isCollection || application.types.some(composite => composite.name === type.name)) {\n context.error(DiagnosticCodes.InvalidSubjectType, 'A subject must be a scalar identity, not a collection or composite type.', property.location);\n continue;\n }\n const concepts = application.concepts.filter(concept => concept.name === type.name);\n if (concepts.some(concept => concept.attributes.some(attribute => ['pii', 'sensitive'].includes(attribute.name))))\n context.error(DiagnosticCodes.ProtectedSubjectType, `Subject concept '${type.name}' is pii or secret. EventContext.Subject is stored in plaintext; use a surrogate Uuid identity.`, property.location);\n const primitive = concepts.length === 1 ? concepts[0].type : concepts.length === 0 && ['String', 'Uuid', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime'].includes(type.name) ? type.name : null;\n if (concepts.length === 0 && primitive === null && application.imports.some(imported => imported.qualifiedName === type.name || imported.qualifiedName.split('.').at(-1) === type.name))\n context.warning(DiagnosticCodes.UnknownType, `Unknown type shape '${type.name}' for subject property '${property.name}'; imported subject identity rules cannot be verified.`, property.location);\n if (concepts.some(concept => concept.type === 'Enum') || primitive !== null && !supportsStreamIdentity(type, application))\n context.error(DiagnosticCodes.InvalidSubjectType, 'Subjects support String, Uuid and their concepts, plus Int-backed concepts; bare Int, enums, Decimal, Bool, Date and DateTime are refused.', property.location);\n }\n }\n }\n}\n"],"mappings":"sVAWA,SAAgB,sBAAsB,EAAgC,EAA8B,CAChG,IAAM,QAAU,EAAuC,IAAwB,CAC3E,IAAK,IAAMA,KAAYC,EAAW,OAAO,GAAYD,EAAS,SAAS,EACnEE,EAAQ,MAAMC,EAAgB,oBAAqB,+DAA+DC,EAAM,0DAA2DJ,EAAS,QAAQ,CAC5M,EACA,IAAK,IAAMK,KAAQC,EAAY,MAAO,OAAOD,EAAK,WAAY,MAAM,EACpE,IAAK,GAAM,CAAE,WAAW,IAAIE,EAA4BD,CAAW,CAAC,CAAC,OAAQ,CACzE,IAAK,IAAME,KAAWC,EAAM,SAAU,OAAOD,EAAQ,WAAY,SAAS,EAC1E,IAAK,IAAME,KAASD,EAAM,WAAY,IAAK,IAAMT,KAAYU,EAAM,WAAW,OAAO,GAAYV,EAAS,SAAS,EAC/GE,EAAQ,MAAMC,EAAgB,6BAA8B,iLAAkLH,EAAS,QAAQ,EACnQ,IAAK,IAAMW,KAASC,EAAkBH,CAAK,EAAG,CAC1C,IAAMI,EAAWF,EAAM,WAAW,OAAO,GAAYX,EAAS,SAAS,EACvE,IAAK,IAAMc,KAASD,EAAS,MAAM,CAAC,EAChCX,EAAQ,MAAMC,EAAgB,sBAAuB,UAAUQ,EAAM,KAAK,2CAA2CG,EAAM,KAAK,4BAA4BD,EAAS,EAAE,CAAC,KAAK,qDAAsDC,EAAM,QAAQ,EACrP,IAAK,IAAMd,KAAYa,EAAU,CAC7B,IAAMR,EAAOL,EAAS,KACtB,GAAIK,EAAK,WAAY,CACjBH,EAAQ,MAAMC,EAAgB,mBAAoB,oFAAqFH,EAAS,QAAQ,EACxJ,QACJ,CACA,GAAIK,EAAK,cAAgBC,EAAY,MAAM,KAAK,GAAaS,EAAU,OAASV,EAAK,IAAI,EAAG,CACxFH,EAAQ,MAAMC,EAAgB,mBAAoB,2EAA4EH,EAAS,QAAQ,EAC/I,QACJ,CACA,IAAMgB,EAAWV,EAAY,SAAS,OAAO,GAAWW,EAAQ,OAASZ,EAAK,IAAI,EAC9EW,EAAS,KAAK,GAAWC,EAAQ,WAAW,KAAK,GAAa,CAAC,MAAO,WAAW,CAAC,CAAC,SAASC,EAAU,IAAI,CAAC,CAAC,GAC5GhB,EAAQ,MAAMC,EAAgB,qBAAsB,oBAAoBE,EAAK,KAAK,iGAAkGL,EAAS,QAAQ,EACzM,IAAMmB,EAAYH,EAAS,SAAW,EAAIA,EAAS,EAAE,CAAC,KAAOA,EAAS,SAAW,GAAK,CAAC,SAAU,OAAQ,MAAO,UAAW,OAAQ,OAAQ,UAAU,CAAC,CAAC,SAASX,EAAK,IAAI,EAAIA,EAAK,KAAO,KACrLW,EAAS,SAAW,GAAKG,IAAc,MAAQb,EAAY,QAAQ,KAAK,GAAYc,EAAS,gBAAkBf,EAAK,MAAQe,EAAS,cAAc,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,IAAMf,EAAK,IAAI,GAClLH,EAAQ,QAAQC,EAAgB,YAAa,uBAAuBE,EAAK,KAAK,0BAA0BL,EAAS,KAAK,wDAAyDA,EAAS,QAAQ,GAChMgB,EAAS,KAAK,GAAWC,EAAQ,OAAS,MAAM,GAAKE,IAAc,MAAQ,CAACE,EAAuBhB,EAAMC,CAAW,IACpHJ,EAAQ,MAAMC,EAAgB,mBAAoB,6IAA8IH,EAAS,QAAQ,CACzN,CACJ,CACJ,CACJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{nativePattern as t,pattern as n}from"../Text/patterns.js";import{isExactNumberToken as r,parseExactNumber as i}from"../Syntax/ExactNumber.js";import{unescapeString as a}from"../Text/StringLiteral.js";import{InvalidStructuredValue as o,StructuredValueParser as s}from"./StructuredValueParser.js";const c=n(`^@?[A-Za-z_]\\w*(\\.@?[A-Za-z_$]\\w*)*$`),l=t(`^@?[A-Za-z_]\\w*(\\.@?[A-Za-z_$]\\w*)*$`),u=n(`^-?\\d+(\\.\\d+)?$`),d=[`command`,`arguments`,`tenant`,`causedBy`,`causation`,`occurred`,`identity`],f=[`subject`,`name`,`userName`],p=[`id`,`name`,`userName`,`isAuthenticated`,`roles`,`claims`];function parseModeledMappingSource(e,t,n){return parseMappingSource(e,t,n,!0)}function parseMappingSource(t,n,r,i=!1){if(t=t.trim(),t===`$refusal`||t.startsWith(`$refusal.`))return{kind:`RefusalExpressionSyntax`,member:t===`$refusal`?``:t.substring(9),location:n};if(t===`$identity`||t===`$identity.`)return r?.error(e.InvalidExpression,`Invalid expression '${t}'`,n),{kind:`RawExpressionSyntax`,text:t,location:n};if(t.startsWith(`$identity.`)){let e=t.substring(10);return r?.deferIdentityValidation!==!0&&warnOnUnknownIdentityProperty(e.split(`.`)[0],`$identity`,n,r),{kind:`IdentityExpressionSyntax`,path:e,location:n}}if(t.startsWith(`$context.`)){let e=t.substring(9);return warnOnUnknownContextPath(e,n,r),{kind:`ContextExpressionSyntax`,path:e,location:n}}if(t.startsWith(`$env.`))return{kind:`EnvironmentExpressionSyntax`,name:t.substring(5),location:n};if(t.startsWith(`$strings.`))return{kind:`StringsExpressionSyntax`,key:t.substring(9),location:n};if(t.startsWith(`$.`))return{kind:`SourceItemExpressionSyntax`,path:t.substring(2),location:n};if(t.startsWith(`{`)||t.startsWith(`[`))try{return new s(t,n,r).parse()}catch(i){if(!(i instanceof o))throw i;return r?.error(e.InvalidStructuredValue,`Invalid inline structured value: ${i.message}`,n),{kind:`RawExpressionSyntax`,text:t,location:n}}let a=r===void 0?parseLiteral(t,n):parseLiteral(t,n,r);return a===void 0?(i||r?.sourceOptions.numericMode===`exact`?l:c).test(t)?{kind:`PathExpressionSyntax`,path:t,location:n}:{kind:`RawExpressionSyntax`,text:t,location:n}:a}function warnOnUnknownContextPath(t,n,r){let[i,a]=t.split(`.`);d.includes(i)?a!==void 0&&i===`causedBy`&&!f.includes(a)?r?.warning(e.UnknownContextCausedByProperty,`Unknown $context.causedBy property '${a}' - expected ${f.join(`, `)}`,n):a!==void 0&&i===`identity`&&warnOnUnknownIdentityProperty(a,`$context.identity`,n,r):r?.warning(e.UnknownContextPath,`Unknown $context path '${t}' - expected one of ${d.join(`, `)}`,n)}function warnOnUnknownIdentityProperty(t,n,r,i){p.includes(t)||i?.warning(e.UnknownContextIdentityProperty,`Unknown ${n} property '${t}' - expected ${p.join(`, `)}`,r)}function parseLiteral(t,n,o){let literal=e=>({kind:`LiteralExpressionSyntax`,value:e,location:n});switch(t){case`true`:return literal(!0);case`false`:return literal(!1);case`null`:return literal(null)}if(t.length>=2&&(t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)))return literal(a(t.substring(1,t.length-1)));if(o?.sourceOptions.numericMode===`exact`){if(!r(t))return;let a=i(t);return a===void 0?(o.error(e.InexactNumericLiteral,`Numeric literal is not exactly representable in the bounded Decimal domain.`,n),{kind:`RawExpressionSyntax`,text:t,location:n}):literal(a)}if(u.test(t)&&!Number.isNaN(Number(t)))return literal(Number(t))}export{p as identityProperties,parseLiteral,parseMappingSource,parseModeledMappingSource};
|
|
2
|
+
//# sourceMappingURL=ExpressionParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ExpressionParser.js","names":["pathPattern","pattern","nativePathPattern","nativePattern","numberPattern","contextRoots","causedByProperties","identityProperties","text","location","context","DiagnosticCodes","path","StructuredValueParser","error","InvalidStructuredValue","literal","nativeIdentifiers","root","member","unescapeString","isExactNumberToken","number","parseExactNumber"],"sources":["../../../../../../Compiler/Parsing/ExpressionParser.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 { ExpressionSyntax, LiteralExpressionSyntax } from '../Syntax/Expressions';\nimport { ExactNumber, isExactNumberToken, parseExactNumber } from '../Syntax/ExactNumber';\nimport { nativePattern, pattern } from '../Text/patterns';\nimport { unescapeString } from '../Text/StringLiteral';\nimport { ParserContext } from './ParserContext';\nimport { InvalidStructuredValue, StructuredValueParser } from './StructuredValueParser';\n\nconst pathPattern = pattern('^@?[A-Za-z_]\\\\w*(\\\\.@?[A-Za-z_$]\\\\w*)*$');\nconst nativePathPattern = nativePattern('^@?[A-Za-z_]\\\\w*(\\\\.@?[A-Za-z_$]\\\\w*)*$');\nconst numberPattern = pattern('^-?\\\\d+(\\\\.\\\\d+)?$');\nconst contextRoots = ['command', 'arguments', 'tenant', 'causedBy', 'causation', 'occurred', 'identity'];\nconst causedByProperties = ['subject', 'name', 'userName'];\nexport const identityProperties = ['id', 'name', 'userName', 'isAuthenticated', 'roles', 'claims'];\n\n// Reads the right-hand side of a mapping or a rule operand - the port of the C# ExpressionParser's\n// ParseMappingSource. With a context it also reports what the C# compiler reports while reading one: an\n// unknown $context path, and an inline structured value that is not valid JSON.\nexport function parseModeledMappingSource(text: string, location: SourceLocation, context: ParserContext): ExpressionSyntax {\n return parseMappingSource(text, location, context, true);\n}\n\nexport function parseMappingSource(text: string, location: SourceLocation, context?: ParserContext, nativeIdentifiers = false): ExpressionSyntax {\n text = text.trim();\n if (text === '$refusal' || text.startsWith('$refusal.')) {\n return { kind: 'RefusalExpressionSyntax', member: text === '$refusal' ? '' : text.substring('$refusal.'.length), location };\n }\n if (text === '$identity' || text === '$identity.') {\n context?.error(DiagnosticCodes.InvalidExpression, `Invalid expression '${text}'`, location);\n return { kind: 'RawExpressionSyntax', text, location };\n }\n if (text.startsWith('$identity.')) {\n const path = text.substring('$identity.'.length);\n if (context?.deferIdentityValidation !== true) warnOnUnknownIdentityProperty(path.split('.')[0], '$identity', location, context);\n return { kind: 'IdentityExpressionSyntax', path, location };\n }\n if (text.startsWith('$context.')) {\n const path = text.substring('$context.'.length);\n warnOnUnknownContextPath(path, location, context);\n return { kind: 'ContextExpressionSyntax', path, location };\n }\n if (text.startsWith('$env.')) {\n return { kind: 'EnvironmentExpressionSyntax', name: text.substring('$env.'.length), location };\n }\n if (text.startsWith('$strings.')) {\n return { kind: 'StringsExpressionSyntax', key: text.substring('$strings.'.length), location };\n }\n if (text.startsWith('$.')) {\n return { kind: 'SourceItemExpressionSyntax', path: text.substring('$.'.length), location };\n }\n if (text.startsWith('{') || text.startsWith('[')) {\n try {\n return new StructuredValueParser(text, location, context).parse();\n } catch (error) {\n if (!(error instanceof InvalidStructuredValue)) {\n throw error;\n }\n context?.error(DiagnosticCodes.InvalidStructuredValue, `Invalid inline structured value: ${error.message}`, location);\n return { kind: 'RawExpressionSyntax', text, location };\n }\n }\n const literal = context === undefined ? parseLiteral(text, location) : parseLiteral(text, location, context);\n if (literal !== undefined) {\n return literal;\n }\n if ((nativeIdentifiers || context?.sourceOptions.numericMode === 'exact' ? nativePathPattern : pathPattern).test(text)) {\n return { kind: 'PathExpressionSyntax', path: text, location };\n }\n return { kind: 'RawExpressionSyntax', text, location };\n}\n\nfunction warnOnUnknownContextPath(path: string, location: SourceLocation, context: ParserContext | undefined): void {\n const [root, member] = path.split('.');\n if (!contextRoots.includes(root)) {\n context?.warning(DiagnosticCodes.UnknownContextPath, `Unknown $context path '${path}' - expected one of ${contextRoots.join(', ')}`, location);\n } else if (member !== undefined && root === 'causedBy' && !causedByProperties.includes(member)) {\n context?.warning(DiagnosticCodes.UnknownContextCausedByProperty,\n `Unknown $context.causedBy property '${member}' - expected ${causedByProperties.join(', ')}`, location);\n } else if (member !== undefined && root === 'identity') {\n warnOnUnknownIdentityProperty(member, '$context.identity', location, context);\n }\n}\n\nfunction warnOnUnknownIdentityProperty(member: string, root: string, location: SourceLocation, context: ParserContext | undefined): void {\n if (!identityProperties.includes(member)) {\n context?.warning(DiagnosticCodes.UnknownContextIdentityProperty,\n `Unknown ${root} property '${member}' - expected ${identityProperties.join(', ')}`, location);\n }\n}\n\nexport function parseLiteral(text: string, location: SourceLocation): LiteralExpressionSyntax | undefined;\nexport function parseLiteral(text: string, location: SourceLocation, context: ParserContext): ExpressionSyntax | undefined;\nexport function parseLiteral(text: string, location: SourceLocation, context?: ParserContext): ExpressionSyntax | undefined {\n const literal = (value: string | number | boolean | null | ExactNumber): LiteralExpressionSyntax => ({ kind: 'LiteralExpressionSyntax', value, location });\n switch (text) {\n case 'true':\n return literal(true);\n case 'false':\n return literal(false);\n case 'null':\n return literal(null);\n }\n const quoted = text.length >= 2 && ((text.startsWith('\"') && text.endsWith('\"')) || (text.startsWith('\\'') && text.endsWith('\\'')));\n if (quoted) {\n return literal(unescapeString(text.substring(1, text.length - 1)));\n }\n if (context?.sourceOptions.numericMode === 'exact') {\n if (!isExactNumberToken(text)) return undefined;\n const number = parseExactNumber(text);\n if (number !== undefined) return literal(number);\n context.error(DiagnosticCodes.InexactNumericLiteral, 'Numeric literal is not exactly representable in the bounded Decimal domain.', location);\n return { kind: 'RawExpressionSyntax', text, location };\n }\n // .NET also parses digits from other scripts; JavaScript's Number does not, so such a number is left to\n // be read as raw text - a divergence no real document is expected to meet.\n if (numberPattern.test(text) && !Number.isNaN(Number(text))) {\n return literal(Number(text));\n }\n return undefined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{firstWord as n}from"./LineText.js";import{locationOf as r}from"./SourceLine.js";import{combineAuthorize as i,parseAuthorize as a}from"./AuthorizeParser.js";import{parseDescription as o}from"./DescriptionParser.js";import{parsePurposeReference as s}from"./PurposeParser.js";import{parseDocumentation as c}from"./DocumentationParser.js";import{parseDependsOn as l}from"./DependsOnParser.js";import{parseFileImport as u}from"./FileImportParser.js";import{collectInputUses as d}from"./InputUses.js";import{misplacedReactionIdentity as f}from"./ReactionIdentityParser.js";import{parseExample as p}from"./SpecificationExampleParser.js";import{parseSlice as m}from"./SliceParser.js";const h=t(`^feature\\s+([A-Za-z_]\\w*)$`),g=/* @__PURE__ */ new Set([`on`,`uses`,`contribute`]),_=`description, documentation, depends on <Name>, authorize, import, feature, slice, contribute, example, 'on <trigger>' or 'uses <Behavior>'`;var FeatureBody=class{name;#e=[];#t=[];#n=[];#r=[];#i=[];#a=[];#o=null;#s=null;#c=null;constructor(e){this.name=e}tryParse(t,r){let h=n(r.content);switch(h){case`runs`:return f(t,r),!0;case`description`:return this.#o=o(t,r,this.#o,`Feature '${this.name}'`),!0;case`documentation`:return this.#s=c(t,r,this.#s,`Feature '${this.name}'`),!0;case`depends`:return l(t,r,this.#i,e.UnknownFeatureDirective),!0;case`purpose`:return s(t,r,this.#a),!0;case`authorize`:return this.#c=i(this.#c,a(t,r)),!0;case`import`:return u(t,r,this.#r),!0;case`feature`:return this.#e.push(parseFeature(t,r)),!0;case`example`:return this.#n.push(p(t,r)),!0;case`slice`:return this.#t.push(m(t,r)),!0;default:return g.has(h)?(d(t,r),!0):!1}}build(e,t=!1){return{kind:`FeatureSyntax`,name:this.name,description:this.#o,documentation:this.#s,authorize:this.#c,dependsOn:this.#i,purposes:this.#a,features:this.#e,slices:this.#t,examples:this.#n,fileImports:this.#r,isPlacement:t,location:e}}};function parseFeature(t,i){let a=h.exec(i.content)?.[1]??``;a===``&&t.error(e.InvalidFeatureDeclaration,`Invalid feature declaration '${i.content}' - expected 'feature <Name>'`,r(i));let o=new FeatureBody(a),s=t.scope;t.scope=[...s,a];for(let a=t.peekChild(i.indent);a!==void 0;a=t.peekChild(i.indent))t.reader.takeSignificant(),o.tryParse(t,a)||(t.error(e.UnknownFeatureDirective,`Unexpected '${n(a.content)}' in feature body - expected ${_}`,r(a)),t.skipBlock(a.indent));return t.scope=s,o.build(r(i))}export{FeatureBody,_ as featureBodyExpected,parseFeature};
|
|
2
|
+
//# sourceMappingURL=FeatureBody.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureBody.js","names":["featurePattern","pattern","opaqueFeatureMembers","featureBodyExpected","name","keyword","firstWord","line","misplacedReactionIdentity","context","#description","parseDescription","#documentation","parseDocumentation","parseDependsOn","#dependsOn","DiagnosticCodes","parsePurposeReference","#purposes","#authorize","combineAuthorize","parseAuthorize","parseFileImport","#fileImports","#features","#examples","parseExample","#slices","parseSlice","collectInputUses","locationOf","body","previous","child"],"sources":["../../../../../../Compiler/Parsing/FeatureBody.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 { AuthorizeSyntax } from '../Syntax/Authorization';\nimport { SpecificationExampleSyntax } from '../Syntax/Specifications';\nimport { DependsOnSyntax, FeatureSyntax, FileImportSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { pattern } from '../Text/patterns';\nimport { combineAuthorize, parseAuthorize } from './AuthorizeParser';\nimport { parseDescription } from './DescriptionParser';\nimport { PurposeReferenceSyntax } from '../Syntax/Purposes';\nimport { parsePurposeReference } from './PurposeParser';\nimport { parseDocumentation } from './DocumentationParser';\nimport { parseDependsOn } from './DependsOnParser';\nimport { parseFileImport } from './FileImportParser';\nimport { collectInputUses } from './InputUses';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { misplacedReactionIdentity } from './ReactionIdentityParser';\nimport { parseExample } from './SpecificationExampleParser';\nimport { parseSlice } from './SliceParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst featurePattern = pattern('^feature\\\\s+([A-Za-z_]\\\\w*)$');\n\n// Feature members the C# compiler knows that this compiler does not model. They are skipped whole, not reported.\nconst opaqueFeatureMembers = new Set(['on', 'uses', 'contribute']);\n\n// What a feature body may hold, as it reads in a diagnostic.\nexport const featureBodyExpected = 'description, documentation, depends on <Name>, authorize, import, feature, slice, contribute, example, \\'on <trigger>\\' or \\'uses <Behavior>\\'';\n\n// Collects the body of a feature - written beneath a 'feature' header, or at the top level of a file imported\n// into the feature. The port of the C# FeatureBody.\nexport class FeatureBody {\n readonly #features: FeatureSyntax[] = [];\n readonly #slices: SliceSyntax[] = [];\n readonly #examples: SpecificationExampleSyntax[] = [];\n readonly #fileImports: FileImportSyntax[] = [];\n readonly #dependsOn: DependsOnSyntax[] = [];\n readonly #purposes: PurposeReferenceSyntax[] = [];\n #description: string | null = null;\n #documentation: string | null = null;\n #authorize: AuthorizeSyntax | null = null;\n\n constructor(readonly name: string) {}\n\n // Parses one already consumed line of the body; false when the line does not belong to a feature body,\n // and nothing was reported.\n tryParse(context: ParserContext, line: SourceLine): boolean {\n const keyword = firstWord(line.content);\n switch (keyword) {\n case 'runs':\n misplacedReactionIdentity(context, line);\n return true;\n case 'description':\n this.#description = parseDescription(context, line, this.#description, `Feature '${this.name}'`);\n return true;\n case 'documentation':\n this.#documentation = parseDocumentation(context, line, this.#documentation, `Feature '${this.name}'`);\n return true;\n case 'depends':\n parseDependsOn(context, line, this.#dependsOn, DiagnosticCodes.UnknownFeatureDirective);\n return true;\n case 'purpose':\n parsePurposeReference(context, line, this.#purposes);\n return true;\n case 'authorize':\n this.#authorize = combineAuthorize(this.#authorize, parseAuthorize(context, line));\n return true;\n case 'import':\n parseFileImport(context, line, this.#fileImports);\n return true;\n case 'feature':\n this.#features.push(parseFeature(context, line));\n return true;\n case 'example':\n this.#examples.push(parseExample(context, line));\n return true;\n case 'slice':\n this.#slices.push(parseSlice(context, line));\n return true;\n default:\n if (opaqueFeatureMembers.has(keyword)) {\n collectInputUses(context, line);\n return true;\n }\n return false;\n }\n }\n\n // Builds the feature, located at its header or, when it only places an imported file, at that file.\n build(location: SourceLocation, isPlacement = false): FeatureSyntax {\n return {\n kind: 'FeatureSyntax',\n name: this.name,\n description: this.#description,\n documentation: this.#documentation,\n authorize: this.#authorize,\n dependsOn: this.#dependsOn,\n purposes: this.#purposes,\n features: this.#features,\n slices: this.#slices,\n examples: this.#examples,\n fileImports: this.#fileImports,\n isPlacement,\n location,\n };\n }\n}\n\n// Parses a feature from its already consumed header line.\nexport function parseFeature(context: ParserContext, line: SourceLine): FeatureSyntax {\n const name = featurePattern.exec(line.content)?.[1] ?? '';\n if (name === '') {\n context.error(DiagnosticCodes.InvalidFeatureDeclaration, `Invalid feature declaration '${line.content}' - expected 'feature <Name>'`, locationOf(line));\n }\n const body = new FeatureBody(name);\n const previous = context.scope;\n context.scope = [...previous, name];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n if (!body.tryParse(context, child)) {\n context.error(DiagnosticCodes.UnknownFeatureDirective, `Unexpected '${firstWord(child.content)}' in feature body - expected ${featureBodyExpected}`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n context.scope = previous;\n return body.build(locationOf(line));\n}\n"],"mappings":"k1BAwBA,MAAMA,EAAiBC,EAAQ,8BAA8B,EAGvDC,kBAAuB,IAAI,IAAI,CAAC,KAAM,OAAQ,YAAY,CAAC,EAGpDC,EAAsB,6IAInC,IAAa,YAAb,KAAyB,CAWA,KAVrB,GAAsC,CAAC,EACvC,GAAkC,CAAC,EACnC,GAAmD,CAAC,EACpD,GAA4C,CAAC,EAC7C,GAAyC,CAAC,EAC1C,GAA+C,CAAC,EAChD,GAA8B,KAC9B,GAAgC,KAChC,GAAqC,KAErC,YAAY,EAAuB,CAAd,KAAA,KAAAC,CAAe,CAIpC,SAAS,EAAwB,EAA2B,CACxD,IAAMC,EAAUC,EAAUC,EAAK,OAAO,EACtC,OAAQF,EAAR,CACI,IAAK,OAED,OADAG,EAA0BC,EAASF,CAAI,EAChC,GACX,IAAK,cAED,MADA,MAAKG,GAAeC,EAAiBF,EAASF,EAAM,KAAKG,GAAc,YAAY,KAAK,KAAK,EAAE,EACxF,GACX,IAAK,gBAED,MADA,MAAKE,GAAiBC,EAAmBJ,EAASF,EAAM,KAAKK,GAAgB,YAAY,KAAK,KAAK,EAAE,EAC9F,GACX,IAAK,UAED,OADAE,EAAeL,EAASF,EAAM,KAAKQ,GAAYC,EAAgB,uBAAuB,EAC/E,GACX,IAAK,UAED,OADAC,EAAsBR,EAASF,EAAM,KAAKW,EAAS,EAC5C,GACX,IAAK,YAED,MADA,MAAKC,GAAaC,EAAiB,KAAKD,GAAYE,EAAeZ,EAASF,CAAI,CAAC,EAC1E,GACX,IAAK,SAED,OADAe,EAAgBb,EAASF,EAAM,KAAKgB,EAAY,EACzC,GACX,IAAK,UAED,OADA,KAAKC,GAAU,KAAK,aAAaf,EAASF,CAAI,CAAC,EACxC,GACX,IAAK,UAED,OADA,KAAKkB,GAAU,KAAKC,EAAajB,EAASF,CAAI,CAAC,EACxC,GACX,IAAK,QAED,OADA,KAAKoB,GAAQ,KAAKC,EAAWnB,EAASF,CAAI,CAAC,EACpC,GACX,QAKI,OAJIL,EAAqB,IAAIG,CAAO,GAChCwB,EAAiBpB,EAASF,CAAI,EACvB,IAEJ,EACf,CACJ,CAGA,MAAM,EAA0B,EAAc,GAAsB,CAChE,MAAO,CACH,KAAM,gBACN,KAAM,KAAK,KACX,YAAa,KAAKG,GAClB,cAAe,KAAKE,GACpB,UAAW,KAAKO,GAChB,UAAW,KAAKJ,GAChB,SAAU,KAAKG,GACf,SAAU,KAAKM,GACf,OAAQ,KAAKG,GACb,SAAU,KAAKF,GACf,YAAa,KAAKF,GAClB,cACA,UACJ,CACJ,CACJ,EAGA,SAAgB,aAAa,EAAwB,EAAiC,CAClF,IAAMnB,EAAOJ,EAAe,KAAKO,EAAK,OAAO,CAAC,GAAG,IAAM,GACnDH,IAAS,IACTK,EAAQ,MAAMO,EAAgB,0BAA2B,gCAAgCT,EAAK,QAAQ,+BAAgCuB,EAAWvB,CAAI,CAAC,EAE1J,IAAMwB,EAAO,IAAI,YAAY3B,CAAI,EAC3B4B,EAAWvB,EAAQ,MACzB,EAAQ,MAAQ,CAAC,GAAGuB,EAAU5B,CAAI,EAClC,IAAK,IAAI6B,EAAQxB,EAAQ,UAAUF,EAAK,MAAM,EAAG0B,IAAU,IAAA,GAAW,EAAQxB,EAAQ,UAAUF,EAAK,MAAM,EACvGE,EAAQ,OAAO,gBAAgB,EAC1BsB,EAAK,SAAStB,EAASwB,CAAK,IAC7BxB,EAAQ,MAAMO,EAAgB,wBAAyB,eAAeV,EAAU2B,EAAM,OAAO,EAAE,+BAA+B9B,IAAuB2B,EAAWG,CAAK,CAAC,EACtKxB,EAAQ,UAAUwB,EAAM,MAAM,GAItC,MADA,GAAQ,MAAQD,EACTD,EAAK,MAAMD,EAAWvB,CAAI,CAAC,CACtC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{locationOf as n}from"./SourceLine.js";const r=t(`^import\\s+"([^"\\\\]+)"$`),i=t(`^import\\s+"`),isFileImport=e=>i.test(e);function tryParseFileImport(e){let t=r.exec(e.content);return t===null?void 0:{kind:`FileImportSyntax`,pattern:t[1],location:n(e)}}function parseFileImport(t,r,i){let a=tryParseFileImport(r);a===void 0?(t.error(e.InvalidFileImport,`Invalid import '${r.content}' - inside a module or feature, import names files: 'import "<path or glob>"'`,n(r)),t.skipBlock(r.indent)):i.push(a)}export{isFileImport,parseFileImport,tryParseFileImport};
|
|
2
|
+
//# sourceMappingURL=FileImportParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileImportParser.js","names":["fileImportPattern","pattern","quotedPattern","content","match","line","locationOf","fileImport","context","DiagnosticCodes","imports"],"sources":["../../../../../../Compiler/Parsing/FileImportParser.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 { FileImportSyntax } from '../Syntax/Structure';\nimport { pattern } from '../Text/patterns';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst fileImportPattern = pattern('^import\\\\s+\"([^\"\\\\\\\\]+)\"$');\nconst quotedPattern = pattern('^import\\\\s+\"');\n\n// Whether an 'import' line names files rather than a qualified name - its operand is quoted.\nexport const isFileImport = (content: string): boolean => quotedPattern.test(content);\n\n// An 'import \"<pattern>\"' line, or undefined when the line does not import files - the port of the C#\n// FileImportParser.TryParse.\nexport function tryParseFileImport(line: SourceLine): FileImportSyntax | undefined {\n const match = fileImportPattern.exec(line.content);\n return match === null ? undefined : { kind: 'FileImportSyntax', pattern: match[1], location: locationOf(line) };\n}\n\n// Parses a consumed 'import' line inside a module or feature, where only files can be imported.\nexport function parseFileImport(context: ParserContext, line: SourceLine, imports: FileImportSyntax[]): void {\n const fileImport = tryParseFileImport(line);\n if (fileImport !== undefined) {\n imports.push(fileImport);\n return;\n }\n context.error(DiagnosticCodes.InvalidFileImport,\n `Invalid import '${line.content}' - inside a module or feature, import names files: 'import \"<path or glob>\"'`, locationOf(line));\n context.skipBlock(line.indent);\n}\n"],"mappings":"oNASA,MAAMA,EAAoBC,EAAQ,2BAA2B,EACvDC,EAAgBD,EAAQ,cAAc,EAG/B,aAAgB,GAA6BC,EAAc,KAAKC,CAAO,EAIpF,SAAgB,mBAAmB,EAAgD,CAC/E,IAAMC,EAAQJ,EAAkB,KAAKK,EAAK,OAAO,EACjD,OAAOD,IAAU,KAAO,IAAA,GAAY,CAAE,KAAM,mBAAoB,QAASA,EAAM,GAAI,SAAUE,EAAWD,CAAI,CAAE,CAClH,CAGA,SAAgB,gBAAgB,EAAwB,EAAkB,EAAmC,CACzG,IAAME,EAAa,mBAAmBF,CAAI,EACtCE,IAAe,IAAA,IAInBC,EAAQ,MAAMC,EAAgB,kBAC1B,mBAAmBJ,EAAK,QAAQ,+EAAgFC,EAAWD,CAAI,CAAC,EACpIG,EAAQ,UAAUH,EAAK,MAAM,GALzBK,EAAQ,KAAKH,CAAU,CAM/B"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{pattern as e}from"../Text/patterns.js";import{firstWord as t}from"./LineText.js";const n=e(`^[A-Za-z_]\\w*(?:\\[\\])?(?:\\?|\\s+optional)?$`),pathOf=e=>t(e.content)===`file`?e.content.substring(4).trim():``,isFileDirective=e=>pathOf(e).length>0,isFileDirectiveAmongProperties=e=>isFileDirective(e)&&!n.test(pathOf(e));export{isFileDirective,isFileDirectiveAmongProperties};
|
|
2
|
+
//# sourceMappingURL=FileReferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileReferences.js","names":["typeReferencePattern","pattern","firstWord","line"],"sources":["../../../../../../Compiler/Parsing/FileReferences.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 { pattern } from '../Text/patterns';\nimport { firstWord } from './LineText';\nimport { SourceLine } from './SourceLine';\n\nconst typeReferencePattern = pattern('^[A-Za-z_]\\\\w*(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?$');\n\nconst pathOf = (line: SourceLine): string =>\n firstWord(line.content) === 'file' ? line.content.substring('file'.length).trim() : '';\n\n// A 'file <path>' directive. This compiler does not model file references; it only recognizes the line so\n// it is not misread as something else.\nexport const isFileDirective = (line: SourceLine): boolean => pathOf(line).length > 0;\n\n// Among properties 'file Path' is a property named file, so only a path that is not type-shaped counts.\nexport const isFileDirectiveAmongProperties = (line: SourceLine): boolean =>\n isFileDirective(line) && !typeReferencePattern.test(pathOf(line));\n"],"mappings":"6IAOA,MAAMA,EAAuBC,EAAQ,iDAAiD,EAEhF,OAAU,GACZC,EAAUC,EAAK,OAAO,IAAM,OAASA,EAAK,QAAQ,UAAU,CAAa,CAAC,CAAC,KAAK,EAAI,GAI3E,gBAAmB,GAA8B,OAAOA,CAAI,CAAC,CAAC,OAAS,EAGvE,+BAAkC,GAC3C,gBAAgBA,CAAI,GAAK,CAACH,EAAqB,KAAK,OAAOG,CAAI,CAAC"}
|
|
@@ -0,0 +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{firstWord as r}from"./LineText.js";import{locationOf as i}from"./SourceLine.js";import{parseCondition as a}from"./ConditionParser.js";const o=n(`^when${t}+([^\\n]+)${t}+execute${t}+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),s=n(`^otherwise${t}+execute${t}+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),c=n(`^with${t}+([A-Za-z_]\\w*)${t}+from${t}+([^\\n]+)$`),l=n(`^item\\.[A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*$`),u=RegExp(`^${t}+|${t}+$`,`gu`);function parseGuardedAction(t,n,c,l){let u=[],d=null,f=null,p=!1;for(let c=t.peekChild(n.indent);c!==void 0;c=t.peekChild(n.indent)){t.reader.takeSignificant();let n=o.exec(c.content),m=s.exec(c.content);if(n!==null){p&&t.error(e.MisplacedActionOtherwise,`A 'when' alternative must precede 'otherwise'`,i(c));let r=a(t,n[1],i(c),!0),o=parseArguments(t,c);r!==null&&(validateCondition(t,r),u.push({kind:`ScreenActionAlternativeSyntax`,condition:r,command:n[2],arguments:o,location:i(c)}))}else if(c.content===`otherwise hidden`||m!==null){if(p&&t.error(e.MisplacedActionOtherwise,`A guarded action permits only one 'otherwise'`,i(c)),p=!0,m!==null)d={kind:`ScreenActionOtherwiseSyntax`,outcome:`Execute`,command:m[1],arguments:parseArguments(t,c),location:i(c)};else{d={kind:`ScreenActionOtherwiseSyntax`,outcome:`Hidden`,command:null,arguments:[],location:i(c)};for(let n=t.peekChild(c.indent);n!==void 0;n=t.peekChild(c.indent))t.reader.takeSignificant(),t.error(e.InvalidActionAlternative,`'otherwise hidden' cannot declare command arguments`,i(n)),t.skipBlock(n.indent)}}else if(r(c.content)===`navigate`)f!==null&&t.error(e.InvalidActionAlternative,`A guarded action permits only one 'navigate to'`,i(c)),f=l(t,c.content,c)??null;else{let n=r(c.content)===`label`;t.error(n?e.UnknownActionDirective:e.InvalidActionAlternative,n?`A guarded action's header already supplies its label`:`Unexpected '${c.content}' in guarded action - expected 'when <condition> execute <Command>', 'otherwise hidden', 'otherwise execute <Command>' or 'navigate to ...'`,i(c)),t.skipBlock(c.indent)}}return u.length===0&&t.error(e.GuardedActionWithoutAlternatives,`A guarded action must declare at least one 'when' alternative`,i(n)),{kind:`ScreenGuardedActionSyntax`,label:c,alternatives:u,otherwise:d,navigate:f,location:i(n)}}function parseArguments(t,n){let r=[];for(let a=t.peekChild(n.indent);a!==void 0;a=t.peekChild(n.indent)){t.reader.takeSignificant();let n=c.exec(a.content);n===null?(t.error(e.InvalidInteractionArgument,`Invalid argument '${a.content}' - expected 'with <name> from <binding>'`,i(a)),t.skipBlock(a.indent)):r.push({kind:`InteractionArgumentSyntax`,name:n[1],binding:n[2].replace(u,``),location:i(a)})}return r}function validateCondition(t,n){if(n.kind===`LogicalConditionSyntax`){validateCondition(t,n.left),validateCondition(t,n.right);return}let r=n.right.kind===`LiteralExpressionSyntax`?n.right.value:void 0,i=l.test(n.left)&&n.right.kind===`LiteralExpressionSyntax`;[`GreaterThan`,`GreaterThanOrEqual`,`LessThan`,`LessThanOrEqual`].includes(n.operator)?i&&=typeof r==`number`||typeof r==`object`&&!!r:[`Contains`,`StartsWith`].includes(n.operator)&&(i&&=typeof r==`string`),i||t.error(e.UnsupportedActionConditionOperand,`Guarded action conditions compare 'item.<field>' with a literal; ordering requires a number and text operators require a string`,n.location)}export{parseGuardedAction,validateCondition};
|
|
2
|
+
//# sourceMappingURL=GuardedActionParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedActionParser.js","names":["alternative","pattern","dotNetWhitespace","otherwise","argument","itemPath","bindingWhitespace","alternatives","fallback","navigate","sawOtherwise","child","context","line","match","fallbackMatch","DiagnosticCodes","locationOf","condition","parseCondition","args","nested","firstWord","parseNavigate","isLabel","value","supported"],"sources":["../../../../../../Compiler/Parsing/GuardedActionParser.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 { ConditionSyntax } from '../Syntax/Conditions';\nimport { InteractionArgumentSyntax, ScreenActionAlternativeSyntax, ScreenActionOtherwiseSyntax, ScreenGuardedActionSyntax, ScreenNavigateSyntax } from '../Syntax/Screens';\nimport { dotNetWhitespace, pattern } from '../Text/patterns';\nimport { parseCondition } from './ConditionParser';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// .NET '.' stops only at LF; U+2028/U+2029 stay inside a CR/LF-delimited source line.\nconst alternative = pattern(`^when${dotNetWhitespace}+([^\\\\n]+)${dotNetWhitespace}+execute${dotNetWhitespace}+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$`);\nconst otherwise = pattern(`^otherwise${dotNetWhitespace}+execute${dotNetWhitespace}+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$`);\nconst argument = pattern(`^with${dotNetWhitespace}+([A-Za-z_]\\\\w*)${dotNetWhitespace}+from${dotNetWhitespace}+([^\\\\n]+)$`);\nconst itemPath = pattern('^item\\\\.[A-Za-z_]\\\\w*(?:\\\\.[A-Za-z_]\\\\w*)*$');\nconst bindingWhitespace = new RegExp(`^${dotNetWhitespace}+|${dotNetWhitespace}+$`, 'gu');\n\ntype ParseNavigate = (context: ParserContext, text: string, line: SourceLine) => ScreenNavigateSyntax | undefined;\n\nexport function parseGuardedAction(context: ParserContext, line: SourceLine, label: string, parseNavigate: ParseNavigate): ScreenGuardedActionSyntax {\n const alternatives: ScreenActionAlternativeSyntax[] = [];\n let fallback: ScreenActionOtherwiseSyntax | null = null;\n let navigate: ScreenNavigateSyntax | null = null;\n let sawOtherwise = false;\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const match = alternative.exec(child.content);\n const fallbackMatch = otherwise.exec(child.content);\n if (match !== null) {\n if (sawOtherwise) context.error(DiagnosticCodes.MisplacedActionOtherwise, \"A 'when' alternative must precede 'otherwise'\", locationOf(child));\n const condition = parseCondition(context, match[1], locationOf(child), true);\n const args = parseArguments(context, child);\n if (condition !== null) {\n validateCondition(context, condition);\n alternatives.push({ kind: 'ScreenActionAlternativeSyntax', condition, command: match[2], arguments: args, location: locationOf(child) });\n }\n } else if (child.content === 'otherwise hidden' || fallbackMatch !== null) {\n if (sawOtherwise) context.error(DiagnosticCodes.MisplacedActionOtherwise, \"A guarded action permits only one 'otherwise'\", locationOf(child));\n sawOtherwise = true;\n if (fallbackMatch !== null) {\n fallback = { kind: 'ScreenActionOtherwiseSyntax', outcome: 'Execute', command: fallbackMatch[1], arguments: parseArguments(context, child), location: locationOf(child) };\n } else {\n fallback = { kind: 'ScreenActionOtherwiseSyntax', outcome: 'Hidden', command: null, arguments: [], location: locationOf(child) };\n for (let nested = context.peekChild(child.indent); nested !== undefined; nested = context.peekChild(child.indent)) {\n context.reader.takeSignificant();\n context.error(DiagnosticCodes.InvalidActionAlternative, \"'otherwise hidden' cannot declare command arguments\", locationOf(nested));\n context.skipBlock(nested.indent);\n }\n }\n } else if (firstWord(child.content) === 'navigate') {\n if (navigate !== null) context.error(DiagnosticCodes.InvalidActionAlternative, \"A guarded action permits only one 'navigate to'\", locationOf(child));\n navigate = parseNavigate(context, child.content, child) ?? null;\n } else {\n const isLabel = firstWord(child.content) === 'label';\n context.error(isLabel ? DiagnosticCodes.UnknownActionDirective : DiagnosticCodes.InvalidActionAlternative, isLabel\n ? \"A guarded action's header already supplies its label\"\n : `Unexpected '${child.content}' in guarded action - expected 'when <condition> execute <Command>', 'otherwise hidden', 'otherwise execute <Command>' or 'navigate to ...'`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n if (alternatives.length === 0) context.error(DiagnosticCodes.GuardedActionWithoutAlternatives, \"A guarded action must declare at least one 'when' alternative\", locationOf(line));\n return { kind: 'ScreenGuardedActionSyntax', label, alternatives, otherwise: fallback, navigate, location: locationOf(line) };\n}\n\nfunction parseArguments(context: ParserContext, line: SourceLine): InteractionArgumentSyntax[] {\n const args: InteractionArgumentSyntax[] = [];\n for (let child = context.peekChild(line.indent); child !== undefined; child = context.peekChild(line.indent)) {\n context.reader.takeSignificant();\n const match = argument.exec(child.content);\n if (match !== null) args.push({ kind: 'InteractionArgumentSyntax', name: match[1], binding: match[2].replace(bindingWhitespace, ''), location: locationOf(child) });\n else {\n context.error(DiagnosticCodes.InvalidInteractionArgument, `Invalid argument '${child.content}' - expected 'with <name> from <binding>'`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return args;\n}\n\nexport function validateCondition(context: ParserContext, condition: ConditionSyntax): void {\n if (condition.kind === 'LogicalConditionSyntax') {\n validateCondition(context, condition.left);\n validateCondition(context, condition.right);\n return;\n }\n const value = condition.right.kind === 'LiteralExpressionSyntax' ? condition.right.value : undefined;\n let supported = itemPath.test(condition.left) && condition.right.kind === 'LiteralExpressionSyntax';\n if (['GreaterThan', 'GreaterThanOrEqual', 'LessThan', 'LessThanOrEqual'].includes(condition.operator)) {\n supported &&= typeof value === 'number' || (typeof value === 'object' && value !== null);\n } else if (['Contains', 'StartsWith'].includes(condition.operator)) supported &&= typeof value === 'string';\n if (!supported) context.error(DiagnosticCodes.UnsupportedActionConditionOperand, \"Guarded action conditions compare 'item.<field>' with a literal; ordering requires a number and text operators require a string\", condition.location);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";function validateGuardedActionShadowing(t,n){let r=[];for(let i of t.alternatives){let t=normalize(i.condition);t!==null&&(t.length>0&&t.every(e=>r.some(t=>[...t].every(t=>e.has(t))))&&n.warning(e.UnreachableActionAlternative,`Alternative executing '${i.command}' is shadowed by earlier alternatives in this action`,i.location),r.push(...t))}}function normalize(e){if(e.kind===`ComparisonConditionSyntax`){if(e.right.kind!==`LiteralExpressionSyntax`)return null;let t=e.right.value,n=JSON.stringify([e.left,e.operator,typeof t,typeof t==`object`&&t?t.value:typeof t==`number`?String(t):t]);return[/* @__PURE__ */ new Set([n])]}let t=normalize(e.left),n=normalize(e.right);return t===null||n===null?null:e.operator===`Or`?t.length+n.length>64?null:[...t,...n]:t.length*n.length>64?null:t.flatMap(e=>n.map(t=>/* @__PURE__ */ new Set([...e,...t])))}export{validateGuardedActionShadowing};
|
|
2
|
+
//# sourceMappingURL=GuardedActionShadowing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedActionShadowing.js","names":["earlier","alternative","action","terms","previous","term","comparison","context","DiagnosticCodes","condition","value","left","right","first","second"],"sources":["../../../../../../Compiler/Parsing/GuardedActionShadowing.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 { ConditionSyntax } from '../Syntax/Conditions';\nimport { ScreenGuardedActionSyntax } from '../Syntax/Screens';\nimport { ParserContext } from './ParserContext';\n\nconst maximumDisjuncts = 64;\n\n// Proves shadowing by comparison-set inclusion, bounding each DNF expansion to 64 disjuncts.\nexport function validateGuardedActionShadowing(action: ScreenGuardedActionSyntax, context: ParserContext): void {\n const earlier: ReadonlySet<string>[] = [];\n for (const alternative of action.alternatives) {\n const terms = normalize(alternative.condition);\n if (terms === null) continue;\n if (terms.length > 0 && terms.every(term => earlier.some(previous => [...previous].every(comparison => term.has(comparison))))) {\n context.warning(DiagnosticCodes.UnreachableActionAlternative, `Alternative executing '${alternative.command}' is shadowed by earlier alternatives in this action`, alternative.location);\n }\n earlier.push(...terms);\n }\n}\n\nfunction normalize(condition: ConditionSyntax): ReadonlySet<string>[] | null {\n if (condition.kind === 'ComparisonConditionSyntax') {\n if (condition.right.kind !== 'LiteralExpressionSyntax') return null;\n const value = condition.right.value;\n // Preserve literal type as well as value (null, text, Boolean, Double or exact Decimal).\n const comparison = JSON.stringify([condition.left, condition.operator, typeof value, value !== null && typeof value === 'object' ? value.value : typeof value === 'number' ? String(value) : value]);\n return [new Set([comparison])];\n }\n const left = normalize(condition.left);\n const right = normalize(condition.right);\n if (left === null || right === null) return null;\n if (condition.operator === 'Or') return left.length + right.length > maximumDisjuncts ? null : [...left, ...right];\n if (left.length * right.length > maximumDisjuncts) return null;\n return left.flatMap(first => right.map(second => new Set([...first, ...second])));\n}\n"],"mappings":"yHAWA,SAAgB,+BAA+B,EAAmC,EAA8B,CAC5G,IAAMA,EAAiC,CAAC,EACxC,IAAK,IAAMC,KAAeC,EAAO,aAAc,CAC3C,IAAMC,EAAQ,UAAUF,EAAY,SAAS,EACzCE,IAAU,OACVA,EAAM,OAAS,GAAKA,EAAM,MAAM,GAAQH,EAAQ,KAAK,GAAY,CAAC,GAAGI,CAAQ,CAAC,CAAC,MAAM,GAAcC,EAAK,IAAIC,CAAU,CAAC,CAAC,CAAC,GACzHC,EAAQ,QAAQC,EAAgB,6BAA8B,0BAA0BP,EAAY,QAAQ,sDAAuDA,EAAY,QAAQ,EAE3LD,EAAQ,KAAK,GAAGG,CAAK,EACzB,CACJ,CAEA,SAAS,UAAU,EAA0D,CACzE,GAAIM,EAAU,OAAS,4BAA6B,CAChD,GAAIA,EAAU,MAAM,OAAS,0BAA2B,OAAO,KAC/D,IAAMC,EAAQD,EAAU,MAAM,MAExBH,EAAa,KAAK,UAAU,CAACG,EAAU,KAAMA,EAAU,SAAU,OAAOC,EAAyB,OAAOA,GAAU,UAAnCA,EAA8CA,EAAM,MAAQ,OAAOA,GAAU,SAAW,OAAOA,CAAK,EAAIA,CAAK,CAAC,EACnM,MAAO,iBAAC,IAAI,IAAI,CAACJ,CAAU,CAAC,CAAC,CACjC,CACA,IAAMK,EAAO,UAAUF,EAAU,IAAI,EAC/BG,EAAQ,UAAUH,EAAU,KAAK,EAIvC,OAHIE,IAAS,MAAQC,IAAU,KAAa,KACxCH,EAAU,WAAa,KAAaE,EAAK,OAASC,EAAM,OAAS,GAAmB,KAAO,CAAC,GAAGD,EAAM,GAAGC,CAAK,EAC7GD,EAAK,OAASC,EAAM,OAAS,GAAyB,KACnDD,EAAK,QAAQ,GAASC,EAAM,IAAI,mBAAU,IAAI,IAAI,CAAC,GAAGC,EAAO,GAAGC,CAAM,CAAC,CAAC,CAAC,CACpF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{RefusalDeclarations as t}from"./RefusalDeclarations.js";import{validateGuardedActionShadowing as n}from"./GuardedActionShadowing.js";const r=/* @__PURE__ */ new Set([`Uuid`,`String`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`]);function validateGuardedActions(e,n){let r=new t(e);for(let{slice:e}of r.slices)for(let t of e.screens)validateContainer(t.directives,[],e,r,n)}function validateContainer(e,t,n,r,i){let a=e.filter(e=>e.kind===`ScreenDataSyntax`),o=a.length===0?t:a;for(let t of e)switch(t.kind){case`ScreenGuardedActionSyntax`:validateAction(t,o,n,r,i);break;case`ScreenSectionSyntax`:validateContainer(t.directives,o,n,r,i);break;case`ScreenTemplateReferenceSyntax`:for(let e of t.slots)validateContainer(e.directives,o,n,r,i)}}function viewProperties(e,t,n){return n.resolve(e,t,e=>e.readModels)?.node.properties??null}function validateAction(t,r,i,a,o){let s=r.length===1?viewProperties(r[0].type.name,i,a):null;r.length!==1&&o.warning(e.UnresolvedActionSubject,`A guarded action requires exactly one nearest 'data' subject; no data or equally near data bindings leave 'item' unresolved`,t.location);for(let e of t.alternatives){for(let t of comparisons(e.condition))validateItemPath(t.left,t.location,s,i,a,o);validateArguments(e.command,e.arguments,s,i,a,o)}t.otherwise?.command!=null&&validateArguments(t.otherwise.command,t.otherwise.arguments,s,i,a,o),n(t,o)}function validateArguments(t,n,r,i,a,o){let s=a.resolve(t,i,e=>e.commands)?.node;for(let c of n){let n=s?.properties.filter(e=>e.name===c.name);n?.length===0&&o.warning(e.UnknownActionArgumentProperty,`Command '${t}' has no argument property '${c.name}'`,c.location);let l=validateItemPath(c.binding,c.location,r,i,a,o,!0);n?.length===1&&l!==null&&n[0].type.isCollection!==l.type.isCollection&&o.warning(e.UnknownActionArgumentProperty,`Command argument '${t}.${c.name}' and subject field '${c.binding}' must have matching collection cardinality`,c.location)}}function validateItemPath(t,n,i,a,o,s,c=!1){if(!t.startsWith(`item.`)||i===null)return null;let l=t.substring(5).split(`.`);for(let[u,d]of l.entries()){let f=i.filter(e=>e.name===d);if(f.length===0||f.length===1&&f[0].type.isCollection&&(!c||u<l.length-1))return s.warning(e.UnknownActionSubjectField,`Unknown or collection-valued subject field '${t}' - guarded actions require an item field path`,n),null;if(f.length!==1)return null;if(u===l.length-1)return f[0];let p=f[0].type;if(i=o.types.get(p.name)?.properties??viewProperties(p.name,a,o),i===null)return(r.has(p.name)||o.application.concepts.some(e=>e.name===p.name)&&!o.application.types.some(e=>e.name===p.name))&&s.warning(e.UnknownActionSubjectField,`Subject field '${t}' continues past scalar '${d}'`,n),null}return null}function comparisons(e){return e.kind===`ComparisonConditionSyntax`?[e]:[...comparisons(e.left),...comparisons(e.right)]}export{validateGuardedActions};
|
|
2
|
+
//# sourceMappingURL=GuardedActionValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuardedActionValidator.js","names":["primitives","declarations","RefusalDeclarations","application","screen","slice","context","local","directives","directive","subjects","inherited","slot","name","candidate","properties","DiagnosticCodes","action","alternative","comparison","validateGuardedActionShadowing","command","commandName","argument","arguments_","inputs","property","subjectProperty","path","segments","index","segment","matches","allowTerminalCollection","location","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 { validateGuardedActionShadowing } from './GuardedActionShadowing';\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 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 '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\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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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{AuthoringProductionResolver as t}from"../Syntax/AuthoringProductionResolver.js";import{dependencySourcesOf as n}from"../Syntax/DependencySources.js";import{EventSourceCatalog as r}from"../Syntax/EventSourceCatalog.js";import{uniqueByName as i}from"./ResponseValidator.js";function validateIdentifierCompliance(a,o){let s=new Set(a.concepts.filter(e=>e.attributes.some(e=>e.name===`pii`)).map(e=>e.name)),c=new Set(a.concepts.filter(e=>e.attributes.some(e=>e.name===`sensitive`)).map(e=>e.name)),l=i(a.types),u=new t(a),d=new Set(a.imports.map(e=>e.qualifiedName.split(`.`).at(-1))),f=/* @__PURE__ */ new Map;for(let e of a.declaredTriggers??[]){let t=f.get(e.name)??[];t.push(e.data),f.set(e.name,t)}let validate=(t,n,r=`an event source identifier`)=>{if(s.has(t.name)||c.has(t.name)){let i=s.has(t.name)?`pii`:`secret`;o.error(e.PiiNotSupportedOnIdentifier,`Concept '${t.name}' is ${i} and cannot be ${r} - use a surrogate Uuid identifier and keep the ${i} value as a property`,n)}},property=(e,t)=>{let[n,...r]=t.split(`.`),i=e.filter(e=>e.name===n);if(i.length!==1)return null;let a=i[0];return r.length===0?a:property(l.get(a.type.name)?.properties??[],r.join(`.`))};for(let e of a.eventSources??[]){e.identifier!=null&&validate(e.identifier,e.identifier.location);for(let t of e.streams){t.streamId!==null&&validate(t.streamId,t.streamId.location,`a stream id`);for(let e of t.streamIdParts)validate(e.type,e.type.location,`a stream id part '${e.name}'`)}}let p=new r(a);for(let{slice:e}of u.slices){for(let t of e.commands){for(let e of t.properties.filter(e=>e.isIdentifier))validate(e.type,e.location);for(let e of[...t.stream?[t.stream]:[],...t.streamCandidates??[]].filter(e=>e.propertyCandidate===null)){let n=p.resolve(e.eventSource,e.stream),r=n.kind===`unique`?n.streams[0]:void 0,i=[...e.streamId===null?[]:[{mapping:e.streamId,target:r?.streamId}],...e.streamIdParts.map(e=>({mapping:e,target:r?.streamIdParts.find(t=>t.name===e.property)?.type}))];for(let{mapping:e,target:n}of i){if(e.source.kind!==`PathExpressionSyntax`)continue;let r=property(t.properties,e.source.path);r!==null&&(r.type.name!==n?.name||!s.has(r.type.name)&&!c.has(r.type.name))&&validate(r.type,e.source.location,`a stream id route mapping`)}}for(let n of t.produces.filter(t=>u.isEventProduction(t,e))){if(n.for?.kind!==`PathExpressionSyntax`)continue;let e=property(t.properties,n.for.path);e!==null&&!e.isIdentifier&&validate(e.type,n.for.location)}}for(let t of e.reactions.flatMap(e=>e.triggers)){if(t.source.kind!==`NamedTriggerSourceSyntax`)continue;let r=u.resolve(t.source.name,e).declaration?.node,i=(n(t).data??[]).flatMap(e=>e.type===null?[]:[{kind:`PropertySyntax`,name:e.name,type:e.type,isIdentifier:!1,location:e.location}]),a=[r?.kind===`EventSyntax`?r.properties:[],i];r?.kind!==`EventSyntax`&&!d.has(t.source.name)&&a.push(...f.get(t.source.name)??[]);for(let n of t.produces.filter(t=>u.isEventProduction(t,e))){if(n.for?.kind!==`PathExpressionSyntax`)continue;let e=n.for.path,t=a.map(t=>property(t,e)).find(e=>e!==null&&(s.has(e.type.name)||c.has(e.type.name)));t!=null&&validate(t.type,n.for.location)}}}}export{validateIdentifierCompliance};
|
|
2
|
+
//# sourceMappingURL=IdentifierComplianceValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentifierComplianceValidator.js","names":["personal","application","concept","attribute","sensitive","types","uniqueByName","resolver","AuthoringProductionResolver","imports","imported","declaredTriggers","declared","shapes","type","context","DiagnosticCodes","position","location","name","rest","path","matches","properties","entry","value","source","stream","part","catalog","EventSourceCatalog","command","slice","route","resolution","mappings","mapping","target","production","trigger","reaction","event","clauseData","dependencySourcesOf","datum"],"sources":["../../../../../../Compiler/Parsing/IdentifierComplianceValidator.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 { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { PropertySyntax, TypeRefSyntax } from '../Syntax/Declarations';\nimport { EventSourceCatalog } from '../Syntax/EventSourceCatalog';\nimport { EventSourceResolutionKind } from '../Syntax/EventSources';\nimport { ApplicationSyntax } from '../Syntax/Structure';\nimport { dependencySourcesOf } from '../Syntax/DependencySources';\nimport { ParserContext } from './ParserContext';\nimport { uniqueByName } from './ResponseValidator';\n\nexport function validateIdentifierCompliance(application: ApplicationSyntax, context: ParserContext): void {\n const personal = new Set(application.concepts.filter(concept => concept.attributes.some(attribute => attribute.name === 'pii')).map(concept => concept.name));\n const sensitive = new Set(application.concepts.filter(concept => concept.attributes.some(attribute => attribute.name === 'sensitive')).map(concept => concept.name));\n const types = uniqueByName(application.types);\n const resolver = new AuthoringProductionResolver(application);\n const imports = new Set(application.imports.map(imported => imported.qualifiedName.split('.').at(-1)!));\n const declaredTriggers = new Map<string, (readonly PropertySyntax[])[]>();\n for (const declared of application.declaredTriggers ?? []) {\n const shapes = declaredTriggers.get(declared.name) ?? [];\n shapes.push(declared.data);\n declaredTriggers.set(declared.name, shapes);\n }\n const validate = (type: TypeRefSyntax, location: SourceLocation, position = 'an event source identifier'): void => {\n if (personal.has(type.name) || sensitive.has(type.name)) {\n const attribute = personal.has(type.name) ? 'pii' : 'secret';\n context.error(DiagnosticCodes.PiiNotSupportedOnIdentifier, `Concept '${type.name}' is ${attribute} and cannot be ${position} - use a surrogate Uuid identifier and keep the ${attribute} value as a property`, location);\n }\n };\n const property = (properties: readonly PropertySyntax[], path: string): PropertySyntax | null => {\n const [name, ...rest] = path.split('.');\n const matches = properties.filter(entry => entry.name === name);\n if (matches.length !== 1) return null;\n const value = matches[0];\n if (rest.length === 0) return value;\n return property(types.get(value.type.name)?.properties ?? [], rest.join('.'));\n };\n for (const source of application.eventSources ?? []) {\n if (source.identifier != null) validate(source.identifier, source.identifier.location);\n for (const stream of source.streams) {\n if (stream.streamId !== null) validate(stream.streamId, stream.streamId.location, 'a stream id');\n for (const part of stream.streamIdParts) validate(part.type, part.type.location, `a stream id part '${part.name}'`);\n }\n }\n const catalog = new EventSourceCatalog(application);\n for (const { slice } of resolver.slices) {\n for (const command of slice.commands) {\n for (const entry of command.properties.filter(entry => entry.isIdentifier)) validate(entry.type, entry.location);\n for (const route of [...(command.stream ? [command.stream] : []), ...command.streamCandidates ?? []].filter(route => route.propertyCandidate === null)) {\n const resolution = catalog.resolve(route.eventSource, route.stream);\n const stream = resolution.kind === EventSourceResolutionKind.Unique ? resolution.streams[0] : undefined;\n const mappings = [\n ...(route.streamId === null ? [] : [{ mapping: route.streamId, target: stream?.streamId }]),\n ...route.streamIdParts.map(mapping => ({ mapping, target: stream?.streamIdParts.find(part => part.name === mapping.property)?.type })),\n ];\n for (const { mapping, target } of mappings) {\n if (mapping.source.kind !== 'PathExpressionSyntax') continue;\n const entry = property(command.properties, mapping.source.path);\n if (entry === null) continue;\n // The same protected concept has already been reported at its resolved declaration.\n if (entry.type.name === target?.name && (personal.has(entry.type.name) || sensitive.has(entry.type.name))) continue;\n validate(entry.type, mapping.source.location, 'a stream id route mapping');\n }\n }\n for (const production of command.produces.filter(production => resolver.isEventProduction(production, slice))) {\n if (production.for?.kind !== 'PathExpressionSyntax') continue;\n const entry = property(command.properties, production.for.path);\n if (entry !== null && !entry.isIdentifier) validate(entry.type, production.for.location);\n }\n }\n for (const trigger of slice.reactions.flatMap(reaction => reaction.triggers)) {\n if (trigger.source.kind !== 'NamedTriggerSourceSyntax') continue;\n const resolution = resolver.resolve(trigger.source.name, slice);\n const event = resolution.declaration?.node;\n const clauseData = (dependencySourcesOf(trigger).data ?? []).flatMap<PropertySyntax>(datum => datum.type === null ? [] : [{ kind: 'PropertySyntax', name: datum.name, type: datum.type, isIdentifier: false, location: datum.location }]);\n const shapes = [event?.kind === 'EventSyntax' ? event.properties : [], clauseData];\n if (event?.kind !== 'EventSyntax' && !imports.has(trigger.source.name)) {\n shapes.push(...declaredTriggers.get(trigger.source.name) ?? []);\n }\n for (const production of trigger.produces.filter(production => resolver.isEventProduction(production, slice))) {\n if (production.for?.kind !== 'PathExpressionSyntax') continue;\n // Check clause-local types alongside the occurrence selected by event-first reaction resolution.\n const path = production.for.path;\n const entry = shapes.map(properties => property(properties, path)).find(entry => entry !== null && (personal.has(entry.type.name) || sensitive.has(entry.type.name)));\n if (entry != null) validate(entry.type, production.for.location);\n }\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{pattern as t}from"../Text/patterns.js";import{stringBodyPattern as n,unescapeString as r}from"../Text/StringLiteral.js";import{parseMappingSource as i}from"./ExpressionParser.js";import{firstWord as a,unescapeIdentifier as o}from"./LineText.js";import{locationOf as s}from"./SourceLine.js";import{parseTypeRef as c,reportLegacyOptionalSuffix as l}from"./PropertyLineParser.js";import{parseDescription as u}from"./DescriptionParser.js";import{isCode as d,isFile as f,parseCode as p,parseFile as m}from"./ImplementationParser.js";const h=t(`^(@?[a-z_]\\w*)\\s+([\\w.]+(?:\\[\\])?(?:\\?|\\s+optional)?)(?:\\s+from\\s+(.+))?$`),g=t(`^claim\\s+"(${n})"$`),_=t(`^query\\s+([A-Za-z_]\\w*(?:\\.[A-Za-z_]\\w*)*)(?:\\s+by\\s+(.+))?$`);function parseIdentity(t,n,r){if(n.content!==`identity`)return t.error(e.InvalidIdentityDeclaration,`Invalid identity declaration '${n.content}' - expected 'identity'`,s(n)),t.skipBlock(n.indent),r;if(r!==null)return t.error(e.DuplicateIdentity,`The document already declares an identity block - a document can have at most one`,s(n)),t.skipBlock(n.indent),r;let i=[],d=null;for(let r=t.peekChild(n.indent);r!==void 0;r=t.peekChild(n.indent)){if(t.reader.takeSignificant(),a(r.content)===`description`){d=u(t,r,d,`Identity`);continue}let n=h.exec(r.content);if(n===null){t.error(e.InvalidIdentityDetail,`Invalid identity detail '${r.content}' - expected '<name> <Type> [from claim "<name>" | from query <Query> by <expression>]'`,s(r)),t.skipBlock(r.indent);continue}let f=c(n[2],{...s(r),column:r.indent+1+r.content.indexOf(n[2],n[1].length)});l(t,f,r);let p=n[3]===void 0?parseEscape(t,r):parseSource(t,r,n[3]);p!==null&&i.push({kind:`IdentityDetailSyntax`,name:o(n[1]),type:f,source:p,location:s(r)}),rejectBody(t,r,n[3]===void 0?e.InvalidIdentityDetail:e.IdentitySourceWithBody)}return{kind:`IdentitySyntax`,details:i,description:d,location:s(n)}}function parseSource(t,n,o){let c=g.exec(o);if(c!==null)return{kind:`ClaimIdentitySourceSyntax`,claim:r(c[1]),location:s(n)};let l=_.exec(o);if(l!==null)return l[2]===void 0?(t.error(e.IdentityQueryWithoutKey,`An identity query source requires 'by <expression>'`,s(n)),null):{kind:`QueryIdentitySourceSyntax`,query:l[1],by:i(l[2],s(n),t),location:s(n)};let u=a(o);return t.error(u===`claim`||u===`query`?e.InvalidIdentityDetail:e.UnknownIdentitySource,`Invalid identity source '${o}' - expected 'claim "<name>"' or 'query <Query> by <expression>'`,s(n)),null}function parseEscape(t,n){let r=t.peekChild(n.indent);if(r===void 0)return t.error(e.IdentityDetailWithoutSource,`An identity detail requires a claim, query, inline code block or file source`,s(n)),null;if(t.reader.takeSignificant(),f(r)){let n=m(t,r);return rejectBody(t,r,e.InvalidIdentityDetail),{kind:`FileIdentitySourceSyntax`,file:n,location:s(r)}}if(d(t,r)){let e=p(t,r);return e===null?null:{kind:`CodeIdentitySourceSyntax`,code:e,location:s(r)}}return t.error(e.InvalidIdentityDetail,`Unexpected '${r.content}' under an identity detail - expected a file reference or inline code block`,s(r)),t.skipBlock(r.indent),null}function rejectBody(e,t,n){for(let r=e.peekChild(t.indent);r!==void 0;r=e.peekChild(t.indent))e.reader.takeSignificant(),e.error(n,`Unexpected '${r.content}' under an identity source - refresh and caching are the runtime's business; a detail has exactly one source`,s(r)),e.skipBlock(r.indent)}export{parseIdentity};
|
|
2
|
+
//# sourceMappingURL=IdentityParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityParser.js","names":["detailPattern","pattern","claimPattern","stringBodyPattern","queryPattern","header","context","DiagnosticCodes","locationOf","existing","details","description","line","firstWord","parseDescription","match","type","parseTypeRef","reportLegacyOptionalSuffix","source","unescapeIdentifier","claim","text","unescapeString","query","parseMappingSource","kind","body","detail","isFile","file","parseFile","isCode","code","parseCode","child","parent"],"sources":["../../../../../../Compiler/Parsing/IdentityParser.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 { IdentitySyntax } from '../Syntax/IdentitySyntax';\nimport { IdentityDetailSyntax } from '../Syntax/IdentityDetailSyntax';\nimport { IdentitySourceSyntax } from '../Syntax/IdentitySourceSyntax';\nimport { pattern } from '../Text/patterns';\nimport { stringBodyPattern, unescapeString } from '../Text/StringLiteral';\nimport { parseDescription } from './DescriptionParser';\nimport { parseMappingSource } from './ExpressionParser';\nimport { isCode, isFile, parseCode, parseFile } from './ImplementationParser';\nimport { firstWord, unescapeIdentifier } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { parseTypeRef, reportLegacyOptionalSuffix } from './PropertyLineParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\nconst detailPattern = pattern('^(@?[a-z_]\\\\w*)\\\\s+([\\\\w.]+(?:\\\\[\\\\])?(?:\\\\?|\\\\s+optional)?)(?:\\\\s+from\\\\s+(.+))?$');\nconst claimPattern = pattern(`^claim\\\\s+\"(${stringBodyPattern})\"$`);\nconst queryPattern = pattern('^query\\\\s+([A-Za-z_]\\\\w*(?:\\\\.[A-Za-z_]\\\\w*)*)(?:\\\\s+by\\\\s+(.+))?$');\n\nexport function parseIdentity(context: ParserContext, header: SourceLine, existing: IdentitySyntax | null): IdentitySyntax | null {\n if (header.content !== 'identity') {\n context.error(DiagnosticCodes.InvalidIdentityDeclaration, `Invalid identity declaration '${header.content}' - expected 'identity'`, locationOf(header));\n context.skipBlock(header.indent);\n return existing;\n }\n if (existing !== null) {\n context.error(DiagnosticCodes.DuplicateIdentity, 'The document already declares an identity block - a document can have at most one', locationOf(header));\n context.skipBlock(header.indent);\n return existing;\n }\n const details: IdentityDetailSyntax[] = [];\n let description: string | null = null;\n for (let line = context.peekChild(header.indent); line !== undefined; line = context.peekChild(header.indent)) {\n context.reader.takeSignificant();\n if (firstWord(line.content) === 'description') {\n description = parseDescription(context, line, description, 'Identity');\n continue;\n }\n const match = detailPattern.exec(line.content);\n if (match === null) {\n context.error(DiagnosticCodes.InvalidIdentityDetail, `Invalid identity detail '${line.content}' - expected '<name> <Type> [from claim \"<name>\" | from query <Query> by <expression>]'`, locationOf(line));\n context.skipBlock(line.indent);\n continue;\n }\n const type = parseTypeRef(match[2], { ...locationOf(line), column: line.indent + 1 + line.content.indexOf(match[2], match[1].length) });\n reportLegacyOptionalSuffix(context, type, line);\n const source = match[3] !== undefined ? parseSource(context, line, match[3]) : parseEscape(context, line);\n if (source !== null) details.push({ kind: 'IdentityDetailSyntax', name: unescapeIdentifier(match[1]), type, source, location: locationOf(line) });\n rejectBody(context, line, match[3] !== undefined ? DiagnosticCodes.IdentitySourceWithBody : DiagnosticCodes.InvalidIdentityDetail);\n }\n return { kind: 'IdentitySyntax', details, description, location: locationOf(header) };\n}\n\nfunction parseSource(context: ParserContext, line: SourceLine, text: string): IdentitySourceSyntax | null {\n const claim = claimPattern.exec(text);\n if (claim !== null) return { kind: 'ClaimIdentitySourceSyntax', claim: unescapeString(claim[1]), location: locationOf(line) };\n const query = queryPattern.exec(text);\n if (query !== null) {\n if (query[2] === undefined) {\n context.error(DiagnosticCodes.IdentityQueryWithoutKey, \"An identity query source requires 'by <expression>'\", locationOf(line));\n return null;\n }\n return { kind: 'QueryIdentitySourceSyntax', query: query[1], by: parseMappingSource(query[2], locationOf(line), context), location: locationOf(line) };\n }\n const kind = firstWord(text);\n context.error(kind === 'claim' || kind === 'query' ? DiagnosticCodes.InvalidIdentityDetail : DiagnosticCodes.UnknownIdentitySource,\n `Invalid identity source '${text}' - expected 'claim \"<name>\"' or 'query <Query> by <expression>'`, locationOf(line));\n return null;\n}\n\nfunction parseEscape(context: ParserContext, detail: SourceLine): IdentitySourceSyntax | null {\n const body = context.peekChild(detail.indent);\n if (body === undefined) {\n context.error(DiagnosticCodes.IdentityDetailWithoutSource, 'An identity detail requires a claim, query, inline code block or file source', locationOf(detail));\n return null;\n }\n context.reader.takeSignificant();\n if (isFile(body)) {\n const file = parseFile(context, body);\n rejectBody(context, body, DiagnosticCodes.InvalidIdentityDetail);\n return { kind: 'FileIdentitySourceSyntax', file, location: locationOf(body) };\n }\n if (isCode(context, body)) {\n const code = parseCode(context, body);\n return code === null ? null : { kind: 'CodeIdentitySourceSyntax', code, location: locationOf(body) };\n }\n context.error(DiagnosticCodes.InvalidIdentityDetail, `Unexpected '${body.content}' under an identity detail - expected a file reference or inline code block`, locationOf(body));\n context.skipBlock(body.indent);\n return null;\n}\n\nfunction rejectBody(context: ParserContext, parent: SourceLine, code: string): void {\n for (let child = context.peekChild(parent.indent); child !== undefined; child = context.peekChild(parent.indent)) {\n context.reader.takeSignificant();\n context.error(code, `Unexpected '${child.content}' under an identity source - refresh and caching are the runtime's business; a detail has exactly one source`, locationOf(child));\n context.skipBlock(child.indent);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{AuthoringProductionResolver as t}from"../Syntax/AuthoringProductionResolver.js";import{dependencySourcesOf as n}from"../Syntax/DependencySources.js";import{ScreenplaySyntaxWalker as r}from"../Syntax/ScreenplaySyntaxWalker.js";import{identityProperties as i}from"./ExpressionParser.js";function validateIdentity(r,a){let o=r.identity?.details??[],s=new Set(o.map(e=>e.name)),c=/* @__PURE__ */ new Set([`Uuid`,`String`,`Int`,`Decimal`,`Bool`,`Date`,`DateTime`,...r.concepts.map(e=>e.name),...r.types.map(e=>e.name),...r.imports.map(e=>e.qualifiedName.split(`.`).at(-1))]),l=new t(r);for(let{slice:e}of l.slices){for(let t of e.readModels)c.add(t.name);for(let t of e.projections){let e=t.blocks.filter(e=>e.kind===`ProjectionVariantSyntax`);for(let n of e.length>0?e.map(e=>e.name):[t.readModel??t.name])c.add(n)}for(let t of n(e).reducers??[])c.add(t.readModel)}new IdentityPaths(s,a).visitApplication(r);let u=/* @__PURE__ */ new Set;for(let t of o){if(u.has(t.name)&&a.error(e.DuplicateIdentityDetail,`Duplicate identity detail '${t.name}' - detail names must be unique`,t.location),u.add(t.name),i.includes(t.name)&&a.error(e.BuiltInIdentityDetail,`Identity detail '${t.name}' redeclares a built-in caller property`,t.location),c.has(t.type.name)||a.warning(e.UnknownType,`Unknown type '${t.type.name}' on identity detail '${t.name}'`,t.type.location),t.source.kind!==`QueryIdentitySourceSyntax`)continue;let n=t.source;isTokenKey(n.by)||a.error(e.InvalidIdentityQueryKey,`Identity detail '${t.name}' query key may reference only caller built-ins, claims or literals, never another detail`,n.by.location);let o=n.query.split(`.`),d=o.at(-1),f=o.slice(0,-1),p=l.slices.flatMap(({slice:e,scope:t})=>e.queries.map(e=>({query:e,scope:t}))).filter(e=>e.query.name===d&&f.length<=e.scope.length&&f.every((t,n)=>t===e.scope[e.scope.length-f.length+n]));if(p.length!==1){a.error(e.UnknownIdentityQuery,`Unknown or ambiguous identity query '${n.query}'`,n.location);continue}let{query:m,scope:h}=p[0];(m.by===null||m.returnType.isCollection)&&a.error(e.InvalidIdentityQuery,`Identity query '${n.query}' must be keyed and return a single, possibly optional result`,n.location),(m.returnType.name!==t.type.name||t.type.isCollection||m.returnType.isOptional&&!t.type.isOptional)&&a.error(e.IdentityQueryTypeMismatch,`Identity detail '${t.name}' must match query '${n.query}' result type, including optionality`,t.type.location);let g=m.authorize===null?[]:[m.authorize];for(let e of r.modules.filter(e=>e.name===h[0]))e.authorize!==null&&g.push(e.authorize),collectFeatureAuthorizations(e.features,h.slice(1,-1),g);let _=new Set(g.flatMap(e=>policyNames(e.requirement))),v=new DetailReferences(s);for(let e of(r.policies??[]).filter(e=>_.has(e.name)))v.visitPolicy(e);v.found.length>0&&a.error(e.IdentityQueryAuthorizationDependency,`Identity query '${n.query}' authorization depends on identity detail '${v.found[0].path.split(`.`)[0]}' - caller details cannot authorize their own resolution`,n.location)}}function isTokenKey(e){return e.kind===`LiteralExpressionSyntax`?!0:e.kind===`IdentityExpressionSyntax`?i.includes(e.path.split(`.`)[0]):e.kind===`ContextExpressionSyntax`&&e.path.startsWith(`identity.`)&&i.includes(e.path.split(`.`)[1])}function policyNames(e){return e.kind===`PolicyReferenceSyntax`?[e.name]:[...policyNames(e.left),...policyNames(e.right)]}function collectFeatureAuthorizations(e,t,n){for(let r of e.filter(e=>e.name===t[0]))r.authorize!==null&&n.push(r.authorize),collectFeatureAuthorizations(r.features,t.slice(1),n)}var IdentityPaths=class extends r{details;context;constructor(e,t){super(),this.details=e,this.context=t}visitExpression(t){if(t.kind===`ContextExpressionSyntax`&&t.path.startsWith(`identity.`)){let n=t.path.split(`.`)[1];!i.includes(n)&&!this.context.diagnostics.some(n=>n.code===e.UnknownContextIdentityProperty&&n.location.line===t.location.line&&n.location.column===t.location.column)&&this.context.warning(e.UnknownContextIdentityProperty,`Unknown $context.identity property '${n}' - expected ${i.join(`, `)}`,t.location)}super.visitExpression(t)}visitIdentityExpression(t){let n=t.path.split(`.`)[0];!this.details.has(n)&&!i.includes(n)&&this.context.warning(e.UnknownContextIdentityProperty,`Unknown $identity property '${n}' - expected ${[...i,...this.details].join(`, `)}`,t.location)}},DetailReferences=class extends r{details;found=[];constructor(e){super(),this.details=e}visitIdentityExpression(e){this.details.has(e.path.split(`.`)[0])&&this.found.push(e)}};export{validateIdentity};
|
|
2
|
+
//# sourceMappingURL=IdentityValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityValidator.js","names":["details","application","names","detail","known","concept","type","imported","resolver","AuthoringProductionResolver","model","slice","projection","variants","block","name","variant","reducer","dependencySourcesOf","context","declared","DiagnosticCodes","identityProperties","source","parts","qualifiers","queries","entry","qualifier","index","query","authorizations","module","scope","policies","authorization","dependency","policy","expression","requirement","feature","features","segments","result","ScreenplaySyntaxWalker","syntax","property","diagnostic"],"sources":["../../../../../../Compiler/Parsing/IdentityValidator.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 { AuthorizeSyntax, PolicyRequirementSyntax } from '../Syntax/Authorization';\nimport { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { dependencySourcesOf } from '../Syntax/DependencySources';\nimport { ExpressionSyntax, IdentityExpressionSyntax } from '../Syntax/Expressions';\nimport { ScreenplaySyntaxWalker } from '../Syntax/ScreenplaySyntaxWalker';\nimport { ApplicationSyntax, FeatureSyntax } from '../Syntax/Structure';\nimport { identityProperties } from './ExpressionParser';\nimport { ParserContext } from './ParserContext';\n\nexport function validateIdentity(application: ApplicationSyntax, context: ParserContext): void {\n const details = application.identity?.details ?? [];\n const names = new Set(details.map(detail => detail.name));\n const known = new Set(['Uuid', 'String', 'Int', 'Decimal', 'Bool', 'Date', 'DateTime', ...application.concepts.map(concept => concept.name), ...application.types.map(type => type.name), ...application.imports.map(imported => imported.qualifiedName.split('.').at(-1)!) ]);\n const resolver = new AuthoringProductionResolver(application);\n for (const { slice } of resolver.slices) {\n for (const model of slice.readModels) known.add(model.name);\n for (const projection of slice.projections) {\n // Match C# ProjectionBuiltReadModelNames: direct variants replace the builder's own output.\n const variants = projection.blocks.filter(block => block.kind === 'ProjectionVariantSyntax');\n for (const name of variants.length > 0 ? variants.map(variant => variant.name) : [projection.readModel ?? projection.name]) known.add(name);\n }\n for (const reducer of dependencySourcesOf(slice).reducers ?? []) known.add(reducer.readModel);\n }\n new IdentityPaths(names, context).visitApplication(application);\n const declared = new Set<string>();\n for (const detail of details) {\n if (declared.has(detail.name)) context.error(DiagnosticCodes.DuplicateIdentityDetail, `Duplicate identity detail '${detail.name}' - detail names must be unique`, detail.location);\n declared.add(detail.name);\n if (identityProperties.includes(detail.name)) context.error(DiagnosticCodes.BuiltInIdentityDetail, `Identity detail '${detail.name}' redeclares a built-in caller property`, detail.location);\n if (!known.has(detail.type.name)) context.warning(DiagnosticCodes.UnknownType, `Unknown type '${detail.type.name}' on identity detail '${detail.name}'`, detail.type.location);\n if (detail.source.kind !== 'QueryIdentitySourceSyntax') continue;\n const source = detail.source;\n if (!isTokenKey(source.by)) context.error(DiagnosticCodes.InvalidIdentityQueryKey, `Identity detail '${detail.name}' query key may reference only caller built-ins, claims or literals, never another detail`, source.by.location);\n const parts = source.query.split('.');\n const name = parts.at(-1)!;\n const qualifiers = parts.slice(0, -1);\n const queries = resolver.slices.flatMap(({ slice, scope }) => slice.queries.map(query => ({ query, scope }))).filter(entry => entry.query.name === name && qualifiers.length <= entry.scope.length && qualifiers.every((qualifier, index) => qualifier === entry.scope[entry.scope.length - qualifiers.length + index]));\n if (queries.length !== 1) {\n context.error(DiagnosticCodes.UnknownIdentityQuery, `Unknown or ambiguous identity query '${source.query}'`, source.location);\n continue;\n }\n const { query, scope } = queries[0];\n if (query.by === null || query.returnType.isCollection) context.error(DiagnosticCodes.InvalidIdentityQuery, `Identity query '${source.query}' must be keyed and return a single, possibly optional result`, source.location);\n if (query.returnType.name !== detail.type.name || detail.type.isCollection || query.returnType.isOptional && !detail.type.isOptional) context.error(DiagnosticCodes.IdentityQueryTypeMismatch, `Identity detail '${detail.name}' must match query '${source.query}' result type, including optionality`, detail.type.location);\n const authorizations: AuthorizeSyntax[] = query.authorize === null ? [] : [query.authorize];\n for (const module of application.modules.filter(module => module.name === scope[0])) {\n if (module.authorize !== null) authorizations.push(module.authorize);\n collectFeatureAuthorizations(module.features, scope.slice(1, -1), authorizations);\n }\n const policies = new Set(authorizations.flatMap(authorization => policyNames(authorization.requirement)));\n const dependency = new DetailReferences(names);\n for (const policy of (application.policies ?? []).filter(policy => policies.has(policy.name))) dependency.visitPolicy(policy);\n if (dependency.found.length > 0) context.error(DiagnosticCodes.IdentityQueryAuthorizationDependency, `Identity query '${source.query}' authorization depends on identity detail '${dependency.found[0].path.split('.')[0]}' - caller details cannot authorize their own resolution`, source.location);\n }\n}\n\nfunction isTokenKey(expression: ExpressionSyntax): boolean {\n if (expression.kind === 'LiteralExpressionSyntax') return true;\n if (expression.kind === 'IdentityExpressionSyntax') return identityProperties.includes(expression.path.split('.')[0]);\n return expression.kind === 'ContextExpressionSyntax' && expression.path.startsWith('identity.') && identityProperties.includes(expression.path.split('.')[1]);\n}\n\nfunction policyNames(requirement: PolicyRequirementSyntax): string[] {\n if (requirement.kind === 'PolicyReferenceSyntax') return [requirement.name];\n return [...policyNames(requirement.left), ...policyNames(requirement.right)];\n}\n\nfunction collectFeatureAuthorizations(features: readonly FeatureSyntax[], segments: readonly string[], result: AuthorizeSyntax[]): void {\n for (const feature of features.filter(feature => feature.name === segments[0])) {\n if (feature.authorize !== null) result.push(feature.authorize);\n collectFeatureAuthorizations(feature.features, segments.slice(1), result);\n }\n}\n\nclass IdentityPaths extends ScreenplaySyntaxWalker {\n constructor(private readonly details: ReadonlySet<string>, private readonly context: ParserContext) { super(); }\n override visitExpression(syntax: ExpressionSyntax): void {\n if (syntax.kind === 'ContextExpressionSyntax' && syntax.path.startsWith('identity.')) {\n const property = syntax.path.split('.')[1];\n if (!identityProperties.includes(property) && !this.context.diagnostics.some(diagnostic => diagnostic.code === DiagnosticCodes.UnknownContextIdentityProperty && diagnostic.location.line === syntax.location.line && diagnostic.location.column === syntax.location.column)) {\n this.context.warning(DiagnosticCodes.UnknownContextIdentityProperty, `Unknown $context.identity property '${property}' - expected ${identityProperties.join(', ')}`, syntax.location);\n }\n }\n super.visitExpression(syntax);\n }\n override visitIdentityExpression(syntax: IdentityExpressionSyntax): void {\n const property = syntax.path.split('.')[0];\n if (!this.details.has(property) && !identityProperties.includes(property)) this.context.warning(DiagnosticCodes.UnknownContextIdentityProperty, `Unknown $identity property '${property}' - expected ${[...identityProperties, ...this.details].join(', ')}`, syntax.location);\n }\n}\n\nclass DetailReferences extends ScreenplaySyntaxWalker {\n readonly found: IdentityExpressionSyntax[] = [];\n constructor(private readonly details: ReadonlySet<string>) { super(); }\n override visitIdentityExpression(syntax: IdentityExpressionSyntax): void {\n if (this.details.has(syntax.path.split('.')[0])) this.found.push(syntax);\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{unescapeString as t}from"../Text/StringLiteral.js";import{firstWord as n}from"./LineText.js";import{locationOf as r}from"./SourceLine.js";import{isBlankImplementationHint as i}from"../Text/ImplementationHintText.js";const a=/* @__PURE__ */ RegExp(`^hint[\\u0009-\\u000d\\u0020\\u0085\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000]+"((?:[^"\\\\\\r\\n]|\\\\[^\\r\\n])*)"$`),isFile=e=>n(e.content)===`file`&&e.content.substring(4).trim().length>0,isCode=(e,t)=>t.content.startsWith("```")||e.languages.has(t.content);function parseFile(t,n){let i=n.content.substring(4).trim();return/^(?:[/\\]|[A-Za-z]:[/\\]|~[/\\])/.test(i)&&t.warning(e.AbsoluteFileReference,`'${i}' is an absolute path - a file reference is relative to the repository root, so it means the same thing on every machine`,r(n)),{kind:`FileReferenceSyntax`,path:i,location:r(n)}}const isClosingCodeFence=e=>e.raw.trim()==="```";function parseCode(t,n){let i=n.content.startsWith("```")?n.content.substring(3):n.content;if(!t.languages.has(i))return t.error(e.ExpectedCodeFence,`Expected a registered language on the opening fence, not '${n.content}'`,r(n)),null;let a=n;if(!n.content.startsWith("```")){t.warning(e.LegacyInlineCodeFence,`'${i}' on its own line is deprecated - use '\`\`\`${i}' instead`,r(n));let o=t.reader.peekSignificant();if(o===void 0||o.indent<=n.indent||o.content!=="```"&&o.content!==`\`\`\`${i}`)return t.error(e.ExpectedCodeFence,`Expected an opening \`\`\`${i} fence after '${i}'`,r(n)),null;a=t.reader.takeSignificant()}let o=[];for(;;){let n=t.reader.takeRaw();if(n===void 0){t.error(e.UnclosedCodeBlock,"Unclosed inline code block - expected a closing ``` line",r(a));break}if(isClosingCodeFence(n))break;let i=0;for(;i<a.indent&&n.raw[i]===` `;)i++;o.push(n.raw.substring(i))}return{kind:`CodeBlockSyntax`,language:i,code:o.join(`
|
|
2
|
+
`),location:r(n)}}function parseHandler(t,i){let a=t.peekChild(i.indent);if(a===void 0)return t.error(e.HandlerWithoutImplementation,`Expected a 'file' directive or an inline code block in the handler`,r(i)),null;if(t.reader.takeSignificant(),n(a.content)===`implementation`)return parseImplementation(t,i,a);let o=isFile(a)?parseFile(t,a):null,s=o===null&&isCode(t,a)?parseCode(t,a):null;if(o!==null||s!==null){let a=t.peekChild(i.indent);return a!==void 0&&n(a.content)===`implementation`&&(t.error(e.ConflictingImplementationSources,`A handler cannot mix wrapped and direct sources.`,r(a)),t.skipBlock(i.indent)),{kind:`HandlerSyntax`,file:o,code:s,implementation:null,location:r(i)}}return t.error(e.UnknownHandlerDirective,`Unexpected '${a.content}' in handler - expected 'file <path>' or an inline code block`,r(a)),t.skipBlock(i.indent),null}function parseImplementation(t,i,a){let o=parseImplementationWrapper(t,a);for(let a=t.peekChild(i.indent);a!==void 0;a=t.peekChild(i.indent))t.reader.takeSignificant(),t.error(n(a.content)===`implementation`?e.InvalidImplementationBlock:e.ConflictingImplementationSources,`A handler has one implementation wrapper and cannot mix wrapped and direct sources.`,r(a)),isCode(t,a)?parseCode(t,a):t.skipBlock(a.indent);return{kind:`HandlerSyntax`,...o,location:r(i)}}function parseImplementationWrapper(o,s){let c=[],l=null,u=null,d=!1;s.content!==`implementation`&&o.error(e.InvalidImplementationBlock,`Expected 'implementation' with no operand.`,r(s));for(let f=o.peekChild(s.indent);f!==void 0;f=o.peekChild(s.indent))if(o.reader.takeSignificant(),n(f.content)===`hint`||a.test(f.content)){let n=a.exec(f.content),s=n===null?null:t(n[1]);i(s)?o.error(e.InvalidImplementationHint,`Expected 'hint' followed by one nonblank quoted string.`,r(f)):c.push({kind:`ImplementationHintSyntax`,text:s,location:r(f)});let l=o.peekChild(f.indent);l!==void 0&&(o.error(e.InvalidImplementationHint,`A hint cannot have children.`,r(l)),o.skipBlock(f.indent))}else if(isFile(f)||f.content.startsWith("```")){d&&o.error(e.ConflictingImplementationSources,`An implementation has at most one file or inline payload.`,r(f));let t=isFile(f)?parseFile(o,f):null,n=t===null?parseCode(o,f):null;d||(l=t,u=n),d=!0;let i=o.peekChild(f.indent);t!==null&&i!==void 0&&(o.error(e.InvalidImplementationBlock,`A file directive cannot have children.`,r(i)),o.skipBlock(f.indent))}else o.error(e.InvalidImplementationBlock,`Unexpected '${f.content}' in implementation - expected hint, file or a tagged fence.`,r(f)),o.skipBlock(f.indent);return{file:l,code:u,implementation:{kind:`ImplementationSyntax`,hints:c,location:r(s)}}}export{isClosingCodeFence,isCode,isFile,parseCode,parseFile,parseHandler,parseImplementationWrapper};
|
|
3
|
+
//# sourceMappingURL=ImplementationParser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImplementationParser.js","names":["hintPattern","firstWord","line","context","path","DiagnosticCodes","locationOf","language","tag","open","next","lines","strip","body","handler","file","code","extra","source","wrapper","hints","hasPayload","child","match","text","unescapeString","isBlankImplementationHint","nested","parsedFile","parsedCode"],"sources":["../../../../../../Compiler/Parsing/ImplementationParser.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 { CodeBlockSyntax, FileReferenceSyntax, HandlerSyntax, ImplementationHintSyntax, ImplementationSyntax } from '../Syntax/Implementations';\nimport { isBlankImplementationHint } from '../Text/ImplementationHintText';\nimport { unescapeString } from '../Text/StringLiteral';\nimport { firstWord } from './LineText';\nimport { ParserContext } from './ParserContext';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Match ImplementationHintText's White_Space set, not ECMAScript \\s. A hint stays on one CR/LF-delimited source line.\n// eslint-disable-next-line no-control-regex -- The shared whitespace set deliberately includes U+0009 through U+000D.\nconst hintPattern = new RegExp('^hint[\\\\u0009-\\\\u000d\\\\u0020\\\\u0085\\\\u00a0\\\\u1680\\\\u2000-\\\\u200a\\\\u2028\\\\u2029\\\\u202f\\\\u205f\\\\u3000]+\"((?:[^\"\\\\\\\\\\\\r\\\\n]|\\\\\\\\[^\\\\r\\\\n])*)\"$');\nexport const isFile = (line: SourceLine): boolean => firstWord(line.content) === 'file' && line.content.substring(4).trim().length > 0;\nexport const isCode = (context: ParserContext, line: SourceLine): boolean => line.content.startsWith('```') || context.languages.has(line.content);\n\nexport function parseFile(context: ParserContext, line: SourceLine): FileReferenceSyntax {\n const path = line.content.substring(4).trim();\n if (/^(?:[/\\\\]|[A-Za-z]:[/\\\\]|~[/\\\\])/.test(path)) {\n context.warning(DiagnosticCodes.AbsoluteFileReference, `'${path}' is an absolute path - a file reference is relative to the repository root, so it means the same thing on every machine`, locationOf(line));\n }\n return { kind: 'FileReferenceSyntax', path, location: locationOf(line) };\n}\n\nexport const isClosingCodeFence = (line: SourceLine): boolean => line.raw.trim() === '```';\n\nexport function parseCode(context: ParserContext, tag: SourceLine): CodeBlockSyntax | null {\n const language = tag.content.startsWith('```') ? tag.content.substring(3) : tag.content;\n if (!context.languages.has(language)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected a registered language on the opening fence, not '${tag.content}'`, locationOf(tag));\n return null;\n }\n let open = tag;\n if (!tag.content.startsWith('```')) {\n context.warning(DiagnosticCodes.LegacyInlineCodeFence, `'${language}' on its own line is deprecated - use '\\`\\`\\`${language}' instead`, locationOf(tag));\n const next = context.reader.peekSignificant();\n if (next === undefined || next.indent <= tag.indent || (next.content !== '```' && next.content !== `\\`\\`\\`${language}`)) {\n context.error(DiagnosticCodes.ExpectedCodeFence, `Expected an opening \\`\\`\\`${language} fence after '${language}'`, locationOf(tag));\n return null;\n }\n open = context.reader.takeSignificant();\n }\n const lines: string[] = [];\n for (;;) {\n const line = context.reader.takeRaw();\n if (line === undefined) {\n context.error(DiagnosticCodes.UnclosedCodeBlock, 'Unclosed inline code block - expected a closing ``` line', locationOf(open));\n break;\n }\n if (isClosingCodeFence(line)) break;\n let strip = 0;\n while (strip < open.indent && line.raw[strip] === ' ') strip++;\n lines.push(line.raw.substring(strip));\n }\n return { kind: 'CodeBlockSyntax', language, code: lines.join('\\n'), location: locationOf(tag) };\n}\n\nexport function parseHandler(context: ParserContext, handler: SourceLine): HandlerSyntax | null {\n const body = context.peekChild(handler.indent);\n if (body === undefined) {\n context.error(DiagnosticCodes.HandlerWithoutImplementation, \"Expected a 'file' directive or an inline code block in the handler\", locationOf(handler));\n return null;\n }\n context.reader.takeSignificant();\n if (firstWord(body.content) === 'implementation') return parseImplementation(context, handler, body);\n const file = isFile(body) ? parseFile(context, body) : null;\n const code = file === null && isCode(context, body) ? parseCode(context, body) : null;\n if (file !== null || code !== null) {\n const extra = context.peekChild(handler.indent);\n if (extra !== undefined && firstWord(extra.content) === 'implementation') {\n context.error(DiagnosticCodes.ConflictingImplementationSources, 'A handler cannot mix wrapped and direct sources.', locationOf(extra));\n context.skipBlock(handler.indent);\n }\n return { kind: 'HandlerSyntax', file, code, implementation: null, location: locationOf(handler) };\n }\n context.error(DiagnosticCodes.UnknownHandlerDirective, `Unexpected '${body.content}' in handler - expected 'file <path>' or an inline code block`, locationOf(body));\n context.skipBlock(handler.indent);\n return null;\n}\n\nfunction parseImplementation(context: ParserContext, handler: SourceLine, wrapper: SourceLine): HandlerSyntax {\n const source = parseImplementationWrapper(context, wrapper);\n for (let extra = context.peekChild(handler.indent); extra !== undefined; extra = context.peekChild(handler.indent)) {\n context.reader.takeSignificant();\n context.error(firstWord(extra.content) === 'implementation' ? DiagnosticCodes.InvalidImplementationBlock : DiagnosticCodes.ConflictingImplementationSources,\n 'A handler has one implementation wrapper and cannot mix wrapped and direct sources.', locationOf(extra));\n if (isCode(context, extra)) parseCode(context, extra);\n else context.skipBlock(extra.indent);\n }\n return { kind: 'HandlerSyntax', ...source, location: locationOf(handler) };\n}\n\nexport function parseImplementationWrapper(context: ParserContext, wrapper: SourceLine): { file: FileReferenceSyntax | null; code: CodeBlockSyntax | null; implementation: ImplementationSyntax } {\n const hints: ImplementationHintSyntax[] = [];\n let file: FileReferenceSyntax | null = null;\n let code: CodeBlockSyntax | null = null;\n let hasPayload = false;\n if (wrapper.content !== 'implementation') context.error(DiagnosticCodes.InvalidImplementationBlock, \"Expected 'implementation' with no operand.\", locationOf(wrapper));\n for (let child = context.peekChild(wrapper.indent); child !== undefined; child = context.peekChild(wrapper.indent)) {\n context.reader.takeSignificant();\n if (firstWord(child.content) === 'hint' || hintPattern.test(child.content)) {\n const match = hintPattern.exec(child.content);\n const text = match === null ? null : unescapeString(match[1]);\n if (isBlankImplementationHint(text)) context.error(DiagnosticCodes.InvalidImplementationHint, \"Expected 'hint' followed by one nonblank quoted string.\", locationOf(child));\n else hints.push({ kind: 'ImplementationHintSyntax', text: text!, location: locationOf(child) });\n const nested = context.peekChild(child.indent);\n if (nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationHint, 'A hint cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else if (isFile(child) || child.content.startsWith('```')) {\n if (hasPayload) context.error(DiagnosticCodes.ConflictingImplementationSources, 'An implementation has at most one file or inline payload.', locationOf(child));\n const parsedFile = isFile(child) ? parseFile(context, child) : null;\n const parsedCode = parsedFile === null ? parseCode(context, child) : null;\n if (!hasPayload) { file = parsedFile; code = parsedCode; }\n hasPayload = true;\n const nested = context.peekChild(child.indent);\n if (parsedFile !== null && nested !== undefined) {\n context.error(DiagnosticCodes.InvalidImplementationBlock, 'A file directive cannot have children.', locationOf(nested));\n context.skipBlock(child.indent);\n }\n } else {\n context.error(DiagnosticCodes.InvalidImplementationBlock, `Unexpected '${child.content}' in implementation - expected hint, file or a tagged fence.`, locationOf(child));\n context.skipBlock(child.indent);\n }\n }\n return { file, code, implementation: { kind: 'ImplementationSyntax', hints, location: locationOf(wrapper) } };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./FileImportParser.js";import"./FeatureBody.js";import"./ModuleBody.js";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{DiagnosticCodes as e}from"../Diagnostics/DiagnosticCodes.js";import{eventDeclarations as t}from"../Syntax/EventDeclarations.js";import{AuthoringProductionResolver as n}from"../Syntax/AuthoringProductionResolver.js";import{requiresExplicitDestinations as r}from"../Syntax/ProductionDestinations.js";function validateInlineEvents(i,a){let o=[],inFeature=e=>{o.push(...e.slices),e.features.forEach(inFeature)};i.modules.forEach(e=>e.features.forEach(inFeature));let s=/* @__PURE__ */ new Map;for(let e of o.flatMap(t))s.set(e.name,(s.get(e.name)??0)+1);let c=new Set(i.imports.map(e=>e.qualifiedName.split(`.`).at(-1))),l=new n(i);for(let{slice:t,command:n}of o.flatMap(e=>e.commands.map(t=>({slice:e,command:t})))){let i=n.produces.filter(e=>l.isEventProduction(e,t)),o=n.properties.find(e=>e.isIdentifier)?.name,u=r(n,{resolver:l,slice:t});for(let t of i){let r=t.inlineEvent;r!==null&&((s.get(r.name)??0)>1||c.has(r.name))&&a.error(e.InlineEventCollision,`Inline event '${r.name}' collides with another event declaration or import`,t.location),u&&t.for===null&&a.error(e.ExplicitProducesTargetsRequired,`Production '${t.event}' in command '${n.name}' must state 'for' explicitly - every production must state 'for' when destinations differ`,t.location);let i=t.for?.kind===`PathExpressionSyntax`?t.for.path:t.for===null&&r!==null?o:void 0;if(o!==void 0&&i===o)for(let n of t.mappings.filter(e=>e.source.kind===`PathExpressionSyntax`&&e.source.path===o)){let i=`Event '${t.event}' copies command identifier '${o}' into payload property '${n.property}' although it already identifies the event source`;r===null?a.information(e.EventSourceIdInPayload,i,n.location):a.warning(e.EventSourceIdInPayload,i,n.location)}}}}export{validateInlineEvents};
|
|
2
|
+
//# sourceMappingURL=InlineEventValidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineEventValidator.js","names":["slices","feature","application","module","eventCounts","event","eventDeclarations","importedNames","value","resolver","AuthoringProductionResolver","slice","events","command","production","identifier","property","mixed","requiresExplicitDestinations","inline","context","DiagnosticCodes","destination","mapping","message"],"sources":["../../../../../../Compiler/Parsing/InlineEventValidator.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 { eventDeclarations } from '../Syntax/EventDeclarations';\nimport { AuthoringProductionResolver } from '../Syntax/AuthoringProductionResolver';\nimport { requiresExplicitDestinations } from '../Syntax/ProductionDestinations';\nimport { ApplicationSyntax, FeatureSyntax, SliceSyntax } from '../Syntax/Structure';\nimport { ParserContext } from './ParserContext';\n\nexport function validateInlineEvents(application: ApplicationSyntax, context: ParserContext): void {\n const slices: SliceSyntax[] = [];\n const inFeature = (feature: FeatureSyntax): void => {\n slices.push(...feature.slices);\n feature.features.forEach(inFeature);\n };\n application.modules.forEach(module => module.features.forEach(inFeature));\n const eventCounts = new Map<string, number>();\n for (const event of slices.flatMap(eventDeclarations)) eventCounts.set(event.name, (eventCounts.get(event.name) ?? 0) + 1);\n const importedNames = new Set(application.imports.map(value => value.qualifiedName.split('.').at(-1)));\n const resolver = new AuthoringProductionResolver(application);\n for (const { slice, command } of slices.flatMap(slice => slice.commands.map(command => ({ slice, command })))) {\n const events = command.produces.filter(production => resolver.isEventProduction(production, slice));\n const identifier = command.properties.find(property => property.isIdentifier)?.name;\n const mixed = requiresExplicitDestinations(command, { resolver, slice });\n for (const production of events) {\n const inline = production.inlineEvent;\n if (inline !== null && ((eventCounts.get(inline.name) ?? 0) > 1 || importedNames.has(inline.name))) {\n context.error(DiagnosticCodes.InlineEventCollision, `Inline event '${inline.name}' collides with another event declaration or import`, production.location);\n }\n if (mixed && production.for === null) {\n context.error(DiagnosticCodes.ExplicitProducesTargetsRequired, `Production '${production.event}' in command '${command.name}' must state 'for' explicitly - every production must state 'for' when destinations differ`, production.location);\n }\n const destination = production.for?.kind === 'PathExpressionSyntax' ? production.for.path : production.for === null && inline !== null ? identifier : undefined;\n if (identifier === undefined || destination !== identifier) continue;\n for (const mapping of production.mappings.filter(mapping => mapping.source.kind === 'PathExpressionSyntax' && mapping.source.path === identifier)) {\n const message = `Event '${production.event}' copies command identifier '${identifier}' into payload property '${mapping.property}' although it already identifies the event source`;\n if (inline === null) context.information(DiagnosticCodes.EventSourceIdInPayload, message, mapping.location);\n else context.warning(DiagnosticCodes.EventSourceIdInPayload, message, mapping.location);\n }\n }\n }\n}\n"],"mappings":"sWAUA,SAAgB,qBAAqB,EAAgC,EAA8B,CAC/F,IAAMA,EAAwB,CAAC,EACzB,UAAa,GAAiC,CAChDA,EAAO,KAAK,GAAGC,EAAQ,MAAM,EAC7BA,EAAQ,SAAS,QAAQ,SAAS,CACtC,EACAC,EAAY,QAAQ,QAAQ,GAAUC,EAAO,SAAS,QAAQ,SAAS,CAAC,EACxE,IAAMC,kBAAc,IAAI,IACxB,IAAK,IAAMC,KAASL,EAAO,QAAQM,CAAiB,EAAGF,EAAY,IAAIC,EAAM,MAAOD,EAAY,IAAIC,EAAM,IAAI,GAAK,GAAK,CAAC,EACzH,IAAME,EAAgB,IAAI,IAAIL,EAAY,QAAQ,IAAI,GAASM,EAAM,cAAc,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAC/FC,EAAW,IAAIC,EAA4BR,CAAW,EAC5D,IAAK,GAAM,CAAE,QAAO,aAAaF,EAAO,QAAQ,GAASW,EAAM,SAAS,IAAI,IAAY,CAAE,QAAO,SAAQ,EAAE,CAAC,EAAG,CAC3G,IAAMC,EAASC,EAAQ,SAAS,OAAO,GAAcJ,EAAS,kBAAkBK,EAAYH,CAAK,CAAC,EAC5FI,EAAaF,EAAQ,WAAW,KAAK,GAAYG,EAAS,YAAY,CAAC,EAAE,KACzEC,EAAQC,EAA6BL,EAAS,CAAE,WAAU,OAAM,CAAC,EACvE,IAAK,IAAMC,KAAcF,EAAQ,CAC7B,IAAMO,EAASL,EAAW,YACtBK,IAAW,QAAUf,EAAY,IAAIe,EAAO,IAAI,GAAK,GAAK,GAAKZ,EAAc,IAAIY,EAAO,IAAI,IAC5FC,EAAQ,MAAMC,EAAgB,qBAAsB,iBAAiBF,EAAO,KAAK,qDAAsDL,EAAW,QAAQ,EAE1JG,GAASH,EAAW,MAAQ,MAC5BM,EAAQ,MAAMC,EAAgB,gCAAiC,eAAeP,EAAW,MAAM,gBAAgBD,EAAQ,KAAK,4FAA6FC,EAAW,QAAQ,EAEhP,IAAMQ,EAAcR,EAAW,KAAK,OAAS,uBAAyBA,EAAW,IAAI,KAAOA,EAAW,MAAQ,MAAQK,IAAW,KAAOJ,EAAa,IAAA,GACtJ,GAAIA,IAAe,IAAA,IAAaO,IAAgBP,EAChD,IAAK,IAAMQ,KAAWT,EAAW,SAAS,OAAO,GAAWS,EAAQ,OAAO,OAAS,wBAA0BA,EAAQ,OAAO,OAASR,CAAU,EAAG,CAC/I,IAAMS,EAAU,UAAUV,EAAW,MAAM,+BAA+BC,EAAW,2BAA2BQ,EAAQ,SAAS,mDAC7HJ,IAAW,KAAMC,EAAQ,YAAYC,EAAgB,uBAAwBG,EAASD,EAAQ,QAAQ,EACrGH,EAAQ,QAAQC,EAAgB,uBAAwBG,EAASD,EAAQ,QAAQ,CAC1F,CACJ,CACJ,CACJ"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import"../../_virtual/_virtual/_rolldown/runtime.js";import{pattern as e}from"../Text/patterns.js";import{firstWord as t,unescapeIdentifier as n}from"./LineText.js";import{locationOf as r}from"./SourceLine.js";import{parseDescription as i}from"./DescriptionParser.js";import{validateInteractionBodies as a}from"./InteractionAlternatives.js";const o=e(`^form\\s+[A-Za-z_]\\w*\\s+for\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),s=e(`^(execute|invokes)\\s+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),c=e(`^field\\s+([\\w.]+)(?:\\s|$)`),l=e(`^with\\s+([A-Za-z_]\\w*)\\s+from\\s+.+$`),u=e(`^(@?[\\w.]+)\\s*=(?!=|>)\\s*.+$`),d=e(`^parameter\\s+([A-Za-z_]\\w*)(?:\\s+([\\w.]+(?:\\[\\])?))?$`),f=/* @__PURE__ */ new Set([`refresh`,`navigate`,`open`,`close`,`set`,`notify`,`confirm`,`raise`,`on`,`when`,`otherwise`]);function collectInputUses(p,m){let h=[],g=/* @__PURE__ */ new Set,_=[],v=t(m.content)===`behavior`,y=null,recognize=e=>{for(;h.length>0&&h[h.length-1].indent>=e.indent;)h.pop();let i=v&&h.length===0?d.exec(e.content):null;i!==null&&g.add(i[1]);let a=o.exec(e.content),m=s.exec(e.content);if(a!==null)h.push({command:a[1],kind:`form`,indent:e.indent});else if(m!==null)h.push({command:m[2],kind:m[1],indent:e.indent});else if(f.has(t(e.content)))h.push({command:``,kind:`other`,indent:e.indent});else{let t=h.at(-1);if(t===void 0||t.kind===`other`)return;let i=(t.kind===`form`?c:t.kind===`execute`?l:u).exec(e.content);i!==null&&_.push({command:t.command,property:n(i[1]),scope:p.scope,location:r(e)})}};recognize(m);let b=[m];for(let n=p.peekChild(m.indent);n!==void 0;n=p.peekChild(m.indent)){for(p.reader.takeSignificant();h.length>0&&h[h.length-1].indent>=n.indent;)h.pop();o.test(m.content)&&t(n.content)===`description`&&h.at(-1)?.kind===`form`?y=i(p,n,y,`Form '${m.content.split(e(`\\s+`))[1]}'`):n.content.startsWith("```")?p.skipFencedBody():(b.push(n),recognize(n))}a(p,b);for(let e of _)p.inputUses.push(g.has(e.command)?{...e,isParameter:!0}:e)}export{collectInputUses};
|
|
2
|
+
//# sourceMappingURL=InputUses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InputUses.js","names":["form","pattern","execution","field","argument","mapping","parameter","actionBoundaries","owners","parameters","inputs","isBehavior","firstWord","header","formDescription","line","declared","formMatch","execute","owner","supplied","unescapeIdentifier","context","locationOf","lines","child","parseDescription","validateInteractionBodies","input"],"sources":["../../../../../../Compiler/Parsing/InputUses.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 { SourceLocation } from '../Diagnostics/SourceLocation';\nimport { pattern } from '../Text/patterns';\nimport { firstWord, unescapeIdentifier } from './LineText';\nimport { validateInteractionBodies } from './InteractionAlternatives';\nimport { ParserContext } from './ParserContext';\nimport { parseDescription } from './DescriptionParser';\nimport { locationOf, SourceLine } from './SourceLine';\n\n// Typed authoring facts from bodies the TS syntax tree does not yet model. Never serialized as ESM.\nexport interface InputUse {\n readonly command: string;\n readonly property: string;\n readonly scope: readonly string[];\n readonly location: SourceLocation;\n readonly isParameter?: boolean;\n}\n\ninterface InputOwner { command: string; kind: 'form' | 'execute' | 'invokes' | 'other'; indent: number }\nconst form = pattern('^form\\\\s+[A-Za-z_]\\\\w*\\\\s+for\\\\s+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$');\nconst execution = pattern('^(execute|invokes)\\\\s+([A-Za-z_]\\\\w*(?:\\\\.\\\\w+)*)$');\nconst field = pattern('^field\\\\s+([\\\\w.]+)(?:\\\\s|$)');\nconst argument = pattern('^with\\\\s+([A-Za-z_]\\\\w*)\\\\s+from\\\\s+.+$');\nconst mapping = pattern('^(@?[\\\\w.]+)\\\\s*=(?!=|>)\\\\s*.+$');\nconst parameter = pattern('^parameter\\\\s+([A-Za-z_]\\\\w*)(?:\\\\s+([\\\\w.]+(?:\\\\[\\\\])?))?$');\nconst actionBoundaries = new Set(['refresh', 'navigate', 'open', 'close', 'set', 'notify', 'confirm', 'raise', 'on', 'when', 'otherwise']);\n\n// A single forward walk, tracking owners by indentation and skipping fences as opaque text.\nexport function collectInputUses(context: ParserContext, header: SourceLine): void {\n const owners: InputOwner[] = [];\n const parameters = new Set<string>();\n const inputs: InputUse[] = [];\n const isBehavior = firstWord(header.content) === 'behavior';\n let formDescription: string | null = null;\n const recognize = (line: SourceLine): void => {\n while (owners.length > 0 && owners[owners.length - 1].indent >= line.indent) owners.pop();\n const declared = isBehavior && owners.length === 0 ? parameter.exec(line.content) : null;\n if (declared !== null) parameters.add(declared[1]);\n const formMatch = form.exec(line.content);\n const execute = execution.exec(line.content);\n if (formMatch !== null) owners.push({ command: formMatch[1], kind: 'form', indent: line.indent });\n else if (execute !== null) owners.push({ command: execute[2], kind: execute[1] as 'execute' | 'invokes', indent: line.indent });\n else if (actionBoundaries.has(firstWord(line.content))) owners.push({ command: '', kind: 'other', indent: line.indent });\n else {\n const owner = owners.at(-1);\n if (owner === undefined || owner.kind === 'other') return;\n const supplied = (owner.kind === 'form' ? field : owner.kind === 'execute' ? argument : mapping).exec(line.content);\n if (supplied !== null) inputs.push({ command: owner.command, property: unescapeIdentifier(supplied[1]), scope: context.scope, location: locationOf(line) });\n }\n };\n recognize(header);\n const lines = [header];\n for (let child = context.peekChild(header.indent); child !== undefined; child = context.peekChild(header.indent)) {\n context.reader.takeSignificant();\n while (owners.length > 0 && owners[owners.length - 1].indent >= child.indent) owners.pop();\n if (form.test(header.content) && firstWord(child.content) === 'description' && owners.at(-1)?.kind === 'form') {\n formDescription = parseDescription(context, child, formDescription, `Form '${header.content.split(pattern('\\\\s+'))[1]}'`);\n } else if (child.content.startsWith('```')) context.skipFencedBody();\n else {\n lines.push(child);\n recognize(child);\n }\n }\n validateInteractionBodies(context, lines);\n // Parameters may be declared after their bindings; commit facts once their scope is complete.\n for (const input of inputs) context.inputUses.push(parameters.has(input.command) ? { ...input, isParameter: true } : input);\n}\n"],"mappings":"qVAqBA,MAAMA,EAAOC,EAAQ,+DAA+D,EAC9EC,EAAYD,EAAQ,oDAAoD,EACxEE,EAAQF,EAAQ,8BAA8B,EAC9CG,EAAWH,EAAQ,yCAAyC,EAC5DI,EAAUJ,EAAQ,iCAAiC,EACnDK,EAAYL,EAAQ,6DAA6D,EACjFM,kBAAmB,IAAI,IAAI,CAAC,UAAW,WAAY,OAAQ,QAAS,MAAO,SAAU,UAAW,QAAS,KAAM,OAAQ,WAAW,CAAC,EAGzI,SAAgB,iBAAiB,EAAwB,EAA0B,CAC/E,IAAMC,EAAuB,CAAC,EACxBC,kBAAa,IAAI,IACjBC,EAAqB,CAAC,EACtBC,EAAaC,EAAUC,EAAO,OAAO,IAAM,WAC7CC,EAAiC,KAC/B,UAAa,GAA2B,CAC1C,KAAON,EAAO,OAAS,GAAKA,EAAOA,EAAO,OAAS,EAAE,CAAC,QAAUO,EAAK,QAAQP,EAAO,IAAI,EACxF,IAAMQ,EAAWL,GAAcH,EAAO,SAAW,EAAIF,EAAU,KAAKS,EAAK,OAAO,EAAI,KAChFC,IAAa,MAAMP,EAAW,IAAIO,EAAS,EAAE,EACjD,IAAMC,EAAYjB,EAAK,KAAKe,EAAK,OAAO,EAClCG,EAAUhB,EAAU,KAAKa,EAAK,OAAO,EAC3C,GAAIE,IAAc,KAAMT,EAAO,KAAK,CAAE,QAASS,EAAU,GAAI,KAAM,OAAQ,OAAQF,EAAK,MAAO,CAAC,OAC3F,GAAIG,IAAY,KAAMV,EAAO,KAAK,CAAE,QAASU,EAAQ,GAAI,KAAMA,EAAQ,GAA6B,OAAQH,EAAK,MAAO,CAAC,OACzH,GAAIR,EAAiB,IAAIK,EAAUG,EAAK,OAAO,CAAC,EAAGP,EAAO,KAAK,CAAE,QAAS,GAAI,KAAM,QAAS,OAAQO,EAAK,MAAO,CAAC,MAClH,CACD,IAAMI,EAAQX,EAAO,GAAG,EAAE,EAC1B,GAAIW,IAAU,IAAA,IAAaA,EAAM,OAAS,QAAS,OACnD,IAAMC,GAAYD,EAAM,OAAS,OAAShB,EAAQgB,EAAM,OAAS,UAAYf,EAAWC,EAAA,CAAS,KAAKU,EAAK,OAAO,EAC9GK,IAAa,MAAMV,EAAO,KAAK,CAAE,QAASS,EAAM,QAAS,SAAUE,EAAmBD,EAAS,EAAE,EAAG,MAAOE,EAAQ,MAAO,SAAUC,EAAWR,CAAI,CAAE,CAAC,CAC9J,CACJ,EACA,UAAUF,CAAM,EAChB,IAAMW,EAAQ,CAACX,CAAM,EACrB,IAAK,IAAIY,EAAQH,EAAQ,UAAUT,EAAO,MAAM,EAAGY,IAAU,IAAA,GAAW,EAAQH,EAAQ,UAAUT,EAAO,MAAM,EAAG,CAE9G,IADAS,EAAQ,OAAO,gBAAgB,EACxBd,EAAO,OAAS,GAAKA,EAAOA,EAAO,OAAS,EAAE,CAAC,QAAUiB,EAAM,QAAQjB,EAAO,IAAI,EACrFR,EAAK,KAAKa,EAAO,OAAO,GAAKD,EAAUa,EAAM,OAAO,IAAM,eAAiBjB,EAAO,GAAG,EAAE,CAAC,EAAE,OAAS,OACnG,EAAkBkB,EAAiBJ,EAASG,EAAOX,EAAiB,SAASD,EAAO,QAAQ,MAAMZ,EAAQ,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,EACjHwB,EAAM,QAAQ,WAAW,KAAK,EAAGH,EAAQ,eAAe,GAE/DE,EAAM,KAAKC,CAAK,EAChB,UAAUA,CAAK,EAEvB,CACAE,EAA0BL,EAASE,CAAK,EAExC,IAAK,IAAMI,KAASlB,EAAQY,EAAQ,UAAU,KAAKb,EAAW,IAAImB,EAAM,OAAO,EAAI,CAAE,GAAGA,EAAO,YAAa,EAAK,EAAIA,CAAK,CAC9H"}
|
|
@@ -0,0 +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{firstWord as r}from"./LineText.js";import{locationOf as i}from"./SourceLine.js";import{parseCondition as a}from"./ConditionParser.js";import{validateCondition as o}from"./GuardedActionParser.js";import{LineReader as s}from"./LineReader.js";import{ParserContext as c}from"./ParserContext.js";const l=n(`^when${t}+([^\\n]+)${t}+execute${t}+([A-Za-z_]\\w*(?:\\.\\w+)*)$`),u=n(`^on${t}+([^\\n]+)$`),d=n(`^where${t}+([^\\n]+)$`),f=/* @__PURE__ */ new Set([`execute`,`navigate`,`open`,`close`,`refresh`,`set`,`notify`,`confirm`,`raise`]);function validateInteractionBodies(t,n){for(let s=0;s<n.length;s++){let c=n[s],p=u.exec(c.content);if(p===null||p[1].startsWith(`row-click `))continue;let m=[];for(let e=s+1;e<n.length&&n[e].indent>c.indent;e++)m.push(n[e]);let h=m.filter(e=>e.indent===m[0]?.indent),g=h.filter(e=>[`when`,`otherwise`].includes(r(e.content))),_=[`click`,`double click`,`select`].includes(p[1].trim()),v=h.filter(e=>d.test(e.content)),y=!1;for(let n of g){let s=r(n.content)===`when`,c=s?l.exec(n.content):null;if(s){y&&t.error(e.MisplacedActionOtherwise,`A 'when' alternative must precede 'otherwise'`,i(n));let r=a(t,c?.[1]??n.content.slice(4).trim(),i(n),!0);r!==null&&o(t,r),c!==null&&t.error(e.InlineInteractionAlternative,`Interaction alternatives require an indented action list, not 'when <condition> execute <Command>'`,i(n))}else(y||n.content!==`otherwise`)&&t.error(e.MisplacedActionOtherwise,`An interaction permits one final block-form 'otherwise'`,i(n)),y=!0;let u=m[m.indexOf(n)+1];c===null&&(u===void 0||u.indent<=n.indent||!f.has(r(u.content)))&&t.error(e.InteractionAlternativeWithoutActions,`An interaction alternative requires a non-empty action list`,i(n))}if(g.length>0&&(_||t.error(e.UnsupportedInteractionAlternatives,`Interaction alternatives are only supported on click, double click and select`,i(c)),(v.length>0||h.some(e=>f.has(r(e.content))))&&t.error(e.MixedInteractionAlternatives,`Interaction alternatives cannot mix with plain actions or 'where'`,i(c)),g.some(e=>r(e.content)===`when`)||t.error(e.GuardedActionWithoutAlternatives,`A guarded interaction requires at least one 'when' alternative`,i(c))),_)for(let e of v)deprecateWhere(t,e)}}function deprecateWhere(t,n){let r=new c(new s([]));r.sourceOptions=t.sourceOptions;let l=a(r,d.exec(n.content)[1].trim(),i(n),!0);l!==null&&o(r,l);let u=`Opaque 'where' on click, double click and select is deprecated; use block-form 'when' item conditions`;l!==null&&r.diagnostics.length===0?t.warning(e.LegacyInteractionWhere,u,i(n)):t.information(e.LegacyInteractionWhere,u,i(n))}export{validateInteractionBodies};
|
|
2
|
+
//# sourceMappingURL=InteractionAlternatives.js.map
|