diff --git a/package.json b/package.json index 37cea5c..69a1e5e 100644 --- a/package.json +++ b/package.json @@ -21,8 +21,10 @@ ], "devDependencies": { "@slicky/webpack-loader": "^0.1.9", + "@types/chai": "^4.0.5", "@types/gulp": "^4.0.4", "@types/merge2": "^1.1.1", + "@types/node": "^8.0.53", "gulp": "github:gulpjs/gulp#4.0", "gulp-concat": "^2.6.1", "gulp-sass": "^3.1.0", diff --git a/packages/compiler-cli/analyzers/directiveAnalyzer.ts b/packages/compiler-cli/analyzers/directiveAnalyzer.ts new file mode 100644 index 0000000..16fe7ba --- /dev/null +++ b/packages/compiler-cli/analyzers/directiveAnalyzer.ts @@ -0,0 +1,644 @@ +import {exists, camelCaseToHyphens, forEach, find, merge, unique, hash} from '@slicky/utils'; +import {TemplateEncapsulation} from '@slicky/templates/templates'; +import { + DirectiveDefinitionType, DirectiveDefinitionInput, DirectiveDefinitionOutput, DirectiveDefinitionElement, + DirectiveDefinitionEvent, DirectiveDefinitionChildDirective, DirectiveDefinitionChildrenDirective, DirectiveDefinition, + DirectiveDefinitionFilterMetadata, + createDirectiveMetadata +} from '@slicky/core/metadata'; +import { + resolveRawRequire, resolveIdentifier, resolveIdentifierAsFlatNodesList, lookupSourceFile, + ResolvedIdentifier, RequiredFile, +} from '@slicky/typescript-api-utils'; +import * as ts from 'typescript'; +import * as path from 'path'; +import {FilterAnalyzer} from './filterAnalyzer'; + + +export declare interface AnalyzedDirective +{ + dependencies: Array, + definition: DirectiveDefinition, +} + + +export class DirectiveAnalyzer +{ + + + private filterAnalyzer: FilterAnalyzer; + + private compilerOptions: ts.CompilerOptions; + + private moduleResolutionHost: ts.ModuleResolutionHost; + + private storage: {[uniqueName: string]: AnalyzedDirective} = {}; + + + constructor(filterAnalyzer: FilterAnalyzer, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost) + { + this.filterAnalyzer = filterAnalyzer; + this.compilerOptions = compilerOptions; + this.moduleResolutionHost = moduleResolutionHost; + } + + + public analyzeDirective(directiveClass: ts.ClassDeclaration, need: boolean = true, includeInnerDirectiveNodes: boolean = true): AnalyzedDirective + { + const className = (directiveClass.name).text; + const sourceFile = lookupSourceFile(directiveClass); + + const uniqueName = `${sourceFile.fileName}:${className}`; + + if (exists(this.storage[uniqueName])) { + return this.storage[uniqueName]; + } + + const directive = this.analyzeDirectiveDecorator(sourceFile, className, directiveClass, includeInnerDirectiveNodes); + + if (!exists(directive)) { + if (need) { + throw new Error(`Class ${className} is not a directive or component. Please add @Directive() or @Component() class decorator.`); + } + + return; + } + + this.analyzeDirectivePropertiesAndMethods(className, directiveClass, directive, includeInnerDirectiveNodes); + + directive.dependencies = unique(directive.dependencies); + + return this.storage[uniqueName] = directive; + } + + + private analyzeDirectiveDecorator(sourceFile: ts.SourceFile, className: string, directiveClass: ts.ClassDeclaration, includeInnerDirectiveNodes: boolean): AnalyzedDirective + { + let directiveDecorator: ts.Decorator = undefined; + + ts.forEachChild(directiveClass, (node: ts.Node) => { + if (ts.isDecorator(node)) { + const decorator = node; + + if (ts.isCallExpression(decorator.expression)) { + const callExpression = decorator.expression; + + if (ts.isIdentifier(callExpression.expression)) { + const identifier = callExpression.expression; + + if (identifier.text === 'Directive' || identifier.text === 'Component') { + directiveDecorator = decorator; + } + } + } + + } + }); + + if (!directiveDecorator) { + return; + } + + const callExpression = directiveDecorator.expression; + const callName = (callExpression.expression).text; + + if (!callExpression.arguments.length || !ts.isObjectLiteralExpression(callExpression.arguments[0])) { + throw new Error(`${callName} ${className}: missing metadata configuration object.`); + } + + let dependencies: Array = []; + + const configuration = callExpression.arguments[0]; + const definition = createDirectiveMetadata({ + type: callName === 'Directive' ? DirectiveDefinitionType.Directive : DirectiveDefinitionType.Component, + id: '', + className: className, + selector: '', + }); + + ts.forEachChild(configuration, (configurationProperty: ts.PropertyAssignment) => { + if (ts.isIdentifier(configurationProperty.name)) { + const property = configurationProperty.name; + + if (property.text === 'selector') { + if (!ts.isStringLiteral(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: selector should be a string.`); + } + + const selectorName = (configurationProperty.initializer).text; + + if (definition.type === DirectiveDefinitionType.Component) { + if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(selectorName) || selectorName.indexOf('-') < 0) { + throw new Error(`${callName} ${className}: name should be a lowercased string with at least one dash.`); + } + } + + definition.selector = selectorName; + + } else if (property.text === 'id') { + if (!ts.isStringLiteral(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: id should be a string.`); + } + + definition.id = (configurationProperty.initializer).text; + + } else if (property.text === 'template') { + let templateInitializer = configurationProperty.initializer; + + if (ts.isIdentifier(templateInitializer)) { + const resolvedTemplateInitializer = resolveIdentifier(templateInitializer, this.compilerOptions, this.moduleResolutionHost); + + dependencies = merge(dependencies, resolvedTemplateInitializer.dependencies); + templateInitializer = resolvedTemplateInitializer.node; + } + + if (ts.isStringLiteral(templateInitializer)) { + definition.template = (templateInitializer).text; + + } else if (ts.isNoSubstitutionTemplateLiteral(templateInitializer)) { + definition.template = (templateInitializer).text; + + } else if (ts.isCallExpression(templateInitializer)) { + const template = this.requireRawFile(callName, className, 'template', sourceFile.fileName, templateInitializer, 'html'); + + dependencies.push(template.path); + definition.template = template.source; + + } else { + throw new Error(`${callName} ${className}: template should be a string, template string, arrow function, function expression or simple require call.`); + } + + } else if (property.text === 'styles') { + if (!ts.isArrayLiteralExpression(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: styles should be an array of string or simple require calls.`); + } + + definition.styles = []; + + ts.forEachChild(configurationProperty.initializer, (innerNode: ts.Node) => { + if (ts.isStringLiteral(innerNode)) { + definition.styles.push((innerNode).text); + + } else if (ts.isCallExpression(innerNode)) { + const styles = this.requireRawFile(callName, className, 'styles', sourceFile.fileName, innerNode, 'css'); + + dependencies.push(styles.path); + definition.styles.push(styles.source); + + } else { + throw new Error(`${callName} ${className}: styles should be an array of string or simple require calls.`); + } + }); + + } else if (property.text === 'encapsulation') { + if (!ts.isPropertyAccessExpression(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.`); + } + + const encapsulationPropertyAccess = configurationProperty.initializer; + + if (!ts.isIdentifier(encapsulationPropertyAccess.expression)) { + throw new Error(`${callName} ${className}: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.`); + } + + const encapsulationExpressionIdentifier = encapsulationPropertyAccess.expression; + + if (encapsulationExpressionIdentifier.text !== 'TemplateEncapsulation') { + throw new Error(`${callName} ${className}: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.`); + } + + const encapsulationName = (encapsulationPropertyAccess.name).text; + + if (encapsulationName !== 'None' && encapsulationName !== 'Emulated' && encapsulationName !== 'Native') { + throw new Error(`${callName} ${className}: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.`); + } + + definition.encapsulation = TemplateEncapsulation[encapsulationName]; + + } else if (property.text === 'override') { + if (!ts.isIdentifier(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: override should be an identifier.`); + } + + const overrideClass = resolveIdentifier(configurationProperty.initializer, this.compilerOptions, this.moduleResolutionHost); + + if (!overrideClass) { + throw new Error(`${callName} ${className}: override class ${(configurationProperty.initializer).text} was not found.`); + } + + if (!ts.isClassDeclaration(overrideClass.node)) { + throw new Error(`${callName} ${className}: override class should be a ClassDeclaration.`); + } + + const overrideDirective = this.analyzeDirective(overrideClass.node); + + dependencies = merge(dependencies, overrideClass.dependencies); + dependencies = merge(dependencies, overrideDirective.dependencies); + definition.override = { + localName: (configurationProperty.initializer).text, + originalName: overrideClass.originalName, + imported: overrideClass.imported, + path: overrideClass.sourceFile.fileName, + metadata: overrideDirective.definition, + node: includeInnerDirectiveNodes ? overrideClass.node : undefined, + }; + + } else if (property.text === 'directives') { + if (!ts.isArrayLiteralExpression(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: directives should be an array of identifiers.`); + } + + ts.forEachChild(configurationProperty.initializer, (innerDirective: ts.Node) => { + if (!ts.isIdentifier(innerDirective)) { + throw new Error(`${callName} ${className}: directives should be an array of identifiers.`); + } + + const innerDirectiveClasses = resolveIdentifierAsFlatNodesList(innerDirective, this.compilerOptions, this.moduleResolutionHost); + + dependencies = merge(dependencies, innerDirectiveClasses.dependencies); + + if (!innerDirectiveClasses.nodes.length) { + throw new Error(`${callName} ${className}: directive class or class list ${(innerDirective).text} was not found.`); + } + + forEach(innerDirectiveClasses.nodes, (innerDirectiveClass: ResolvedIdentifier) => { + if (!ts.isClassDeclaration(innerDirectiveClass.node)) { + throw new Error(`${callName} ${className}: directives must contain only a list of ClassDirectives.`); + } + + if (sourceFile !== innerDirectiveClass.sourceFile) { + const isExported = find(innerDirectiveClass.node.modifiers || [], (modifier: ts.Modifier) => { + return modifier.kind === ts.SyntaxKind.ExportKeyword; + }); + + if (!isExported) { + throw new Error(`${callName} ${className}: can not use inner directive ${innerDirectiveClass.originalName}, class is not exported.`); + } + } + + const innerDirectiveClassMetadata = this.analyzeDirective(innerDirectiveClass.node); + + dependencies = merge(dependencies, innerDirectiveClassMetadata.dependencies); + definition.directives.push({ + localName: innerDirectiveClassMetadata.definition.className, + originalName: innerDirectiveClass.originalName, + imported: innerDirectiveClass.imported, + metadata: innerDirectiveClassMetadata.definition, + path: innerDirectiveClass.sourceFile.fileName, + node: includeInnerDirectiveNodes ? innerDirectiveClass.node : undefined, + }); + }); + }); + + } else if (property.text === 'filters') { + if (!ts.isArrayLiteralExpression(configurationProperty.initializer)) { + throw new Error(`${callName} ${className}: filters should be an array of identifiers.`); + } + + definition.filters = []; + + ts.forEachChild(configurationProperty.initializer, (filter: ts.Node) => { + if (!ts.isIdentifier(filter)) { + throw new Error(`${callName} ${className}: filters should be an array of identifiers.`); + } + + const filterClass = resolveIdentifier(filter, this.compilerOptions, this.moduleResolutionHost); + + if (!filterClass) { + throw new Error(`${callName} ${className}: filter ${(filter).text} does not exists.`); + } + + if (!ts.isClassDeclaration(filterClass.node)) { + throw new Error(`${callName} ${className}: filters must be a list of ClassDeclarations.`); + } + + dependencies = merge(dependencies, filterClass.dependencies); + + const definitionFilter: DirectiveDefinitionFilterMetadata = { + localName: (filter).text, + originalName: filterClass.originalName, + imported: filterClass.imported, + path: filterClass.sourceFile.fileName, + metadata: this.filterAnalyzer.analyzeFilter(filterClass.node), + }; + + definition.filters.push(definitionFilter); + }); + + } else if (property.text === 'exportAs') { + if (ts.isStringLiteral(configurationProperty.initializer)) { + definition.exportAs.push((configurationProperty.initializer).text); + + } else if (ts.isArrayLiteralExpression(configurationProperty.initializer)) { + ts.forEachChild(configurationProperty.initializer, (exportAs: ts.Node) => { + if (!ts.isStringLiteral(exportAs)) { + throw new Error(`${callName} ${className}: exportAs should be a string or an array of strings.`); + } + + definition.exportAs.push((exportAs).text); + }); + + } else { + throw new Error(`${callName} ${className}: exportAs should be a string or an array of strings.`); + } + + } else { + definition[property.text] = configurationProperty.initializer; + } + } + }); + + if (definition.selector === '') { + throw new Error(`${callName} ${className}: missing selector.`); + } + + if (definition.type === DirectiveDefinitionType.Component) { + if (!exists(definition.template)) { + throw new Error(`Component ${className}: missing template.`); + } + + if (!exists(definition.encapsulation)) { + definition.encapsulation = TemplateEncapsulation.Emulated; + } + + if (!exists(definition.filters)) { + definition.filters = []; + } + + if (!exists(definition.styles)) { + definition.styles = []; + } + } + + if (definition.id === '') { + definition.id = this.createDefaultDirectiveId(className, definition, sourceFile); + } + + return { + dependencies: dependencies, + definition: definition, + }; + } + + + private createDefaultDirectiveId(className: string, metadata: DirectiveDefinition, sourceFile: ts.SourceFile): string + { + const parts = [ + className, + metadata.selector, + path.basename(sourceFile.fileName), + ]; + + return `${className}_${hash(parts.join(''))}`; + } + + + private analyzeDirectivePropertiesAndMethods(className: string, directiveClass: ts.ClassDeclaration, directive: AnalyzedDirective, includeInnerDirectiveNodes: boolean): void + { + const definition = directive.definition; + + ts.forEachChild(directiveClass, (node: ts.Node) => { + if (ts.isPropertyDeclaration(node) || ts.isMethodDeclaration(node)) { + const property = node; + + if (!ts.isIdentifier(property.name)) { + return; + } + + const propertyName = property.name; + + if (ts.isMethodDeclaration(node)) { + let isLifeCycleEvent = false; + + if (propertyName.text === 'onInit') { + definition.onInit = isLifeCycleEvent = true; + } else if (propertyName.text === 'onDestroy') { + definition.onDestroy = isLifeCycleEvent = true; + } else if (propertyName.text === 'onTemplateInit') { + definition.onTemplateInit = isLifeCycleEvent = true; + } else if (propertyName.text === 'onUpdate') { + definition.onUpdate = isLifeCycleEvent = true; + } else if (propertyName.text === 'onAttach') { + definition.onAttach = isLifeCycleEvent = true; + } + + if (isLifeCycleEvent) { + return; + } + } + + let isRequired: boolean = false; + let input: DirectiveDefinitionInput = null; + let output: DirectiveDefinitionOutput = null; + let hostElement: DirectiveDefinitionElement = null; + let hostEvent: DirectiveDefinitionEvent = null; + let childDirective: DirectiveDefinitionChildDirective = null; + let childrenDirective: DirectiveDefinitionChildrenDirective = null; + + ts.forEachChild(property, (propertyNode: ts.Node) => { + if (ts.isDecorator(propertyNode) && ts.isCallExpression((propertyNode).expression)) { + const decoratorExpression = (propertyNode).expression; + + if (ts.isIdentifier(decoratorExpression.expression)) { + const decoratorName = decoratorExpression.expression; + + if (decoratorName.text === 'Required') { + isRequired = true; + + } else if (decoratorName.text === 'Input') { + let inputValue = camelCaseToHyphens(propertyName.text); + + if (decoratorExpression.arguments.length) { + if (!ts.isStringLiteral(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @Input() decorator should have no argument or string.`); + } + + inputValue = (decoratorExpression.arguments[0]).text; + } + + input = { + property: propertyName.text, + name: inputValue, + required: false, + }; + + } else if (decoratorName.text === 'Output') { + let outputValue = camelCaseToHyphens(propertyName.text); + + if (decoratorExpression.arguments.length) { + if (!ts.isStringLiteral(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @Output() decorator should have no argument or string.`); + } + + outputValue = (decoratorExpression.arguments[0]).text; + } + + output = { + property: propertyName.text, + name: outputValue, + }; + + } else if (decoratorName.text === 'HostElement') { + if (!decoratorExpression.arguments.length || !ts.isStringLiteral(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @HostElement() decorator should have string selector argument.`); + } + + hostElement = { + property: propertyName.text, + selector: (decoratorExpression.arguments[0]).text, + required: false, + }; + + } else if (decoratorName.text === 'HostEvent') { + if (!decoratorExpression.arguments.length || !ts.isStringLiteral(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @HostEvent() decorator should have string event name argument.`); + } + + if (decoratorExpression.arguments.length > 1 && !ts.isStringLiteral(decoratorExpression.arguments[1])) { + throw new Error(`${className}.${propertyName.text}: @HostEvent() decorator should have string event name argument.`); + } + + hostEvent = { + method: propertyName.text, + event: (decoratorExpression.arguments[0]).text, + }; + + if (decoratorExpression.arguments.length > 1) { + hostEvent.selector = (decoratorExpression.arguments[1]).text; + } + + } else if (decoratorName.text === 'ChildDirective') { + if (!decoratorExpression.arguments.length || !ts.isIdentifier(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @ChildDirective() decorator should have identifier argument.`); + } + + const childDirectiveClass = resolveIdentifier(decoratorExpression.arguments[0], this.compilerOptions, this.moduleResolutionHost); + + if (!childDirectiveClass) { + throw new Error(`${className}.${propertyName.text}: class ${(decoratorExpression.arguments[0]).text} used in @ChildDirective() decorator was not found.`); + } + + if (!ts.isClassDeclaration(childDirectiveClass.node)) { + throw new Error(`${className}.${propertyName.text}: identifier ${(decoratorExpression.arguments[0]).text} used in @ChildDirective() should be a ClassDeclaration.`); + } + + const childDirectiveDirective = this.analyzeDirective(childDirectiveClass.node); + + directive.dependencies = merge(directive.dependencies, childDirectiveClass.dependencies); + childDirective = { + property: propertyName.text, + directive: { + localName: (decoratorExpression.arguments[0]).text, + imported: childDirectiveClass.imported, + path: childDirectiveClass.sourceFile.fileName, + originalName: childDirectiveDirective.definition.className, + metadata: childDirectiveDirective.definition, + node: includeInnerDirectiveNodes ? childDirectiveClass.node : undefined, + }, + required: false, + }; + + } else if (decoratorName.text === 'ChildrenDirective') { + if (!decoratorExpression.arguments.length || !ts.isIdentifier(decoratorExpression.arguments[0])) { + throw new Error(`${className}.${propertyName.text}: @ChildrenDirective() decorator should have identifier argument.`); + } + + const childrenDirectiveClass = resolveIdentifier(decoratorExpression.arguments[0], this.compilerOptions, this.moduleResolutionHost); + + if (!childrenDirectiveClass) { + throw new Error(`${className}.${propertyName.text}: class ${(decoratorExpression.arguments[0]).text} used in @ChildrenDirective() decorator was not found.`); + } + + if (!ts.isClassDeclaration(childrenDirectiveClass.node)) { + throw new Error(`${className}.${propertyName.text}: identifier ${(decoratorExpression.arguments[0]).text} used in @ChildrenDirective() should be a ClassDeclaration.`); + } + + const childrenDirectiveDirective = this.analyzeDirective(childrenDirectiveClass.node); + + directive.dependencies = merge(directive.dependencies, childrenDirectiveClass.dependencies); + childrenDirective = { + property: propertyName.text, + directive: { + localName: (decoratorExpression.arguments[0]).text, + imported: childrenDirectiveClass.imported, + path: childrenDirectiveClass.sourceFile.fileName, + originalName: childrenDirectiveClass.originalName, + metadata: childrenDirectiveDirective.definition, + node: includeInnerDirectiveNodes ? childrenDirectiveClass.node : undefined, + }, + }; + } + } + } + }); + + if (input !== null) { + input.required = isRequired; + definition.inputs.push(input); + + } else if (output !== null) { + definition.outputs.push(output); + + } else if (hostElement !== null) { + hostElement.required = isRequired; + definition.elements.push(hostElement); + + } else if (hostEvent !== null) { + definition.events.push(hostEvent); + + } else if (childDirective !== null) { + childDirective.required = isRequired; + definition.childDirectives.push(childDirective); + + } else if (childrenDirective !== null) { + definition.childrenDirectives.push(childrenDirective); + } + } + }); + + forEach(definition.events, (hostEvent: DirectiveDefinitionEvent) => { + if (exists(hostEvent.selector) && hostEvent.selector.charAt(0) === '@') { + const hostElementName = hostEvent.selector.substr(1); + + const hostElement: DirectiveDefinitionElement = find(definition.elements, (findHostElement: DirectiveDefinitionElement) => { + return hostElementName === findHostElement.property; + }); + + if (!hostElement) { + throw new Error(`${className}.${hostEvent.method}: @HostEvent() requires unknown @HostElement() on ${className}.${hostElementName}.`); + } + + hostEvent.selector = hostElement.selector; + } + }); + } + + + private requireRawFile(decoratorName: string, className: string, type: string, file: string, requireCall: ts.CallExpression, extension: string): RequiredFile + { + if (!ts.isIdentifier(requireCall.expression) || !requireCall.arguments.length || !ts.isStringLiteral(requireCall.arguments[0])) { + throw new Error(`${decoratorName} ${className}: ${type} should be a simple require call.`); + } + + const requireCallIdentifier = requireCall.expression; + + if (requireCallIdentifier.text !== 'require') { + throw new Error(`${decoratorName} ${className}: ${type} should be a simple require call.`); + } + + const requirePath = (requireCall.arguments[0]).text; + + if (path.extname(requirePath) !== `.${extension}`) { + throw new Error(`${decoratorName} ${className}: required template must have file extension.`); + } + + const module = resolveRawRequire(file, requirePath, this.moduleResolutionHost); + + if (!exists(module)) { + throw new Error(`${file}: can not require file "${requirePath}". File does not exists.`); + } + + return module; + } + +} diff --git a/packages/compiler-cli/analyzers/fileAnalyzer.ts b/packages/compiler-cli/analyzers/fileAnalyzer.ts new file mode 100644 index 0000000..ee40390 --- /dev/null +++ b/packages/compiler-cli/analyzers/fileAnalyzer.ts @@ -0,0 +1,106 @@ +import {exists, merge, unique} from '@slicky/utils'; +import {FilterMetadata, DirectiveDefinition} from '@slicky/core/metadata'; +import * as ts from 'typescript'; +import {DirectiveAnalyzer} from './directiveAnalyzer'; +import {FilterAnalyzer} from './filterAnalyzer'; + + +export declare interface FileDefinitionFilter +{ + exported: boolean, + metadata: FilterMetadata, +} + + +export declare interface FileDefinitionDirective +{ + exported: boolean, + metadata: DirectiveDefinition, +} + + +export declare interface FileDefinition +{ + dependencies: Array, + filters: Array, + directives: Array, +} + + +export class FileAnalyzer +{ + + + private directiveAnalyzer: DirectiveAnalyzer; + + private filterAnalyzer: FilterAnalyzer; + + private storage: {[path: string]: FileDefinition} = {}; + + + constructor(directiveAnalyzer: DirectiveAnalyzer, filterAnalyzer: FilterAnalyzer) + { + this.directiveAnalyzer = directiveAnalyzer; + this.filterAnalyzer = filterAnalyzer; + } + + + public analyzeFile(sourceFile: ts.SourceFile, includeInnerDirectiveNodes: boolean = true): FileDefinition + { + if (exists(this.storage[sourceFile.fileName])) { + return this.storage[sourceFile.fileName]; + } + + const definition: FileDefinition = { + dependencies: [], + filters: [], + directives: [], + }; + + ts.forEachChild(sourceFile, (node: ts.Node) => { + if (!ts.isClassDeclaration(node)) { + return; + } + + const classDeclaration = node; + const filter = this.filterAnalyzer.analyzeFilter(classDeclaration, false); + + if (filter) { + definition.filters.push({ + exported: this.isClassExported(classDeclaration), + metadata: filter, + }); + + } else { + const directive = this.directiveAnalyzer.analyzeDirective(classDeclaration, false, includeInnerDirectiveNodes); + + if (directive) { + definition.dependencies = merge(definition.dependencies, directive.dependencies); + definition.directives.push({ + exported: this.isClassExported(classDeclaration), + metadata: directive.definition, + }); + } + } + }); + + definition.dependencies = unique(definition.dependencies); + + return this.storage[sourceFile.fileName] = definition; + } + + + private isClassExported(classDeclaration: ts.ClassDeclaration): boolean + { + let exported = false; + + ts.forEachChild(classDeclaration, (node: ts.Node) => { + if (node.kind === ts.SyntaxKind.ExportKeyword) { + exported = true; + } + }); + + return exported; + } + +} diff --git a/packages/compiler-cli/analyzers/filterAnalyzer.ts b/packages/compiler-cli/analyzers/filterAnalyzer.ts new file mode 100644 index 0000000..b69fe82 --- /dev/null +++ b/packages/compiler-cli/analyzers/filterAnalyzer.ts @@ -0,0 +1,96 @@ +import {exists} from '@slicky/utils'; +import {FilterMetadata} from '@slicky/core/metadata'; +import * as ts from 'typescript'; + + +export class FilterAnalyzer +{ + + + private storage: { [className: string]: FilterMetadata } = {}; + + + public analyzeFilter(filterClass: ts.ClassDeclaration, need: boolean = true): FilterMetadata + { + const className = (filterClass.name).text; + + if (exists(this.storage[className])) { + return this.storage[className]; + } + + const definition = this.analyzeFilterDecorator(className, filterClass); + + if (!exists(definition)) { + if (need) { + throw new Error(`Class "${className}" is not a valid filter. Please add @Filter() decorator.`); + } + + return; + } + + return this.storage[className] = definition; + } + + + private analyzeFilterDecorator(className: string, filterClass: ts.ClassDeclaration): FilterMetadata + { + + let filterDecorator: ts.Decorator; + + ts.forEachChild(filterClass, (node: ts.Node) => { + if (ts.isDecorator(node)) { + const decorator = node; + + if (ts.isCallExpression(decorator.expression)) { + const callExpression = decorator.expression; + + if (ts.isIdentifier(callExpression.expression)) { + const identifier = callExpression.expression; + + if (identifier.text === 'Filter') { + filterDecorator = decorator; + } + } + } + + } + }); + + if (!filterDecorator) { + return; + } + + const callExpression = filterDecorator.expression; + + if (!callExpression.arguments.length || !ts.isObjectLiteralExpression(callExpression.arguments[0])) { + throw new Error(`Filter ${className}: missing metadata configuration object.`); + } + + const configuration = callExpression.arguments[0]; + const definition: FilterMetadata = { + className: className, + name: '', + }; + + ts.forEachChild(configuration, (configurationProperty: ts.PropertyAssignment) => { + if (ts.isIdentifier(configurationProperty.name)) { + const property = configurationProperty.name; + + if (property.text === 'name') { + if (!ts.isStringLiteral(configurationProperty.initializer)) { + throw new Error(`Filter ${definition.className}: name should be a string.`); + } + + definition.name = (configurationProperty.initializer).text; + } + } + }); + + if (definition.name === '') { + throw new Error(`Filter ${definition.className}: missing name.`); + } + + return definition; + } + +} diff --git a/packages/compiler-cli/analyzers/index.ts b/packages/compiler-cli/analyzers/index.ts new file mode 100644 index 0000000..2d2dd1e --- /dev/null +++ b/packages/compiler-cli/analyzers/index.ts @@ -0,0 +1,3 @@ +export * from './directiveAnalyzer'; +export * from './fileAnalyzer'; +export * from './filterAnalyzer'; diff --git a/packages/compiler-cli/bin/scc.ts b/packages/compiler-cli/bin/scc.ts deleted file mode 100644 index 7f91a11..0000000 --- a/packages/compiler-cli/bin/scc.ts +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env node - -import * as yargs from 'yargs'; -import * as path from 'path'; -import * as colors from 'colors/safe'; -import {existsSync} from 'fs'; -import {forEach} from '@slicky/utils'; -import {Compiler, ParsedFile, ParsedComponent} from '../compiler'; - - -const args = yargs - .usage('$0 [args]') - .command('compile [tsconfig]', 'Compile given app components', { - tsconfig: { - describe: 'Path to your project tsconfig.json file', - }, - }) - .coerce('tsconfig', (arg) => { - if (existsSync(arg)) { - return arg; - } - - return path.join(process.cwd(), arg); - }) - .strict(true) - .help() - .argv; - - -if (args._[0] !== 'compile') { - throw new Error('Unknown command.'); -} - - -console.log(`Using typescript config file ${colors.yellow(path.relative(process.cwd(), args.tsconfig))}`); -console.log(''); - - -const compiler = new Compiler(args.tsconfig); - - -compiler.compile((files) => { - let componentsLength = 0; - - forEach(files, (file: ParsedFile) => { - if (!file.components.length) { - return; - } - - console.log(colors.yellow(path.relative(process.cwd(), file.file))); - - forEach(file.components, (component: ParsedComponent) => { - componentsLength++; - console.log(` - ${component.name}`); - }); - }); - - if (componentsLength) { - console.log(''); - console.log(colors.green(`Successfully generated ${componentsLength} templates into ${path.relative(process.cwd(), compiler.getConfig().outDir)}`)); - } else { - console.log(colors.green('No components found')); - } -}); diff --git a/packages/compiler-cli/index.ts b/packages/compiler-cli/index.ts index 7ec0839..00ac705 100644 --- a/packages/compiler-cli/index.ts +++ b/packages/compiler-cli/index.ts @@ -1 +1,2 @@ -export {Compiler} from './compiler/compiler'; +//export {Compiler} from './compiler/compiler'; +export {Compiler} from './newCompiler'; diff --git a/packages/compiler-cli/newCompiler/compiler.ts b/packages/compiler-cli/newCompiler/compiler.ts new file mode 100644 index 0000000..fac2d88 --- /dev/null +++ b/packages/compiler-cli/newCompiler/compiler.ts @@ -0,0 +1,56 @@ +import {FileAnalyzer} from '../analyzers'; +import {createFilterTransformer, createDirectiveTransformer} from '../transformers'; +import * as ts from 'typescript'; + + +export declare interface CompiledFileResult +{ + dependencies: Array + sourceText: string, + sourceFile: ts.SourceFile, +} + + +export class Compiler +{ + + + private fileAnalyzer: FileAnalyzer; + + private compilerOptions: ts.CompilerOptions; + + private moduleResolutionHost: ts.ModuleResolutionHost; + + + constructor(fileAnalyzer: FileAnalyzer, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost) + { + this.fileAnalyzer = fileAnalyzer; + this.compilerOptions = compilerOptions; + this.moduleResolutionHost = moduleResolutionHost; + } + + + public compileFile(fileName: string, source: string): CompiledFileResult + { + let dependencies: Array = []; + + const sourceFile = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true); + const result = >ts.transform(sourceFile, [ + createFilterTransformer(this.fileAnalyzer, this.compilerOptions, this.moduleResolutionHost), + createDirectiveTransformer(this.fileAnalyzer, this.compilerOptions, this.moduleResolutionHost, (file) => { + dependencies = file.dependencies; + }), + ], this.compilerOptions); + + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + }); + + return { + dependencies: dependencies, + sourceText: printer.printNode(ts.EmitHint.SourceFile, result.transformed[0], result.transformed[0]), + sourceFile: result.transformed[0], + }; + } + +} diff --git a/packages/compiler-cli/newCompiler/index.ts b/packages/compiler-cli/newCompiler/index.ts new file mode 100644 index 0000000..b2a5775 --- /dev/null +++ b/packages/compiler-cli/newCompiler/index.ts @@ -0,0 +1 @@ +export * from './compiler'; diff --git a/packages/compiler-cli/package.json b/packages/compiler-cli/package.json index 44b04e8..5595f95 100644 --- a/packages/compiler-cli/package.json +++ b/packages/compiler-cli/package.json @@ -19,6 +19,8 @@ "dependencies": { "@slicky/compiler": "^0.5.1", "@slicky/core": "^0.10.1", + "@slicky/templates": "^1.3.2", + "@slicky/typescript-api-utils": "^0.0.1", "@slicky/utils": "^1.3.1", "colors": "^1.1.2", "glob": "^7.1.2", diff --git a/packages/compiler-cli/tests/data/component.functionalTemplate.expected.ts b/packages/compiler-cli/tests/data/_old/component.functionalTemplate.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.functionalTemplate.expected.ts rename to packages/compiler-cli/tests/data/_old/component.functionalTemplate.expected.ts diff --git a/packages/compiler-cli/tests/data/component.functionalTemplate.original.ts b/packages/compiler-cli/tests/data/_old/component.functionalTemplate.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.functionalTemplate.original.ts rename to packages/compiler-cli/tests/data/_old/component.functionalTemplate.original.ts diff --git a/packages/compiler-cli/tests/data/component.metadata.invalid.original.ts b/packages/compiler-cli/tests/data/_old/component.metadata.invalid.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.metadata.invalid.original.ts rename to packages/compiler-cli/tests/data/_old/component.metadata.invalid.original.ts diff --git a/packages/compiler-cli/tests/data/component.template.expected.ts b/packages/compiler-cli/tests/data/_old/component.template.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.template.expected.ts rename to packages/compiler-cli/tests/data/_old/component.template.expected.ts diff --git a/packages/compiler-cli/tests/data/component.template.invalid.original.ts b/packages/compiler-cli/tests/data/_old/component.template.invalid.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.template.invalid.original.ts rename to packages/compiler-cli/tests/data/_old/component.template.invalid.original.ts diff --git a/packages/compiler-cli/tests/data/component.template.original.ts b/packages/compiler-cli/tests/data/_old/component.template.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/component.template.original.ts rename to packages/compiler-cli/tests/data/_old/component.template.original.ts diff --git a/packages/compiler-cli/tests/data/directive.noExport.expected.ts b/packages/compiler-cli/tests/data/_old/directive.noExport.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/directive.noExport.expected.ts rename to packages/compiler-cli/tests/data/_old/directive.noExport.expected.ts diff --git a/packages/compiler-cli/tests/data/directive.noExport.original.ts b/packages/compiler-cli/tests/data/_old/directive.noExport.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/directive.noExport.original.ts rename to packages/compiler-cli/tests/data/_old/directive.noExport.original.ts diff --git a/packages/compiler-cli/tests/data/mixed.expected.ts b/packages/compiler-cli/tests/data/_old/mixed.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/mixed.expected.ts rename to packages/compiler-cli/tests/data/_old/mixed.expected.ts diff --git a/packages/compiler-cli/tests/data/mixed.original.ts b/packages/compiler-cli/tests/data/_old/mixed.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/mixed.original.ts rename to packages/compiler-cli/tests/data/_old/mixed.original.ts diff --git a/packages/compiler-cli/tests/data/noClass.expected.ts b/packages/compiler-cli/tests/data/_old/noClass.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/noClass.expected.ts rename to packages/compiler-cli/tests/data/_old/noClass.expected.ts diff --git a/packages/compiler-cli/tests/data/noClass.original.ts b/packages/compiler-cli/tests/data/_old/noClass.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/noClass.original.ts rename to packages/compiler-cli/tests/data/_old/noClass.original.ts diff --git a/packages/compiler-cli/tests/data/plain.expected.ts b/packages/compiler-cli/tests/data/_old/plain.expected.ts similarity index 100% rename from packages/compiler-cli/tests/data/plain.expected.ts rename to packages/compiler-cli/tests/data/_old/plain.expected.ts diff --git a/packages/compiler-cli/tests/data/plain.original.ts b/packages/compiler-cli/tests/data/_old/plain.original.ts similarity index 100% rename from packages/compiler-cli/tests/data/plain.original.ts rename to packages/compiler-cli/tests/data/_old/plain.original.ts diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_1.ts new file mode 100644 index 0000000..234ecd6 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_1.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + encapsulation: 1, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_2.ts new file mode 100644 index 0000000..cfd6469 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_2.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + encapsulation: Template.Encapsulation.None, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_3.ts new file mode 100644 index 0000000..472c097 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_3.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + encapsulation: Encapsulation.None, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_4.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_4.ts new file mode 100644 index 0000000..e13bded --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/invalid_4.ts @@ -0,0 +1,9 @@ +import {Component, TemplateEncapsulation} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + encapsulation: TemplateEncapsulation.Unknown, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/valid.ts new file mode 100644 index 0000000..18bd2bc --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.encapsulation/valid.ts @@ -0,0 +1,9 @@ +import {Component, TemplateEncapsulation} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + encapsulation: TemplateEncapsulation.None, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_1.ts new file mode 100644 index 0000000..549f3d7 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_1.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + filters: 'filter', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_2.ts new file mode 100644 index 0000000..c191082 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/invalid_2.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + filters: ['filter'], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/valid.ts new file mode 100644 index 0000000..a90d1de --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.filters/valid.ts @@ -0,0 +1,24 @@ +import {Component, Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} + + +@Component({ + selector: 'test-component', + template: '', + filters: [TestFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_1.ts new file mode 100644 index 0000000..a746aa2 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_1.ts @@ -0,0 +1,7 @@ +import {Component} from '@slicky/core'; + + +@Component({ + template: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_2.ts new file mode 100644 index 0000000..c8f683b --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_2.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 5, + template: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_3.ts new file mode 100644 index 0000000..0251cc3 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.selector/invalid_3.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'button', + template: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_1.ts new file mode 100644 index 0000000..c8cd453 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_1.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + styles: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_2.ts new file mode 100644 index 0000000..0fc2bd6 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/invalid_2.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + styles: [5], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/valid.ts new file mode 100644 index 0000000..b0b315f --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.styles/valid.ts @@ -0,0 +1,12 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + styles: [ + 'body {color: red}', + require('/styles.css'), + ], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_1.ts new file mode 100644 index 0000000..01b8db1 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_1.ts @@ -0,0 +1,7 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_2.ts new file mode 100644 index 0000000..f7a700a --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_2.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: 5, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_3.ts new file mode 100644 index 0000000..ac69787 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_3.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: loadTemplate(), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_4.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_4.ts new file mode 100644 index 0000000..a688c9e --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_4.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require(), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_5.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_5.ts new file mode 100644 index 0000000..a675672 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_5.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require(5), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_6.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_6.ts new file mode 100644 index 0000000..a1b3c35 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_6.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require('/template'), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_7.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_7.ts new file mode 100644 index 0000000..7cb536e --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/invalid_7.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require('/template.txt'), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_1.ts new file mode 100644 index 0000000..677ca11 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_1.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: 'hello world', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_2.ts new file mode 100644 index 0000000..66eeecd --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_2.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require('/template.html'), +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_3.ts new file mode 100644 index 0000000..e4aa0f1 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_3.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: `hello world`, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_4.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_4.ts new file mode 100644 index 0000000..816891e --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_4.ts @@ -0,0 +1,11 @@ +import {Component} from '@slicky/core'; + + +const TEMPLATE = 'hello world'; + + +@Component({ + selector: 'test-component', + template: TEMPLATE, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_5.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_5.ts new file mode 100644 index 0000000..0e41221 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/component.template/valid_5.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; +import {TEMPLATE} from '/template'; + + +@Component({ + selector: 'test-component', + template: TEMPLATE, +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_1.ts new file mode 100644 index 0000000..df9ed66 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_1.ts @@ -0,0 +1,13 @@ +import {Directive, ChildDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildDirective() + child; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_2.ts new file mode 100644 index 0000000..c2897ab --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/invalid_2.ts @@ -0,0 +1,13 @@ +import {Directive, ChildDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildDirective(5) + child; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/valid.ts new file mode 100644 index 0000000..376cf85 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childDirectives/valid.ts @@ -0,0 +1,23 @@ +import {Directive, ChildDirective, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildDirective(TestChildDirective) + child; + + @ChildDirective(TestChildDirective) + @Required() + childRequired; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_1.ts new file mode 100644 index 0000000..dbf000f --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_1.ts @@ -0,0 +1,13 @@ +import {Directive, ChildrenDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildrenDirective() + child; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_2.ts new file mode 100644 index 0000000..50ba054 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/invalid_2.ts @@ -0,0 +1,13 @@ +import {Directive, ChildrenDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildrenDirective(5) + child; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/valid.ts new file mode 100644 index 0000000..ebf9297 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.childrenDirectives/valid.ts @@ -0,0 +1,19 @@ +import {Directive, ChildrenDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-children-directive', +}) +class TestChildrenDirective {} + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @ChildrenDirective(TestChildrenDirective) + children; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.customMetadata/valid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.customMetadata/valid_1.ts new file mode 100644 index 0000000..982d462 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.customMetadata/valid_1.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + customData: 'hello world', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_1.ts new file mode 100644 index 0000000..d05afee --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_1.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + directives: 'hello world', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_2.ts new file mode 100644 index 0000000..e9167fd --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_2.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + directives: ['hello world'], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.innerDirective.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.innerDirective.ts new file mode 100644 index 0000000..8b8cf0f --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.innerDirective.ts @@ -0,0 +1,10 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +export const CHILD_DIRECTIVES = [TestChildDirective]; diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.ts new file mode 100644 index 0000000..3d926a9 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/invalid_3.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {CHILD_DIRECTIVES} from './invalid_3.innerDirective'; + + +@Directive({ + selector: 'test-directive', + directives: [CHILD_DIRECTIVES], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/valid.ts new file mode 100644 index 0000000..a590666 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.directives/valid.ts @@ -0,0 +1,14 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', + directives: [TestChildDirective], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_1.ts new file mode 100644 index 0000000..26463af --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_1.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: 5, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_2.ts new file mode 100644 index 0000000..2a80093 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/invalid_2.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: [5], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_1.ts new file mode 100644 index 0000000..996ae54 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_1.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: 'dir', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_2.ts new file mode 100644 index 0000000..8d107e9 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.exportAs/valid_2.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: ['dirA', 'dirB'], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_1.ts new file mode 100644 index 0000000..4c18659 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_1.ts @@ -0,0 +1,13 @@ +import {Directive, HostElement} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostElement() + el; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_2.ts new file mode 100644 index 0000000..08a1288 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/invalid_2.ts @@ -0,0 +1,13 @@ +import {Directive, HostElement} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostElement(5) + el; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/valid.ts new file mode 100644 index 0000000..059e97d --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostElements/valid.ts @@ -0,0 +1,17 @@ +import {Directive, HostElement, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostElement('button') + el; + + @HostElement('div') + @Required() + elRequired; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_1.ts new file mode 100644 index 0000000..ff32620 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_1.ts @@ -0,0 +1,13 @@ +import {Directive, HostEvent} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostEvent() + onClick() {}; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_2.ts new file mode 100644 index 0000000..634bcf2 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_2.ts @@ -0,0 +1,13 @@ +import {Directive, HostEvent} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostEvent(5) + onClick() {}; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_3.ts new file mode 100644 index 0000000..06a2741 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_3.ts @@ -0,0 +1,13 @@ +import {Directive, HostEvent} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostEvent('click', 5) + onClick() {}; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_4.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_4.ts new file mode 100644 index 0000000..c6e440a --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/invalid_4.ts @@ -0,0 +1,13 @@ +import {Directive, HostEvent} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostEvent('click', '@btn') + onClick() {}; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/valid.ts new file mode 100644 index 0000000..0f0b940 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.hostEvents/valid.ts @@ -0,0 +1,22 @@ +import {Directive, HostEvent, HostElement} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @HostElement('button') + el; + + @HostEvent('click') + onEvent() {} + + @HostEvent('click', 'div') + onEventWithSelector() {} + + @HostEvent('click', '@el') + onEventWithHostElement() {} + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/invalid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/invalid.ts new file mode 100644 index 0000000..48dbeb7 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/invalid.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + id: 5, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/valid.ts new file mode 100644 index 0000000..88fb84c --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.id/valid.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + id: 'app:directive', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/invalid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/invalid.ts new file mode 100644 index 0000000..285fe6f --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/invalid.ts @@ -0,0 +1,13 @@ +import {Directive, Input} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @Input(5) + input; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/valid.ts new file mode 100644 index 0000000..0424582 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.inputs/valid.ts @@ -0,0 +1,24 @@ +import {Directive, Input, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @Input() + input; + + @Input('custom-name-input') + inputWithDifferentName; + + @Input() + @Required() + inputRequired; + + @Input('custom-name-required-input') + @Required() + inputRequiredWithDifferentName; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.lifeCycleEvents/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.lifeCycleEvents/valid.ts new file mode 100644 index 0000000..63cbe1e --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.lifeCycleEvents/valid.ts @@ -0,0 +1,20 @@ +import {Directive, OnInit, OnDestroy, OnTemplateInit, OnUpdate, OnAttach} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective implements OnInit, OnDestroy, OnTemplateInit, OnUpdate, OnAttach +{ + + onInit() {} + + onDestroy() {} + + onTemplateInit() {} + + onUpdate() {} + + onAttach() {} + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/invalid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/invalid.ts new file mode 100644 index 0000000..8c0b5c9 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/invalid.ts @@ -0,0 +1,13 @@ +import {Directive, Output} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @Output(5) + output; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/valid.ts new file mode 100644 index 0000000..dfed26a --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.outputs/valid.ts @@ -0,0 +1,16 @@ +import {Directive, Output} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + @Output() + output; + + @Output('custom-name-output') + outputWithDifferentName; + +} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/invalid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/invalid.ts new file mode 100644 index 0000000..0981b47 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/invalid.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + override: 'override', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/valid.ts new file mode 100644 index 0000000..4c9cd0e --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.override/valid.ts @@ -0,0 +1,14 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestBaseDirective {} + + +@Directive({ + selector: 'test-directive', + override: TestBaseDirective, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_1.ts new file mode 100644 index 0000000..990ac30 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_1.ts @@ -0,0 +1,5 @@ +import {Directive} from '@slicky/core'; + + +@Directive({}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_2.ts new file mode 100644 index 0000000..ed5adc3 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/directive.selector/invalid_2.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 5, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_1.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_1.ts new file mode 100644 index 0000000..e9f4e66 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_1.ts @@ -0,0 +1 @@ +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_2.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_2.ts new file mode 100644 index 0000000..7a7cbef --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_2.ts @@ -0,0 +1,5 @@ +import {Directive} from '@slicky/core'; + + +@Directive() +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_3.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_3.ts new file mode 100644 index 0000000..cd7d6c6 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/invalid_3.ts @@ -0,0 +1,5 @@ +import {Directive} from '@slicky/core'; + + +@Directive(5) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/valid.ts b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/valid.ts new file mode 100644 index 0000000..ec52051 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/directiveAnalyzer/valid.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.filter.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.filter.ts new file mode 100644 index 0000000..53175a6 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.filter.ts @@ -0,0 +1,16 @@ +import {Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +export class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.ts new file mode 100644 index 0000000..5f52259 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.aliased.ts @@ -0,0 +1,10 @@ +import {Component} from '@slicky/core'; +import {TestFilter as MyFilter} from './component.filters.aliased.filter'; + + +@Component({ + selector: 'test-component', + template: '', + filters: [MyFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.filter.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.filter.ts new file mode 100644 index 0000000..53175a6 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.filter.ts @@ -0,0 +1,16 @@ +import {Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +export class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.ts new file mode 100644 index 0000000..0da3ae7 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.imported.ts @@ -0,0 +1,10 @@ +import {Component} from '@slicky/core'; +import {TestFilter} from './component.filters.imported.filter'; + + +@Component({ + selector: 'test-component', + template: '', + filters: [TestFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.ts new file mode 100644 index 0000000..bd84c26 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/component.filters.ts @@ -0,0 +1,25 @@ +import {Component, Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} + + + +@Component({ + selector: 'test-component', + template: '', + filters: [TestFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.childDirective.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.childDirective.ts new file mode 100644 index 0000000..cec5bc9 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.childDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.ts new file mode 100644 index 0000000..248911f --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.import.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {TestChildDirective} from './directive.innerDirectives.import.childDirective'; + + +@Directive({ + selector: 'test-directive', + directives: [TestChildDirective], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.ts new file mode 100644 index 0000000..a590666 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.innerDirectives.ts @@ -0,0 +1,14 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', + directives: [TestChildDirective], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.base.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.base.ts new file mode 100644 index 0000000..f75ce28 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.base.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +export class TestBaseDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.ts new file mode 100644 index 0000000..2e9bbea --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directive.override.import.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {TestBaseDirective} from './directive.override.import.base'; + + +@Directive({ + selector: 'test-directive', + override: TestBaseDirective, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.childDirective.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.childDirective.ts new file mode 100644 index 0000000..cec5bc9 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.childDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.index.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.index.ts new file mode 100644 index 0000000..6133436 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.index.ts @@ -0,0 +1,6 @@ +import {TestChildDirective} from './directives.innerDirectives.array.childDirective'; + + +export const DIRECTIVES = [ + TestChildDirective, +]; diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.ts new file mode 100644 index 0000000..ea270ff --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.innerDirectives.array.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {DIRECTIVES} from './directives.innerDirectives.array.index'; + + +@Directive({ + selector: 'test-directive', + directives: [DIRECTIVES], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.ts new file mode 100644 index 0000000..31ef4b2 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/directives.ts @@ -0,0 +1,13 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'not-exported-directive', +}) +class NotExportedDirective {} + + +@Directive({ + selector: 'exported-directive', +}) +export class ExportedDirective {} diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/empty.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/empty.ts new file mode 100644 index 0000000..e69de29 diff --git a/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/filters.ts b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/filters.ts new file mode 100644 index 0000000..02e5709 --- /dev/null +++ b/packages/compiler-cli/tests/data/analyzers/fileAnalyzer/filters.ts @@ -0,0 +1,31 @@ +import {FilterInterface, Filter} from '@slicky/core'; + + +@Filter({ + name: 'not-exported', +}) +class NotExportedFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} + + +@Filter({ + name: 'exported', +}) +export class ExportedFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} diff --git a/packages/compiler-cli/tests/data/compiler/valid_1.original.ts b/packages/compiler-cli/tests/data/compiler/valid_1.original.ts new file mode 100644 index 0000000..ec52051 --- /dev/null +++ b/packages/compiler-cli/tests/data/compiler/valid_1.original.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/compiler/valid_1.updated.ts b/packages/compiler-cli/tests/data/compiler/valid_1.updated.ts new file mode 100644 index 0000000..f5b7778 --- /dev/null +++ b/packages/compiler-cli/tests/data/compiler/valid_1.updated.ts @@ -0,0 +1,27 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_4208925198", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.original.ts new file mode 100644 index 0000000..73c40bb --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.original.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.updated.ts new file mode 100644 index 0000000..ff487c8 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_1.updated.ts @@ -0,0 +1,36 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_2514560718", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.original.ts new file mode 100644 index 0000000..8d657f7 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.original.ts @@ -0,0 +1,14 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: require('./valid_2.template.html'), +}) +class TestComponent +{ + + + public name: string = 'John'; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.template.html b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.template.html new file mode 100644 index 0000000..c81cc5a --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.template.html @@ -0,0 +1,4 @@ +

Test

+
+

Hello world, I'm {{ name }}

+
diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.updated.ts new file mode 100644 index 0000000..fe06c68 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_2.updated.ts @@ -0,0 +1,52 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public name: string = 'John'; + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_3921432429", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + el.addElement("h1", {}, function (el) { + el.addText("Test"); + }); + el.addText(" "); + el.addElement("div", {}, function (el) { + el.addText(" "); + el.addElement("p", {}, function (el) { + el.addText("Hello world, I'm "); + el.addExpression(function () { + return component.name; + }); + }); + el.addText(" "); + }); + el.addText(" "); + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.original.ts new file mode 100644 index 0000000..1ee4b18 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.original.ts @@ -0,0 +1,22 @@ +import {Directive, Component, ChildDirective} from '@slicky/core'; + + +@Directive({ + selector: 'div', +}) +class TestChildDirective {} + + +@Component({ + selector: 'test-component', + template: '
', + directives: [TestChildDirective], +}) +class TestComponent +{ + + + @ChildDirective(TestChildDirective) + public child: TestChildDirective; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.updated.ts new file mode 100644 index 0000000..cbd5e26 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_3.updated.ts @@ -0,0 +1,73 @@ +import { Directive, Component, ChildDirective, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestChildDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestChildDirective_180609201", + className: "TestChildDirective", + selector: "div", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +class TestComponent { + public child: TestChildDirective; + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_180609201": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_3794846732", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [ + { property: "child", required: false, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + el + .addElement("div", {}, function (el) { + root.createDirectivesStorageTemplate(template, directivesProvider, el, function (template, directivesProvider) { + template.addDirective("@directive_0", directivesProvider.getDirectiveTypeByName("TestChildDirective_180609201"), function (directive) { + component.child = directive; + }); + }); + }); + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.childDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.childDirective.ts new file mode 100644 index 0000000..4062bf6 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.childDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'div', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.original.ts new file mode 100644 index 0000000..0f8e4b6 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.original.ts @@ -0,0 +1,17 @@ +import {Component, ChildDirective} from '@slicky/core'; +import {TestChildDirective} from './valid_4.childDirective'; + + +@Component({ + selector: 'test-component', + template: '
', + directives: [TestChildDirective], +}) +class TestComponent +{ + + + @ChildDirective(TestChildDirective) + public child: TestChildDirective; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.updated.ts new file mode 100644 index 0000000..c841f56 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer.components/valid_4.updated.ts @@ -0,0 +1,50 @@ +import { Component, ChildDirective, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { TestChildDirective } from './valid_4.childDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public child: TestChildDirective; + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_71363570": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_2879162539", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [ + { property: "child", required: false, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + el.addElement("div", {}, function (el) { + root.createDirectivesStorageTemplate(template, directivesProvider, el, function (template, directivesProvider) { + template + .addDirective("@directive_0", directivesProvider.getDirectiveTypeByName("TestChildDirective_71363570"), function (directive) { + component.child = directive; + }); + }); + }); + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.original.ts new file mode 100644 index 0000000..ec52051 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.original.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.updated.ts new file mode 100644 index 0000000..f5b7778 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_1.updated.ts @@ -0,0 +1,27 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_4208925198", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.original.ts new file mode 100644 index 0000000..7df7788 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.original.ts @@ -0,0 +1,18 @@ +import {Directive, HostElement, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @HostElement('button') + public el; + + @HostElement('span') + @Required() + public requiredEl; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.updated.ts new file mode 100644 index 0000000..943e18b --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_10.updated.ts @@ -0,0 +1,32 @@ +import { Directive, HostElement, Required } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public el; + public requiredEl; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_167659934", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [ + { property: "el", selector: "button", required: false }, + { property: "requiredEl", selector: "span", required: true } + ], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.original.ts new file mode 100644 index 0000000..8234d44 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.original.ts @@ -0,0 +1,23 @@ +import {Directive, HostElement, HostEvent} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @HostElement('button') + public el; + + @HostEvent('click') + public onClick(): void {} + + @HostEvent('click', 'button') + public onClickInner(): void {} + + @HostEvent('click', '@el') + public onClickHostElement(): void {} + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.updated.ts new file mode 100644 index 0000000..762074e --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_11.updated.ts @@ -0,0 +1,37 @@ +import { Directive, HostElement, HostEvent } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public el; + public onClick(): void { } + public onClickInner(): void { } + public onClickHostElement(): void { } + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_932332703", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [ + { property: "el", selector: "button", required: false } + ], + events: [ + { method: "onClick", event: "click" }, + { method: "onClickInner", event: "click", selector: "button" }, + { method: "onClickHostElement", event: "click", selector: "button" } + ], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.original.ts new file mode 100644 index 0000000..ff74a92 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.original.ts @@ -0,0 +1,24 @@ +import {Directive, ChildDirective, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @ChildDirective(TestChildDirective) + public child; + + @ChildDirective(TestChildDirective) + @Required() + public requiredChild; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.updated.ts new file mode 100644 index 0000000..638488c --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_12.updated.ts @@ -0,0 +1,56 @@ +import { Directive, ChildDirective, Required } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestChildDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestChildDirective_4240175889", + className: "TestChildDirective", + selector: "test-child-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +class TestDirective { + public child; + public requiredChild; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1298264732", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [ + { property: "child", required: false, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } }, + { property: "requiredChild", required: true, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.childDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.childDirective.ts new file mode 100644 index 0000000..cec5bc9 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.childDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.original.ts new file mode 100644 index 0000000..dee1ec6 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.original.ts @@ -0,0 +1,19 @@ +import {Directive, ChildDirective, Required} from '@slicky/core'; +import {TestChildDirective} from './valid_13.childDirective'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @ChildDirective(TestChildDirective) + public child; + + @ChildDirective(TestChildDirective) + @Required() + public requiredChild; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.updated.ts new file mode 100644 index 0000000..17f6810 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_13.updated.ts @@ -0,0 +1,33 @@ +import { Directive, ChildDirective, Required } from '@slicky/core'; +import { TestChildDirective } from './valid_13.childDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public child; + public requiredChild; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_2072128925", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [ + { property: "child", required: false, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } }, + { property: "requiredChild", required: true, directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.original.ts new file mode 100644 index 0000000..c18d8b9 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.original.ts @@ -0,0 +1,20 @@ +import {Directive, ChildrenDirective} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @ChildrenDirective(TestChildDirective) + public children; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.updated.ts new file mode 100644 index 0000000..de6114c --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_14.updated.ts @@ -0,0 +1,54 @@ +import { Directive, ChildrenDirective } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestChildDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestChildDirective_1768785879", + className: "TestChildDirective", + selector: "test-child-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +class TestDirective { + public children; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_755644826", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [ + { property: "children", directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.childrenDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.childrenDirective.ts new file mode 100644 index 0000000..cec5bc9 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.childrenDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.original.ts new file mode 100644 index 0000000..6a02e8a --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.original.ts @@ -0,0 +1,15 @@ +import {Directive, ChildrenDirective} from '@slicky/core'; +import {TestChildDirective} from './valid_15.childrenDirective'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @ChildrenDirective(TestChildDirective) + public children; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.updated.ts new file mode 100644 index 0000000..72035d8 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_15.updated.ts @@ -0,0 +1,31 @@ +import { Directive, ChildrenDirective } from '@slicky/core'; +import { TestChildDirective } from './valid_15.childrenDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public children; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1520317595", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [ + { property: "children", directive: { metadata: TestChildDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestChildDirective } } + ] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.original.ts new file mode 100644 index 0000000..a590666 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.original.ts @@ -0,0 +1,14 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +@Directive({ + selector: 'test-directive', + directives: [TestChildDirective], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.updated.ts new file mode 100644 index 0000000..402e91c --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_16.updated.ts @@ -0,0 +1,53 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestChildDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestChildDirective_3653916309", + className: "TestChildDirective", + selector: "test-child-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_3653916309": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1886249624", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.original.ts new file mode 100644 index 0000000..366da82 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.original.ts @@ -0,0 +1,18 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +class TestChildDirective {} + + +const INNER_DIRECTIVES = [TestChildDirective]; +const INNER_INNER_DIRECTIVES = [INNER_DIRECTIVES]; + + +@Directive({ + selector: 'test-directive', + directives: [INNER_INNER_DIRECTIVES], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.updated.ts new file mode 100644 index 0000000..492c627 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_17.updated.ts @@ -0,0 +1,55 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestChildDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestChildDirective_112079348", + className: "TestChildDirective", + selector: "test-child-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +const INNER_DIRECTIVES = [TestChildDirective]; +const INNER_INNER_DIRECTIVES = [INNER_DIRECTIVES]; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_112079348": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_2660113817", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.innerDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.innerDirective.ts new file mode 100644 index 0000000..cec5bc9 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.innerDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.original.ts new file mode 100644 index 0000000..1d34336 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.original.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {TestChildDirective} from './valid_18.innerDirective'; + + +@Directive({ + selector: 'test-directive', + directives: [TestChildDirective], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.updated.ts new file mode 100644 index 0000000..7a97291 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_18.updated.ts @@ -0,0 +1,30 @@ +import { Directive } from '@slicky/core'; +import { TestChildDirective } from './valid_18.innerDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_3406023051": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1224827798", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.innerDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.innerDirective.ts new file mode 100644 index 0000000..2314468 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.innerDirective.ts @@ -0,0 +1,12 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-child-directive', +}) +export class TestChildDirective {} + +const CHILD_INNER_DIRECTIVES = [TestChildDirective]; + + +export const CHILD_DIRECTIVES = [CHILD_INNER_DIRECTIVES]; diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.original.ts new file mode 100644 index 0000000..dcba681 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.original.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {CHILD_DIRECTIVES} from './valid_19.innerDirective'; + + +@Directive({ + selector: 'test-directive', + directives: [CHILD_DIRECTIVES], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.updated.ts new file mode 100644 index 0000000..1129699 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_19.updated.ts @@ -0,0 +1,30 @@ +import { Directive } from '@slicky/core'; +import { CHILD_DIRECTIVES, TestChildDirective } from './valid_19.innerDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = { + "TestChildDirective_1938181098": TestChildDirective + }; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1989500567", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.original.ts new file mode 100644 index 0000000..73c40bb --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.original.ts @@ -0,0 +1,8 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.updated.ts new file mode 100644 index 0000000..77bfdfe --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_2.updated.ts @@ -0,0 +1,36 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_3921432429", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.original.ts new file mode 100644 index 0000000..a90d1de --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.original.ts @@ -0,0 +1,24 @@ +import {Component, Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} + + +@Component({ + selector: 'test-component', + template: '', + filters: [TestFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.updated.ts new file mode 100644 index 0000000..9be3239 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_20.updated.ts @@ -0,0 +1,47 @@ +import { Component, Filter, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { FilterMetadata, DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +import { ClassType } from "@slicky/lang"; +class TestFilter implements FilterInterface { + public transform(value: any): string { + return value.toString(); + } + public static __SLICKY__FILTER__METADATA__: FilterMetadata = { + className: "TestFilter", + name: "test-filter" + }; +} +class TestComponent { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = { + "test-filter": TestFilter + }; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_785581821", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.filter.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.filter.ts new file mode 100644 index 0000000..53175a6 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.filter.ts @@ -0,0 +1,16 @@ +import {Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +export class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.original.ts new file mode 100644 index 0000000..3fa842a --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.original.ts @@ -0,0 +1,10 @@ +import {Component} from '@slicky/core'; +import {TestFilter} from './valid_21.filter'; + + +@Component({ + selector: 'test-component', + template: '', + filters: [TestFilter], +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.updated.ts new file mode 100644 index 0000000..ae9a3f3 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_21.updated.ts @@ -0,0 +1,39 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { TestFilter } from './valid_21.filter'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = { + "test-filter": TestFilter + }; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_384094524", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.original.ts new file mode 100644 index 0000000..6cfdbf1 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.original.ts @@ -0,0 +1,12 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-directive', + template: '', + styles: [ + 'body {color: red}', + require('./valid_22.styles.css'), + ], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.styles.css b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.styles.css new file mode 100644 index 0000000..977844e --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.styles.css @@ -0,0 +1 @@ +button {border: 1px solid red} \ No newline at end of file diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.updated.ts new file mode 100644 index 0000000..1d40ced --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_22.updated.ts @@ -0,0 +1,39 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestDirective_483075775", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [ + "body {color: red}", + "button {border: 1px solid red}" + ], + template: function (template, el, component, directivesProvider) { + var root = template; + } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.original.ts new file mode 100644 index 0000000..64b36c8 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.original.ts @@ -0,0 +1,9 @@ +import {Component} from '@slicky/core'; + + +@Component({ + selector: 'test-component', + template: '', + customData: 'hello world', +}) +class TestComponent {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.updated.ts new file mode 100644 index 0000000..dbc556c --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_23.updated.ts @@ -0,0 +1,37 @@ +import { Component, FilterInterface, TemplateEncapsulation } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestComponent { + public static __SLICKY__FILTERS__: { + [name: string]: ClassType; + } = {}; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Component, + id: "TestComponent_1567790270", + className: "TestComponent", + selector: "test-component", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + encapsulation: TemplateEncapsulation.Emulated, + filters: [], + styles: [], + template: function (template, el, component, directivesProvider) { + var root = template; + }, + customData: 'hello world' + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.original.ts new file mode 100644 index 0000000..4c9cd0e --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.original.ts @@ -0,0 +1,14 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestBaseDirective {} + + +@Directive({ + selector: 'test-directive', + override: TestBaseDirective, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.updated.ts new file mode 100644 index 0000000..78e540e --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_3.updated.ts @@ -0,0 +1,52 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestBaseDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestBaseDirective_1275412921", + className: "TestBaseDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_3151878988", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + override: { metadata: TestBaseDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestBaseDirective } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.original.ts new file mode 100644 index 0000000..8795803 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.original.ts @@ -0,0 +1,9 @@ +import {Directive} from '@slicky/core'; +import {TestBaseDirective} from './valid_4.overrideDirective'; + + +@Directive({ + selector: 'test-directive', + override: TestBaseDirective, +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.overrideDirective.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.overrideDirective.ts new file mode 100644 index 0000000..f75ce28 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.overrideDirective.ts @@ -0,0 +1,7 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +export class TestBaseDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.updated.ts new file mode 100644 index 0000000..a853044 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_4.updated.ts @@ -0,0 +1,29 @@ +import { Directive } from '@slicky/core'; +import { TestBaseDirective } from './valid_4.overrideDirective'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_2437713899", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [], + override: { metadata: TestBaseDirective.__SLICKY__DIRECTIVE__METADATA__, directiveType: TestBaseDirective } + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.original.ts new file mode 100644 index 0000000..996ae54 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.original.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: 'dir', +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.updated.ts new file mode 100644 index 0000000..efe6b68 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_5.updated.ts @@ -0,0 +1,27 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_97057162", + className: "TestDirective", + selector: "test-directive", + exportAs: ["dir"], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.original.ts new file mode 100644 index 0000000..8d107e9 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.original.ts @@ -0,0 +1,8 @@ +import {Directive} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', + exportAs: ['dirA', 'dirB'], +}) +class TestDirective {} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.updated.ts new file mode 100644 index 0000000..c3030fa --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_6.updated.ts @@ -0,0 +1,27 @@ +import { Directive } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_236671529", + className: "TestDirective", + selector: "test-directive", + exportAs: ["dirA", "dirB"], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.original.ts new file mode 100644 index 0000000..f84e780 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.original.ts @@ -0,0 +1,21 @@ +import {Directive, OnInit, OnDestroy, OnTemplateInit, OnAttach, OnUpdate} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective implements OnInit, OnDestroy, OnTemplateInit, OnAttach, OnUpdate +{ + + + public onInit(): void {} + + public onDestroy(): void {} + + public onTemplateInit(): void {} + + public onAttach(): void {} + + public onUpdate(): void {} + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.updated.ts new file mode 100644 index 0000000..1a8e683 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_7.updated.ts @@ -0,0 +1,32 @@ +import { Directive, OnInit, OnDestroy, OnTemplateInit, OnAttach, OnUpdate } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective implements OnInit, OnDestroy, OnTemplateInit, OnAttach, OnUpdate { + public onInit(): void { } + public onDestroy(): void { } + public onTemplateInit(): void { } + public onAttach(): void { } + public onUpdate(): void { } + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_3334978248", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: true, + onDestroy: true, + onTemplateInit: true, + onUpdate: true, + onAttach: true, + inputs: [], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.original.ts new file mode 100644 index 0000000..0a53826 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.original.ts @@ -0,0 +1,25 @@ +import {Directive, Input, Required} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @Input() + public input; + + @Input() + @Required() + public requiredInput; + + @Input('data-named-input') + public namedInput; + + @Input('data-named-required-input') + @Required() + public namedRequiredInput; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.updated.ts new file mode 100644 index 0000000..59d7f93 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_8.updated.ts @@ -0,0 +1,36 @@ +import { Directive, Input, Required } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public input; + public requiredInput; + public namedInput; + public namedRequiredInput; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_4121553767", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [ + { property: "input", name: "input", required: false }, + { property: "requiredInput", name: "required-input", required: true }, + { property: "namedInput", name: "data-named-input", required: false }, + { property: "namedRequiredInput", name: "data-named-required-input", required: true } + ], + outputs: [], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.original.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.original.ts new file mode 100644 index 0000000..9eb9647 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.original.ts @@ -0,0 +1,17 @@ +import {Directive, Output} from '@slicky/core'; + + +@Directive({ + selector: 'test-directive', +}) +class TestDirective +{ + + + @Output() + public output; + + @Output('custom-output-name') + public namedOutput; + +} diff --git a/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.updated.ts b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.updated.ts new file mode 100644 index 0000000..2ad259b --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/directiveTransformer/valid_9.updated.ts @@ -0,0 +1,32 @@ +import { Directive, Output } from '@slicky/core'; +import { ClassType } from "@slicky/lang"; +import { DirectiveDefinition, DirectiveDefinitionType } from "@slicky/core/metadata"; +class TestDirective { + public output; + public namedOutput; + public static __SLICKY__INNER__DIRECTIVES__: { + [id: string]: ClassType; + } = {}; + public static __SLICKY__DIRECTIVE__METADATA__: DirectiveDefinition = { + type: DirectiveDefinitionType.Directive, + id: "TestDirective_1780897030", + className: "TestDirective", + selector: "test-directive", + exportAs: [], + onInit: false, + onDestroy: false, + onTemplateInit: false, + onUpdate: false, + onAttach: false, + inputs: [], + outputs: [ + { property: "output", name: "output" }, + { property: "namedOutput", name: "custom-output-name" } + ], + elements: [], + events: [], + directives: [], + childDirectives: [], + childrenDirectives: [] + }; +} diff --git a/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.original.ts b/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.original.ts new file mode 100644 index 0000000..1a0e740 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.original.ts @@ -0,0 +1,16 @@ +import {Filter, FilterInterface} from '@slicky/core'; + + +@Filter({ + name: 'test-filter', +}) +class TestFilter implements FilterInterface +{ + + + public transform(value: any): string + { + return value.toString(); + } + +} diff --git a/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.updated.ts b/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.updated.ts new file mode 100644 index 0000000..d3a2778 --- /dev/null +++ b/packages/compiler-cli/tests/data/transformers/filterTransformer/valid.updated.ts @@ -0,0 +1,11 @@ +import { Filter, FilterInterface } from '@slicky/core'; +import { FilterMetadata } from "@slicky/core/metadata"; +class TestFilter implements FilterInterface { + public transform(value: any): string { + return value.toString(); + } + public static __SLICKY__FILTER__METADATA__: FilterMetadata = { + className: "TestFilter", + name: "test-filter" + }; +} diff --git a/packages/compiler-cli/tests/helpers.ts b/packages/compiler-cli/tests/helpers.ts new file mode 100644 index 0000000..719f8a6 --- /dev/null +++ b/packages/compiler-cli/tests/helpers.ts @@ -0,0 +1,85 @@ +import {exists, clone} from '@slicky/utils'; +import {DirectiveDefinition, createDirectiveMetadata as _createDirectiveMetadata, createComponentMetadata as _createComponentMetadata} from '@slicky/core/metadata'; +import {mockModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {FilterAnalyzer, DirectiveAnalyzer, FileAnalyzer} from '../analyzers'; +import * as ts from 'typescript'; +import * as path from 'path'; +import * as fs from 'fs'; + + +export function createDirectiveMetadata(partialMetadata: any = {}): DirectiveDefinition +{ + partialMetadata.id = exists(partialMetadata.id) ? partialMetadata.id : 'TestDirective'; + partialMetadata.className = exists(partialMetadata.className) ? partialMetadata.className : 'TestDirective'; + partialMetadata.selector = exists(partialMetadata.selector) ? partialMetadata.selector : 'test-directive'; + + return _createDirectiveMetadata(partialMetadata); +} + + +export function createComponentMetadata(partialMetadata: any = {}): DirectiveDefinition +{ + partialMetadata.id = exists(partialMetadata.id) ? partialMetadata.id : 'TestComponent'; + partialMetadata.className = exists(partialMetadata.className) ? partialMetadata.className : 'TestComponent'; + partialMetadata.selector = exists(partialMetadata.selector) ? partialMetadata.selector : 'test-component'; + partialMetadata.template = exists(partialMetadata.template) ? partialMetadata.template : ''; + + return _createComponentMetadata(partialMetadata); +} + + +export function createDirectiveAnalyzer(moduleResolutionHost: ts.ModuleResolutionHost = mockModuleResolutionHost()): DirectiveAnalyzer +{ + return new DirectiveAnalyzer(new FilterAnalyzer, {}, moduleResolutionHost); +} + + +export function createFileAnalyzer(moduleResolutionHost: ts.ModuleResolutionHost = mockModuleResolutionHost()): FileAnalyzer +{ + const filterAnalyzer = new FilterAnalyzer; + const directiveAnalyzer = new DirectiveAnalyzer(filterAnalyzer, {}, moduleResolutionHost); + + return new FileAnalyzer(directiveAnalyzer, filterAnalyzer); +} + + +export function createFilePathFactory(pathParts: Array): (name: string) => string +{ + const parts = clone(pathParts); + + parts.unshift(__dirname, 'data'); + + return (name: string): string => { + return path.join(...parts, `${name}.ts`); + }; +} + + +export function createFileFactory(pathParts: Array): (name: string) => string +{ + const pathProvider = createFilePathFactory(pathParts); + + return (name: string): string => { + return fs.readFileSync(pathProvider(name), {encoding: 'utf8'}); + }; +} + + +export function createSourceFileFactory(pathParts: Array): (name: string) => ts.SourceFile +{ + const pathProvider = createFilePathFactory(pathParts); + const fileProvider = createFileFactory(pathParts); + + return (name: string): ts.SourceFile => { + const filePath = pathProvider(name); + const file = fileProvider(name); + + return ts.createSourceFile(filePath, file, ts.ScriptTarget.Latest, true); + }; +} + + +export function createTransformationResult(sourceFile: ts.SourceFile, transformers: Array>): ts.TransformationResult +{ + return >ts.transform(sourceFile, transformers); +} diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.encapsulation.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.encapsulation.ts new file mode 100644 index 0000000..63b1eab --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.encapsulation.ts @@ -0,0 +1,62 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {TemplateEncapsulation} from '@slicky/templates/templates'; +import {createComponentMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'component.encapsulation']); + + +describe('#Analyzators/DirectiveAnalyzer.component.encapsulation', () => { + + it('should throw an error when @Component.encapsulation is not valid #1', () => { + const sourceFile = createSourceFile('invalid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.'); + }); + + it('should throw an error when @Component.encapsulation is not valid #2', () => { + const sourceFile = createSourceFile('invalid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.'); + }); + + it('should throw an error when @Component.encapsulation is not valid #3', () => { + const sourceFile = createSourceFile('invalid_3'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.'); + }); + + it('should throw an error when @Component.encapsulation is unknown 3', () => { + const sourceFile = createSourceFile('invalid_4'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: encapsulation should be one of: TemplateEncapsulation.None, TemplateEncapsulation.Emulated or TemplateEncapsulation.Native.'); + }); + + it('should analyze component decorator with encapsulation', () => { + const sourceFile = createSourceFile('valid'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(component)).to.be.eql({ + dependencies: [], + definition: createComponentMetadata({ + id: 'TestComponent_412123319', + encapsulation: TemplateEncapsulation.None, + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.filters.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.filters.ts new file mode 100644 index 0000000..2ab9554 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.filters.ts @@ -0,0 +1,54 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createComponentMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'component.filters']); + + +describe('#Analyzators/DirectiveAnalyzer.component.filters', () => { + + it('should throw an error when @Component.filters is not valid', () => { + const sourceFile = createSourceFile('invalid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: filters should be an array of identifiers.'); + }); + + it('should throw an error when @Component.filters is not valid array', () => { + const sourceFile = createSourceFile('invalid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: filters should be an array of identifiers.'); + }); + + it('should parse filters', () => { + const sourceFile = createSourceFile('valid'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(component)).to.be.eql({ + dependencies: [], + definition: createComponentMetadata({ + id: 'TestComponent_412123319', + filters: [ + { + localName: 'TestFilter', + originalName: 'TestFilter', + imported: false, + path: sourceFile.fileName, + metadata: { + className: 'TestFilter', + name: 'test-filter', + }, + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.selector.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.selector.ts new file mode 100644 index 0000000..3e12830 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.selector.ts @@ -0,0 +1,39 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'component.selector']); + + +describe('#Analyzators/DirectiveAnalyzer.component.selector', () => { + + it('should throw an error when @Component.name is missing', () => { + const sourceFile = createSourceFile('invalid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: missing selector.'); + }); + + it('should throw an error when @Component.name is not valid', () => { + const sourceFile = createSourceFile('invalid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: selector should be a string.'); + }); + + it('should throw an error when @Component.name is not valid string', () => { + const sourceFile = createSourceFile('invalid_3'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: name should be a lowercased string with at least one dash.'); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.styles.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.styles.ts new file mode 100644 index 0000000..e1bda39 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.styles.ts @@ -0,0 +1,52 @@ +import {mockModuleResolutionHost, findNode} from '@slicky/typescript-api-utils'; +import {createComponentMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'component.styles']); + + +describe('#Analyzators/DirectiveAnalyzer.component.styles', () => { + + it('should throw an error when @Component.styles is not an array', () => { + const sourceFile = createSourceFile('invalid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: styles should be an array of string or simple require calls.'); + }); + + it('should throw an error when @Component.styles is invalid array', () => { + const sourceFile = createSourceFile('invalid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: styles should be an array of string or simple require calls.'); + }); + + it('should set component styles', () => { + const sourceFile = createSourceFile('valid'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + const moduleResolutionHost = mockModuleResolutionHost({ + '/styles.css': 'body {background-color: blue}', + }); + + expect(createDirectiveAnalyzer(moduleResolutionHost).analyzeDirective(component)).to.be.eql({ + dependencies: [ + '/styles.css', + ], + definition: createComponentMetadata({ + id: 'TestComponent_412123319', + styles: [ + 'body {color: red}', + 'body {background-color: blue}', + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.template.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.template.ts new file mode 100644 index 0000000..4f23212 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.component.template.ts @@ -0,0 +1,152 @@ +import {mockModuleResolutionHost, findNode} from '@slicky/typescript-api-utils'; +import {createComponentMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'component.template']); + + +describe('#Analyzators/DirectiveAnalyzer.component.template', () => { + + it('should throw an error when @Component.template is missing', () => { + const sourceFile = createSourceFile('invalid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: missing template.'); + }); + + it('should throw an error when @Component.template is not valid', () => { + const sourceFile = createSourceFile('invalid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: template should be a string, template string, arrow function, function expression or simple require call.'); + }); + + it('should throw an error when @Component.template is using not require function', () => { + const sourceFile = createSourceFile('invalid_3'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: template should be a simple require call.'); + }); + + it('should throw an error when @Component.template is using require without arguments', () => { + const sourceFile = createSourceFile('invalid_4'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: template should be a simple require call.'); + }); + + it('should throw an error when @Component.template is using require with wrong argument', () => { + const sourceFile = createSourceFile('invalid_5'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: template should be a simple require call.'); + }); + + it('should throw an error when @Component.template is using require without file extension', () => { + const sourceFile = createSourceFile('invalid_6'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: required template must have file extension.'); + }); + + it('should throw an error when @Component.template is using require with not html extension', () => { + const sourceFile = createSourceFile('invalid_7'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(component); + }).to.throw(Error, 'Component TestComponent: required template must have file extension.'); + }); + + it('should analyze component decorator with string template', () => { + const sourceFile = createSourceFile('valid_1'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(component)).to.be.eql({ + dependencies: [], + definition: createComponentMetadata({ + id: 'TestComponent_544008761', + template: 'hello world', + }), + }); + }); + + it('should analyze component decorator with template from file', () => { + const sourceFile = createSourceFile('valid_2'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + const moduleResolutionHost = mockModuleResolutionHost({ + '/template.html': 'hello world', + }); + + expect(createDirectiveAnalyzer(moduleResolutionHost).analyzeDirective(component)).to.be.eql({ + dependencies: [ + '/template.html', + ], + definition: createComponentMetadata({ + id: 'TestComponent_913547418', + template: 'hello world', + }), + }); + }); + + it('should analyze component decorator with template in template string', () => { + const sourceFile = createSourceFile('valid_3'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(component)).to.be.eql({ + dependencies: [], + definition: createComponentMetadata({ + id: 'TestComponent_3558690043', + template: 'hello world', + }), + }); + }); + + it('should analyze component decorator with template in variable in local file', () => { + const sourceFile = createSourceFile('valid_4'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(component)).to.be.eql({ + dependencies: [], + definition: createComponentMetadata({ + id: 'TestComponent_1955817308', + template: 'hello world', + }), + }); + }); + + it('should analyze component decorator with template in variable from imported file', () => { + const sourceFile = createSourceFile('valid_5'); + const component = findNode(ts.SyntaxKind.ClassDeclaration, 'TestComponent', sourceFile); + + const moduleResolutionHost = mockModuleResolutionHost({ + '/template.ts': 'export const TEMPLATE = "hello world";', + }); + + expect(createDirectiveAnalyzer(moduleResolutionHost).analyzeDirective(component)).to.be.eql({ + dependencies: [ + '/template.ts', + ], + definition: createComponentMetadata({ + id: 'TestComponent_373721789', + template: 'hello world', + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childDirectives.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childDirectives.ts new file mode 100644 index 0000000..21d9444 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childDirectives.ts @@ -0,0 +1,77 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory, createFilePathFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createPath = createFilePathFactory(['analyzers', 'directiveAnalyzer', 'directive.childDirectives']); +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.childDirectives']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.childDirectives', () => { + + it('should throw an error when @ChildDirective() has no arguments', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.child: @ChildDirective() decorator should have identifier argument.'); + }); + + it('should throw an error when @ChildDirective() has invalid arguments', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.child: @ChildDirective() decorator should have identifier argument.'); + }); + + it('should compile child directives', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive, true, false)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + childDirectives: [ + { + property: 'child', + required: false, + directive: { + localName: 'TestChildDirective', + originalName: 'TestChildDirective', + imported: false, + path: createPath('valid'), + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestChildDirective_680227610', + className: 'TestChildDirective', + selector: 'test-child-directive', + }), + }, + }, + { + property: 'childRequired', + required: true, + directive: { + localName: 'TestChildDirective', + originalName: 'TestChildDirective', + imported: false, + path: createPath('valid'), + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestChildDirective_680227610', + className: 'TestChildDirective', + selector: 'test-child-directive', + }), + }, + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childrenDirectives.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childrenDirectives.ts new file mode 100644 index 0000000..acbbfde --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.childrenDirectives.ts @@ -0,0 +1,60 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createFilePathFactory, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createPath = createFilePathFactory(['analyzers', 'directiveAnalyzer', 'directive.childrenDirectives']); +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.childrenDirectives']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.childrenDirectives', () => { + + it('should throw an error when @ChildrenDirective() has no arguments', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.child: @ChildrenDirective() decorator should have identifier argument.'); + }); + + it('should throw an error when @ChildrenDirective() has invalid arguments', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.child: @ChildrenDirective() decorator should have identifier argument.'); + }); + + it('should compile children directives', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive, true, false)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + childrenDirectives: [ + { + property: 'children', + directive: { + localName: 'TestChildrenDirective', + originalName: 'TestChildrenDirective', + imported: false, + path: createPath('valid'), + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestChildrenDirective_2962788058', + className: 'TestChildrenDirective', + selector: 'test-children-directive', + }), + }, + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.customMetadata.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.customMetadata.ts new file mode 100644 index 0000000..e469498 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.customMetadata.ts @@ -0,0 +1,23 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.customMetadata']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.customMetadata', () => { + + it('should analyze custom metadata', () => { + const sourceFile = createSourceFile('valid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + const analyzed = createDirectiveAnalyzer().analyzeDirective(directive); + + expect(analyzed.dependencies).to.be.eql([]); + expect(analyzed.definition.customData.kind).to.be.equal(ts.SyntaxKind.StringLiteral); + expect(analyzed.definition.customData.text).to.be.equal('hello world'); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.directives.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.directives.ts new file mode 100644 index 0000000..925adb7 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.directives.ts @@ -0,0 +1,65 @@ +import {findNode, fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.directives']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.directives', () => { + + it('should throw an error when @Directive.directives is not valid', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: directives should be an array of identifiers.'); + }); + + it('should throw an error when @Directive.directives is not valid array', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: directives should be an array of identifiers.'); + }); + + it('should throw an error when @Directive.directives is an array with not exported directive', () => { + const sourceFile = createSourceFile('invalid_3'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer(fsModuleResolutionHost()).analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: can not use inner directive TestChildDirective, class is not exported.'); + }); + + it('should analyze directive decorator with inner directives', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive, true, false)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + directives: [ + { + localName: 'TestChildDirective', + originalName: 'TestChildDirective', + imported: false, + path: sourceFile.fileName, + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestChildDirective_680227610', + className: 'TestChildDirective', + selector: 'test-child-directive', + }), + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.exportAs.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.exportAs.ts new file mode 100644 index 0000000..10d2403 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.exportAs.ts @@ -0,0 +1,56 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.exportAs']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.exportAs', () => { + + it('should throw an error when @Directive.exportAs is not valid', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: exportAs should be a string or an array of strings.'); + }); + + it('should throw an error when @Directive.exportAs array is not valid', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: exportAs should be a string or an array of strings.'); + }); + + it('should analyze directive decorator with exportAs as string', () => { + const sourceFile = createSourceFile('valid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_1019046009', + exportAs: ['dir'], + }), + }); + }); + + it('should analyze directive decorator with exportAs as array', () => { + const sourceFile = createSourceFile('valid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_797356250', + exportAs: ['dirA', 'dirB'], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostElements.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostElements.ts new file mode 100644 index 0000000..0e5a01d --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostElements.ts @@ -0,0 +1,54 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.hostElements']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.hostElements', () => { + + it('should throw an error when @HostElement() has no arguments', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.el: @HostElement() decorator should have string selector argument.'); + }); + + it('should throw an error when @HostElement() has wrong argument', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.el: @HostElement() decorator should have string selector argument.'); + }); + + it('should load host elements', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + elements: [ + { + property: 'el', + selector: 'button', + required: false, + }, + { + property: 'elRequired', + selector: 'div', + required: true, + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostEvents.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostEvents.ts new file mode 100644 index 0000000..c9bcdb2 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.hostEvents.ts @@ -0,0 +1,83 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.hostEvents']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.hostEvents', () => { + + it('should throw an error when @HostEvent() has no arguments', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.onClick: @HostEvent() decorator should have string event name argument.'); + }); + + it('should throw an error when @HostEvent() has wrong event argument', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.onClick: @HostEvent() decorator should have string event name argument.'); + }); + + it('should throw an error when @HostEvent() has wrong selector argument', () => { + const sourceFile = createSourceFile('invalid_3'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.onClick: @HostEvent() decorator should have string event name argument.'); + }); + + it('should throw an error when @HostEvent depends on unknown @HostElement', () => { + const sourceFile = createSourceFile('invalid_4'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.onClick: @HostEvent() requires unknown @HostElement() on TestDirective.btn.'); + }); + + it('should load host events', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + elements: [ + { + property: 'el', + selector: 'button', + required: false, + }, + ], + events: [ + { + method: 'onEvent', + event: 'click', + }, + { + method: 'onEventWithSelector', + event: 'click', + selector: 'div', + }, + { + method: 'onEventWithHostElement', + event: 'click', + selector: 'button', + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.id.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.id.ts new file mode 100644 index 0000000..233f700 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.id.ts @@ -0,0 +1,33 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.id']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.id', () => { + + it('should throw an error when @Directive.id is not valid', () => { + const sourceFile = createSourceFile('invalid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: id should be a string.'); + }); + + it('should analyze directive decorator with custom id', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'app:directive', + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.inputs.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.inputs.ts new file mode 100644 index 0000000..98e510c --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.inputs.ts @@ -0,0 +1,55 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.inputs']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.inputs', () => { + + it('should throw an error when @Input() has wrong argument', () => { + const sourceFile = createSourceFile('invalid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.input: @Input() decorator should have no argument or string.'); + }); + + it('should load inputs', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + inputs: [ + { + name: 'input', + property: 'input', + required: false, + }, + { + name: 'custom-name-input', + property: 'inputWithDifferentName', + required: false, + }, + { + name: 'input-required', + property: 'inputRequired', + required: true, + }, + { + name: 'custom-name-required-input', + property: 'inputRequiredWithDifferentName', + required: true, + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.lifeCycleEvents.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.lifeCycleEvents.ts new file mode 100644 index 0000000..d3758ae --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.lifeCycleEvents.ts @@ -0,0 +1,29 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.lifeCycleEvents']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.lifeCycleEvents', () => { + + it('should compile life cycle events', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + onInit: true, + onDestroy: true, + onTemplateInit: true, + onUpdate: true, + onAttach: true, + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.outputs.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.outputs.ts new file mode 100644 index 0000000..66ee8ca --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.outputs.ts @@ -0,0 +1,43 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.outputs']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.outputs', () => { + + it('should throw an error when @Output() has wrong argument', () => { + const sourceFile = createSourceFile('invalid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'TestDirective.output: @Output() decorator should have no argument or string.'); + }); + + it('should load outputs', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + outputs: [ + { + property: 'output', + name: 'output', + }, + { + property: 'outputWithDifferentName', + name: 'custom-name-output', + }, + ], + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.override.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.override.ts new file mode 100644 index 0000000..dfc1a6a --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.override.ts @@ -0,0 +1,44 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.override']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.override', () => { + + it('should throw an error when @Directive.override is not valid', () => { + const sourceFile = createSourceFile('invalid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: override should be an identifier.'); + }); + + it('should analyze directive decorator with override', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive, true, false)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + override: { + localName: 'TestBaseDirective', + originalName: 'TestBaseDirective', + imported: false, + path: sourceFile.fileName, + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestBaseDirective_2586426242', + className: 'TestBaseDirective', + }), + }, + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.selector.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.selector.ts new file mode 100644 index 0000000..aced257 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.directive.selector.ts @@ -0,0 +1,30 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer', 'directive.selector']); + + +describe('#Analyzators/DirectiveAnalyzer.directive.selector', () => { + + it('should throw an error when selector for @Directive is missing', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: missing selector.'); + }); + + it('should throw an error when @Directive.selector is not valid', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: selector should be a string.'); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.ts b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.ts new file mode 100644 index 0000000..bda0f3a --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/directiveAnalyzer.ts @@ -0,0 +1,58 @@ +import {findNode} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createDirectiveAnalyzer, createSourceFileFactory} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'directiveAnalyzer']); + + +describe('#Analyzators/DirectiveAnalyzer', () => { + + it('should return undefined if class is not a directive and need is set to false', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive, false)).to.be.equal(undefined); + }); + + it('should throw an error when class is not a directive and need is set to true', () => { + const sourceFile = createSourceFile('invalid_1'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Class TestDirective is not a directive or component. Please add @Directive() or @Component() class decorator.'); + }); + + it('should throw an error when missing configuration object for @Directive', () => { + const sourceFile = createSourceFile('invalid_2'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: missing metadata configuration object.'); + }); + + it('should throw an error when directive has invalid configuration object', () => { + const sourceFile = createSourceFile('invalid_3'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(() => { + createDirectiveAnalyzer().analyzeDirective(directive); + }).to.throw(Error, 'Directive TestDirective: missing metadata configuration object.'); + }); + + it('should analyze directive decorator', () => { + const sourceFile = createSourceFile('valid'); + const directive = findNode(ts.SyntaxKind.ClassDeclaration, 'TestDirective', sourceFile); + + expect(createDirectiveAnalyzer().analyzeDirective(directive)).to.be.eql({ + dependencies: [], + definition: createDirectiveMetadata({ + id: 'TestDirective_3669703671', + }), + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/fileAnalyzer.ts b/packages/compiler-cli/tests/tests/analyzers/fileAnalyzer.ts new file mode 100644 index 0000000..da9bb8f --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/fileAnalyzer.ts @@ -0,0 +1,282 @@ +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {createDirectiveMetadata, createComponentMetadata, createFileAnalyzer, createSourceFileFactory, createFilePathFactory} from '../../helpers'; +import {expect} from 'chai'; + + +const createSourceFile = createSourceFileFactory(['analyzers', 'fileAnalyzer']); +const createFilePath = createFilePathFactory(['analyzers', 'fileAnalyzer']); + + +describe('#Analyzers/FileAnalyzer', () => { + + describe('analyzeFile()', () => { + + it('should analyze empty file', () => { + const sourceFile = createSourceFile('empty'); + + expect(createFileAnalyzer().analyzeFile(sourceFile)).to.be.eql({ + dependencies: [], + filters: [], + directives: [], + }); + }); + + it('should analyze file with filters', () => { + const sourceFile = createSourceFile('filters'); + + expect(createFileAnalyzer().analyzeFile(sourceFile)).to.be.eql({ + dependencies: [], + filters: [ + { + exported: false, + metadata: { + className: 'NotExportedFilter', + name: 'not-exported', + }, + }, + { + exported: true, + metadata: { + className: 'ExportedFilter', + name: 'exported', + }, + }, + ], + directives: [], + }); + }); + + it('should analyze file with directives', () => { + const sourceFile = createSourceFile('directives'); + + expect(createFileAnalyzer().analyzeFile(sourceFile)).to.be.eql({ + dependencies: [], + filters: [], + directives: [ + { + exported: false, + metadata: createDirectiveMetadata({ + id: 'NotExportedDirective_105271944', + className: 'NotExportedDirective', + selector: 'not-exported-directive', + }), + }, + { + exported: true, + metadata: createDirectiveMetadata({ + id: 'ExportedDirective_3764721541', + className: 'ExportedDirective', + selector: 'exported-directive', + }), + }, + ], + }); + }); + + it('should load directive with inner directives from same file', () => { + const sourceFile = createSourceFile('directive.innerDirectives'); + + const childDirectiveMetadata = createDirectiveMetadata({ + id: 'TestChildDirective_1257297583', + className: 'TestChildDirective', + selector: 'test-child-directive', + }); + + const analyzed = createFileAnalyzer().analyzeFile(sourceFile, false); + + expect(analyzed).to.be.eql({ + dependencies: [], + filters: [], + directives: [ + { + exported: false, + metadata: childDirectiveMetadata, + }, + { + exported: false, + metadata: createDirectiveMetadata({ + id: 'TestDirective_438549218', + directives: [ + { + localName: 'TestChildDirective', + originalName: 'TestChildDirective', + imported: false, + path: sourceFile.fileName, + node: undefined, + metadata: childDirectiveMetadata, + }, + ], + }), + }, + ], + }); + + expect(analyzed.directives[0].metadata).to.be.equal(analyzed.directives[1].metadata.directives[0].metadata); + }); + + it('should analyze file with inner directives from array', () => { + const sourceFile = createSourceFile('directives.innerDirectives.array'); + + expect(createFileAnalyzer(fsModuleResolutionHost()).analyzeFile(sourceFile, false)).to.be.eql({ + dependencies: [ + createFilePath('directives.innerDirectives.array.index'), + createFilePath('directives.innerDirectives.array.childDirective'), + ], + filters: [], + directives: [ + { + exported: false, + metadata: createDirectiveMetadata({ + id: 'TestDirective_3764400614', + directives: [ + { + localName: 'TestChildDirective', + originalName: 'TestChildDirective', + imported: true, + path: createFilePath('directives.innerDirectives.array.childDirective'), + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestChildDirective_2585284280', + className: 'TestChildDirective', + selector: 'test-child-directive', + }), + }, + ], + }), + }, + ], + }); + }); + + it('should load directive with override directive from different file', () => { + const sourceFile = createSourceFile('directive.override.import'); + + expect(createFileAnalyzer(fsModuleResolutionHost()).analyzeFile(sourceFile, false)).to.be.eql({ + dependencies: [ + createFilePath('directive.override.import.base'), + ], + filters: [], + directives: [ + { + exported: false, + metadata: createDirectiveMetadata({ + id: 'TestDirective_2902471519', + override: { + localName: 'TestBaseDirective', + originalName: 'TestBaseDirective', + imported: true, + path: createFilePath('directive.override.import.base'), + node: undefined, + metadata: createDirectiveMetadata({ + id: 'TestBaseDirective_2702631665', + className: 'TestBaseDirective', + }), + }, + }), + }, + ], + }); + }); + + it('should load directive with filters from same file', () => { + const sourceFile = createSourceFile('component.filters'); + + expect(createFileAnalyzer().analyzeFile(sourceFile)).to.be.eql({ + dependencies: [], + filters: [ + { + exported: false, + metadata: { + className: 'TestFilter', + name: 'test-filter', + }, + }, + ], + directives: [ + { + exported: false, + metadata: createComponentMetadata({ + id: 'TestComponent_1660393203', + filters: [ + { + localName: 'TestFilter', + originalName: 'TestFilter', + imported: false, + path: sourceFile.fileName, + metadata: { + className: 'TestFilter', + name: 'test-filter', + }, + }, + ], + }), + }, + ], + }); + }); + + it('should load directive with filters from imported file', () => { + const sourceFile = createSourceFile('component.filters.imported'); + + expect(createFileAnalyzer(fsModuleResolutionHost()).analyzeFile(sourceFile)).to.be.eql({ + dependencies: [ + createFilePath('component.filters.imported.filter'), + ], + filters: [], + directives: [ + { + exported: false, + metadata: createComponentMetadata({ + id: 'TestComponent_3936316353', + filters: [ + { + localName: 'TestFilter', + originalName: 'TestFilter', + imported: true, + path: createFilePath('component.filters.imported.filter'), + metadata: { + className: 'TestFilter', + name: 'test-filter', + }, + }, + ], + }), + }, + ], + }); + }); + + it('should load directive with aliased filters from imported file', () => { + const sourceFile = createSourceFile('component.filters.aliased'); + + expect(createFileAnalyzer(fsModuleResolutionHost()).analyzeFile(sourceFile)).to.be.eql({ + dependencies: [ + createFilePath('component.filters.aliased.filter'), + ], + filters: [], + directives: [ + { + exported: false, + metadata: createComponentMetadata({ + id: 'TestComponent_1903920458', + filters: [ + { + localName: 'MyFilter', + originalName: 'TestFilter', + imported: true, + path: createFilePath('component.filters.aliased.filter'), + metadata: { + className: 'TestFilter', + name: 'test-filter', + }, + }, + ], + }), + }, + ], + }); + }); + + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.name.ts b/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.name.ts new file mode 100644 index 0000000..f6559f4 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.name.ts @@ -0,0 +1,55 @@ +import {FilterAnalyzer} from '../../../analyzers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +let analyzer: FilterAnalyzer; + + +describe('#Analyzators/FilterAnalyzer.name', () => { + + beforeEach(() => { + analyzer = new FilterAnalyzer; + }); + + it('should throw an error when @Filter.name is missing', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createCall(ts.createIdentifier('Filter'), [], [ + ts.createObjectLiteral([]), + ])), + ], + [], + 'TestFilter', + [], + [], + [], + ); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Filter TestFilter: missing name.'); + }); + + it('should throw an error when @Filter.name is not valid', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createCall(ts.createIdentifier('Filter'), [], [ + ts.createObjectLiteral([ + ts.createPropertyAssignment(ts.createIdentifier('name'), ts.createLiteral(10)), + ]), + ])), + ], + [], + 'TestFilter', + [], + [], + [], + ); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Filter TestFilter: name should be a string.'); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.ts b/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.ts new file mode 100644 index 0000000..0d004a2 --- /dev/null +++ b/packages/compiler-cli/tests/tests/analyzers/filterAnalyzer.ts @@ -0,0 +1,106 @@ +import {FilterAnalyzer} from '../../../analyzers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +let analyzer: FilterAnalyzer; + + +describe('#Analyzators/FilterAnalyzer', () => { + + beforeEach(() => { + analyzer = new FilterAnalyzer; + }); + + it('should return undefined when class does not have a @Filter() decorator and need flag is false', () => { + const c = ts.createClassDeclaration([], [], 'TestFilter', [], [], []); + + expect(analyzer.analyzeFilter(c, false)).to.be.equal(undefined); + }); + + it('should throw an error when class does not have a @Filter() decorator and need flag is true', () => { + const c = ts.createClassDeclaration([], [], 'TestFilter', [], [], []); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Class "TestFilter" is not a valid filter. Please add @Filter() decorator.'); + }); + + it('should throw an error when class does not have a valid @Filter() decorator', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createIdentifier('Filter')), + ], + [], + 'TestFilter', + [], + [], + [], + ); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Class "TestFilter" is not a valid filter. Please add @Filter() decorator.'); + }); + + it('should throw an error when missing configuration object for @Filter()', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createCall(ts.createIdentifier('Filter'), [], [])), + ], + [], + 'TestFilter', + [], + [], + [], + ); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Filter TestFilter: missing metadata configuration object.'); + }); + + it('should throw an error when filter has invalid configuration object', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createCall(ts.createIdentifier('Filter'), [], [ + ts.createLiteral('configuration'), + ])), + ], + [], + 'TestFilter', + [], + [], + [], + ); + + expect(() => { + analyzer.analyzeFilter(c); + }).to.throw(Error, 'Filter TestFilter: missing metadata configuration object.'); + }); + + it('should analyze filter decorator', () => { + const c = ts.createClassDeclaration( + [ + ts.createDecorator(ts.createCall(ts.createIdentifier('Filter'), [], [ + ts.createObjectLiteral([ + ts.createPropertyAssignment(ts.createIdentifier('name'), ts.createLiteral('revert')), + ]), + ])), + ], + [], + 'TestFilter', + [], + [ + ts.createExpressionWithTypeArguments([], ts.createIdentifier('FilterInterface')), + ], + [], + ); + + expect(analyzer.analyzeFilter(c)).to.be.eql({ + className: 'TestFilter', + name: 'revert', + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/compiler/compiler.ts b/packages/compiler-cli/tests/tests/compiler/compiler.ts new file mode 100644 index 0000000..5656bf8 --- /dev/null +++ b/packages/compiler-cli/tests/tests/compiler/compiler.ts @@ -0,0 +1,30 @@ +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {Compiler, CompiledFileResult} from '../../../newCompiler'; +import {createFileFactory, createFilePathFactory, createFileAnalyzer} from '../../helpers'; +import {expect} from 'chai'; + + +const createPath = createFilePathFactory(['compiler']); +const createFile = createFileFactory(['compiler']); + + +function compileFile(name: string): CompiledFileResult +{ + const moduleResolutionHost = fsModuleResolutionHost(); + const fileAnalyzer = createFileAnalyzer(moduleResolutionHost); + const compiler = new Compiler(fileAnalyzer, {}, moduleResolutionHost); + + return compiler.compileFile(createPath(name), createFile(name)); +} + + +describe('#Compiler/Compiler', () => { + + it('should compile simple file', () => { + const compiled = compileFile('valid_1.original'); + + expect(compiled.dependencies).to.be.eql([]); + expect(compiled.sourceText).to.be.equal(createFile('valid_1.updated')); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/parser.ts b/packages/compiler-cli/tests/tests/parser.ts index 974d3aa..9a7edbe 100644 --- a/packages/compiler-cli/tests/tests/parser.ts +++ b/packages/compiler-cli/tests/tests/parser.ts @@ -6,13 +6,13 @@ import * as path from 'path'; function parse(name: string, done: (err: Error, file: ParsedFile, path: string, expected: string) => void): void { - const originalPath = path.resolve(`${__dirname}/../data/${name}.original.ts`); + const originalPath = path.resolve(`${__dirname}/../data/_old/${name}.original.ts`); (new Parser(originalPath)).parse((err, file) => { if (err) { done(err, undefined, undefined, undefined); } else { - done(undefined, file, originalPath, readFileSync(`${__dirname}/../data/${name}.expected.ts`, {encoding: 'utf8'})); + done(undefined, file, originalPath, readFileSync(`${__dirname}/../data/_old/${name}.expected.ts`, {encoding: 'utf8'})); } }); } diff --git a/packages/compiler-cli/tests/tests/transformers/directiveTransformer.components.ts b/packages/compiler-cli/tests/tests/transformers/directiveTransformer.components.ts new file mode 100644 index 0000000..6fed70d --- /dev/null +++ b/packages/compiler-cli/tests/tests/transformers/directiveTransformer.components.ts @@ -0,0 +1,62 @@ +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {createDirectiveTransformer, createFilterTransformer} from '../../../transformers'; +import {FileDefinition} from '../../../analyzers'; +import {createSourceFileFactory, createFileFactory, createTransformationResult, createFileAnalyzer} from '../../helpers'; +import * as ts from 'typescript'; +import * as path from 'path'; +import {expect} from 'chai'; + + +const createFile = createFileFactory(['transformers', 'directiveTransformer.components']); +const createSourceFile = createSourceFileFactory(['transformers', 'directiveTransformer.components']); + + +function compareSource(name: string, onDone?: (file: FileDefinition) => void): void +{ + const moduleResolutionHost = fsModuleResolutionHost(); + const fileAnalyzer = createFileAnalyzer(moduleResolutionHost); + const sourceFile = createSourceFile(`${name}.original`); + const transformed = createTransformationResult(sourceFile, [ + createFilterTransformer(fileAnalyzer, {}, moduleResolutionHost), + createDirectiveTransformer(fileAnalyzer, {}, moduleResolutionHost, onDone), + ]).transformed; + + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + }); + + expect(printer.printNode(ts.EmitHint.SourceFile, transformed[0], transformed[0])).to.be.equal(createFile(`${name}.updated`)); +} + + +describe('#Transformers/DirectiveTransformer.components', () => { + + it('should transform simple component class', () => { + compareSource('valid_1', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform component with template from html file', () => { + compareSource('valid_2', (file) => { + expect(file.dependencies).to.be.eql([ + path.normalize(path.join(__dirname, '..', '..', 'data', 'transformers', 'directiveTransformer.components', 'valid_2.template.html')), + ]); + }); + }); + + it('should transform component with inner directive and @ChildDirective()', () => { + compareSource('valid_3', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform component with inner directive and @ChildDirective() from imported file', () => { + compareSource('valid_4', (file) => { + expect(file.dependencies).to.be.eql([ + path.normalize(path.join(__dirname, '..', '..', 'data', 'transformers', 'directiveTransformer.components', 'valid_4.childDirective.ts')), + ]); + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/transformers/directiveTransformer.ts b/packages/compiler-cli/tests/tests/transformers/directiveTransformer.ts new file mode 100644 index 0000000..342c685 --- /dev/null +++ b/packages/compiler-cli/tests/tests/transformers/directiveTransformer.ts @@ -0,0 +1,187 @@ +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {createDirectiveTransformer, createFilterTransformer} from '../../../transformers'; +import {FileDefinition} from '../../../analyzers'; +import {createSourceFileFactory, createFileFactory, createFilePathFactory, createTransformationResult, createFileAnalyzer} from '../../helpers'; +import * as ts from 'typescript'; +import * as path from 'path'; +import {expect} from 'chai'; + + +const createPath = createFilePathFactory(['transformers', 'directiveTransformer']); +const createFile = createFileFactory(['transformers', 'directiveTransformer']); +const createSourceFile = createSourceFileFactory(['transformers', 'directiveTransformer']); + + +function compareSource(name: string, onDone?: (file: FileDefinition) => void): void +{ + const moduleResolutionHost = fsModuleResolutionHost(); + const fileAnalyzer = createFileAnalyzer(moduleResolutionHost); + const sourceFile = createSourceFile(`${name}.original`); + const transformed = createTransformationResult(sourceFile, [ + createFilterTransformer(fileAnalyzer, {}, moduleResolutionHost), + createDirectiveTransformer(fileAnalyzer, {}, moduleResolutionHost, onDone), + ]).transformed; + + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + }); + + expect(printer.printNode(ts.EmitHint.SourceFile, transformed[0], transformed[0])).to.be.equal(createFile(`${name}.updated`)); +} + + +describe('#Transformers/DirectiveTransformer', () => { + + it('should transform simple directive class', () => { + compareSource('valid_1', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform simple component class', () => { + compareSource('valid_2', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with override directive from same file', () => { + compareSource('valid_3', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with override directive from imported file', () => { + compareSource('valid_4', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_4.overrideDirective'), + ]); + }); + }); + + it('should transform directive with string exportAs', () => { + compareSource('valid_5', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with array exportAs', () => { + compareSource('valid_6', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with life cycle events', () => { + compareSource('valid_7', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with inputs', () => { + compareSource('valid_8', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with outputs', () => { + compareSource('valid_9', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with host elements', () => { + compareSource('valid_10', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with host events', () => { + compareSource('valid_11', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with child directives from same file', () => { + compareSource('valid_12', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with child directives from imported file', () => { + compareSource('valid_13', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_13.childDirective'), + ]); + }); + }); + + it('should transform directive with children directives from same file', () => { + compareSource('valid_14', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with children directives from imported file', () => { + compareSource('valid_15', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_15.childrenDirective'), + ]); + }); + }); + + it('should transform directive with inner directives from same file', () => { + compareSource('valid_16', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with inner directives from array in same file', () => { + compareSource('valid_17', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with inner directives from imported file', () => { + compareSource('valid_18', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_18.innerDirective'), + ]); + }); + }); + + it('should transform directive with inner directives from array in imported file', () => { + compareSource('valid_19', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_19.innerDirective'), + ]); + }); + }); + + it('should transform directive with filters from same file', () => { + compareSource('valid_20', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + + it('should transform directive with filters from imported file', () => { + compareSource('valid_21', (file) => { + expect(file.dependencies).to.be.eql([ + createPath('valid_21.filter'), + ]); + }); + }); + + it('should transform directive with styles from imported file', () => { + compareSource('valid_22', (file) => { + expect(file.dependencies).to.be.eql([ + path.normalize(path.join(__dirname, '..', '..', 'data', 'transformers', 'directiveTransformer', 'valid_22.styles.css')), + ]); + }); + }); + + it('should transform directive with custom data', () => { + compareSource('valid_23', (file) => { + expect(file.dependencies).to.be.eql([]); + }); + }); + +}); diff --git a/packages/compiler-cli/tests/tests/transformers/filterTransformer.ts b/packages/compiler-cli/tests/tests/transformers/filterTransformer.ts new file mode 100644 index 0000000..4824be9 --- /dev/null +++ b/packages/compiler-cli/tests/tests/transformers/filterTransformer.ts @@ -0,0 +1,33 @@ +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import {createFilterTransformer} from '../../../transformers'; +import {createSourceFileFactory, createFileFactory, createTransformationResult, createFileAnalyzer} from '../../helpers'; +import * as ts from 'typescript'; +import {expect} from 'chai'; + + +const createFile = createFileFactory(['transformers', 'filterTransformer']); +const createSourceFile = createSourceFileFactory(['transformers', 'filterTransformer']); + + +function compareSource(name: string): void +{ + const sourceFile = createSourceFile(`${name}.original`); + const transformed = createTransformationResult(sourceFile, [ + createFilterTransformer(createFileAnalyzer(), {}, fsModuleResolutionHost()), + ]).transformed; + + const printer = ts.createPrinter({ + newLine: ts.NewLineKind.LineFeed, + }); + + expect(printer.printNode(ts.EmitHint.SourceFile, transformed[0], transformed[0])).to.be.equal(createFile(`${name}.updated`)); +} + + +describe('#Transformers/FilterTransformer', () => { + + it('should transform filter class', () => { + compareSource('valid'); + }); + +}); diff --git a/packages/compiler-cli/transformers/directiveTransformer.ts b/packages/compiler-cli/transformers/directiveTransformer.ts new file mode 100644 index 0000000..67e4d92 --- /dev/null +++ b/packages/compiler-cli/transformers/directiveTransformer.ts @@ -0,0 +1,307 @@ +import {find, clone, map, camelCaseToHyphens, exists, isFunction} from '@slicky/utils'; +import {AppendImportsBuffer, isClassInstanceOf} from '@slicky/typescript-api-utils'; +import {TemplateEncapsulation} from '@slicky/core'; +import { + STATIC_FILTERS_STORAGE, STATIC_INNER_DIRECTIVES_STORAGE, STATIC_DIRECTIVE_METADATA_STORAGE, + DirectiveDefinition, DirectiveDefinitionType, DirectiveDefinitionInput, DirectiveDefinitionOutput, + DirectiveDefinitionElement, DirectiveDefinitionEvent, DirectiveDefinitionChildDirective, + DirectiveDefinitionChildrenDirective, DirectiveDefinitionInnerDirective, DirectiveDefinitionFilterMetadata, +} from '@slicky/core/metadata'; +import {Compiler} from '@slicky/compiler'; +import {FileAnalyzer, FileDefinitionDirective, FileDefinition} from '../analyzers'; +import * as ts from 'typescript'; +import * as path from 'path'; +import {forEach} from "../../utils/utils/objects"; + + +const KNOWN_METADATA_OPTIONS: Array = [ + 'type', 'id', 'className', 'selector', 'exportAs', 'onInit', 'onDestroy', 'onTemplateInit', 'onUpdate', 'onAttach', + 'inputs', 'outputs', 'elements', 'events', 'directives', 'override', 'childDirectives', 'childrenDirectives', + 'template', 'filters', 'styles', 'encapsulation', +]; + + +export function createDirectiveTransformer(fileAnalyzer: FileAnalyzer, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost, onDone?: (file: FileDefinition) => void): ts.TransformerFactory +{ + return function filterTransformer(context: ts.TransformationContext): ts.Transformer + { + return (sourceFile: ts.SourceFile) => { + const analyzedFile = fileAnalyzer.analyzeFile(sourceFile); + const importsBuffer = new AppendImportsBuffer; + + function visit(node: ts.Node): ts.Node + { + if (ts.isClassDeclaration(node) && (node).name) { + const directiveClass = node; + const directive: FileDefinitionDirective = find(analyzedFile.directives, (directive: FileDefinitionDirective) => { + return directive.metadata.className === (directiveClass.name).text; + }); + + if (directive) { + const members = map(clone(directiveClass.members), (member: ts.ClassElement) => { + if (member.decorators && member.decorators.length) { + if (ts.isPropertyDeclaration(member)) { + const property = member; + return ts.createProperty([], property.modifiers, property.name, property.questionToken, property.type, property.initializer); + + } else if (ts.isMethodDeclaration(member)) { + const method = member; + return ts.createMethod([], method.modifiers, method.asteriskToken, method.name, method.questionToken, method.typeParameters, method.parameters, method.type, method.body); + } + } + + return member; + }); + + importsBuffer.add('@slicky/lang', undefined, 'ClassType'); + importsBuffer.add('@slicky/core/metadata', undefined, 'DirectiveDefinition'); + importsBuffer.add('@slicky/core/metadata', undefined, 'DirectiveDefinitionType'); + + if (directive.metadata.type === DirectiveDefinitionType.Component) { + importsBuffer.add('@slicky/core', undefined, 'FilterInterface'); + importsBuffer.add('@slicky/core', undefined, 'TemplateEncapsulation'); + + members.push(ts.createProperty( + [], + [ + ts.createToken(ts.SyntaxKind.PublicKeyword), + ts.createToken(ts.SyntaxKind.StaticKeyword), + ], + STATIC_FILTERS_STORAGE, + undefined, + ts.createTypeLiteralNode([ + ts.createIndexSignature(undefined, undefined, [ + ts.createParameter(undefined, undefined, undefined, 'name', undefined, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)), + ], ts.createTypeReferenceNode('ClassType', [ + ts.createTypeReferenceNode('FilterInterface', []), + ])), + ]), + createFiltersObject(directive.metadata), + )); + } + + members.push(ts.createProperty( + [], + [ + ts.createToken(ts.SyntaxKind.PublicKeyword), + ts.createToken(ts.SyntaxKind.StaticKeyword), + ], + STATIC_INNER_DIRECTIVES_STORAGE, + undefined, + ts.createTypeLiteralNode([ + ts.createIndexSignature(undefined, undefined, [ + ts.createParameter(undefined, undefined, undefined, 'id', undefined, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)), + ], ts.createTypeReferenceNode('ClassType', [ + ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword), + ])), + ]), + createDirectivesObject(sourceFile, directive.metadata, importsBuffer), + )); + + members.push(ts.createProperty( + [], + [ + ts.createToken(ts.SyntaxKind.PublicKeyword), + ts.createToken(ts.SyntaxKind.StaticKeyword), + ], + STATIC_DIRECTIVE_METADATA_STORAGE, + undefined, + ts.createTypeReferenceNode('DirectiveDefinition', undefined), + createDirectiveMetadataObject(directive.metadata, compilerOptions, moduleResolutionHost), + )); + + return ts.createClassDeclaration( + [], + directiveClass.modifiers, + directiveClass.name, + directiveClass.typeParameters, + directiveClass.heritageClauses, + members, + ); + } + } + + return ts.visitEachChild(node, visit, context); + } + + sourceFile = ts.visitNode(sourceFile, visit); + importsBuffer.applyImports(sourceFile, compilerOptions, moduleResolutionHost); + + if (isFunction(onDone)) { + onDone(analyzedFile); + } + + return sourceFile; + }; + } +} + + +function createFiltersObject(metadata: DirectiveDefinition): ts.ObjectLiteralExpression +{ + return ts.createObjectLiteral(map(metadata.filters, (filter: DirectiveDefinitionFilterMetadata) => { + return ts.createPropertyAssignment( + ts.createLiteral(filter.metadata.name), + ts.createIdentifier(filter.localName), + ); + }), true); +} + + +function createDirectivesObject(sourceFile: ts.SourceFile, metadata: DirectiveDefinition, importsBuffer: AppendImportsBuffer): ts.ObjectLiteralExpression +{ + return ts.createObjectLiteral(map(metadata.directives, (innerDirective: DirectiveDefinitionInnerDirective) => { + if (sourceFile.fileName !== innerDirective.path) { + const importPath = path.relative(path.dirname(sourceFile.fileName), innerDirective.path); + importsBuffer.add('./' + path.basename(importPath, path.extname(importPath)), undefined, innerDirective.localName); + } + + return ts.createPropertyAssignment( + ts.createLiteral(innerDirective.metadata.id), + ts.createIdentifier(innerDirective.localName), + ); + }), true); +} + + +function createDirectiveMetadataObject(metadata: DirectiveDefinition, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost): ts.ObjectLiteralExpression +{ + const properties = [ + ts.createPropertyAssignment('type', ts.createPropertyAccess( + ts.createIdentifier('DirectiveDefinitionType'), + ts.createIdentifier(DirectiveDefinitionType[metadata.type])), + ), + ts.createPropertyAssignment('id', ts.createLiteral(metadata.id)), + ts.createPropertyAssignment('className', ts.createLiteral(metadata.className)), + ts.createPropertyAssignment('selector', ts.createLiteral(metadata.selector)), + ts.createPropertyAssignment('exportAs', ts.createArrayLiteral(map(metadata.exportAs, (exportAs: string) => { + return ts.createLiteral(exportAs); + }), false)), + ts.createPropertyAssignment('onInit', metadata.onInit ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('onDestroy', metadata.onDestroy ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('onTemplateInit', metadata.onTemplateInit ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('onUpdate', metadata.onUpdate ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('onAttach', metadata.onAttach ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('inputs', ts.createArrayLiteral(map(metadata.inputs, (input: DirectiveDefinitionInput) => { + return ts.createObjectLiteral([ + ts.createPropertyAssignment('property', ts.createLiteral(input.property)), + ts.createPropertyAssignment('name', ts.createLiteral(camelCaseToHyphens(input.name))), + ts.createPropertyAssignment('required', input.required ? ts.createTrue() : ts.createFalse()), + ]); + }), true)), + ts.createPropertyAssignment('outputs', ts.createArrayLiteral(map(metadata.outputs, (output: DirectiveDefinitionOutput) => { + return ts.createObjectLiteral([ + ts.createPropertyAssignment('property', ts.createLiteral(output.property)), + ts.createPropertyAssignment('name', ts.createLiteral(camelCaseToHyphens(output.name))), + ]); + }), true)), + ts.createPropertyAssignment('elements', ts.createArrayLiteral(map(metadata.elements, (element: DirectiveDefinitionElement) => { + return ts.createObjectLiteral([ + ts.createPropertyAssignment('property', ts.createLiteral(element.property)), + ts.createPropertyAssignment('selector', ts.createLiteral(element.selector)), + ts.createPropertyAssignment('required', element.required ? ts.createTrue() : ts.createFalse()), + ]); + }), true)), + ts.createPropertyAssignment('events', ts.createArrayLiteral(map(metadata.events, (event: DirectiveDefinitionEvent) => { + const eventProperties = [ + ts.createPropertyAssignment('method', ts.createLiteral(event.method)), + ts.createPropertyAssignment('event', ts.createLiteral(event.event)), + ]; + + if (exists(event.selector)) { + eventProperties.push(ts.createPropertyAssignment('selector', ts.createLiteral(event.selector))); + } + + return ts.createObjectLiteral(eventProperties); + }), true)), + ts.createPropertyAssignment('directives', ts.createArrayLiteral([])), + ts.createPropertyAssignment('childDirectives', ts.createArrayLiteral(map(metadata.childDirectives, (childDirective: DirectiveDefinitionChildDirective) => { + return ts.createObjectLiteral([ + ts.createPropertyAssignment('property', ts.createLiteral(childDirective.property)), + ts.createPropertyAssignment('required', childDirective.required ? ts.createTrue() : ts.createFalse()), + ts.createPropertyAssignment('directive', ts.createObjectLiteral([ + ts.createPropertyAssignment('metadata', ts.createPropertyAccess( + ts.createIdentifier(childDirective.directive.localName), + ts.createIdentifier(STATIC_DIRECTIVE_METADATA_STORAGE), + )), + ts.createPropertyAssignment('directiveType', ts.createIdentifier(childDirective.directive.localName)), + ])), + ]); + }), true)), + ts.createPropertyAssignment('childrenDirectives', ts.createArrayLiteral(map(metadata.childrenDirectives, (childrenDirective: DirectiveDefinitionChildrenDirective) => { + return ts.createObjectLiteral([ + ts.createPropertyAssignment('property', ts.createLiteral(childrenDirective.property)), + ts.createPropertyAssignment('directive', ts.createObjectLiteral([ + ts.createPropertyAssignment('metadata', ts.createPropertyAccess( + ts.createIdentifier(childrenDirective.directive.localName), + ts.createIdentifier(STATIC_DIRECTIVE_METADATA_STORAGE), + )), + ts.createPropertyAssignment('directiveType', ts.createIdentifier(childrenDirective.directive.localName)), + ])), + ]); + }), true)), + ]; + + if (metadata.override) { + properties.push(ts.createPropertyAssignment('override', ts.createObjectLiteral([ + ts.createPropertyAssignment('metadata', ts.createPropertyAccess( + ts.createIdentifier(metadata.override.localName), + ts.createIdentifier(STATIC_DIRECTIVE_METADATA_STORAGE), + )), + ts.createPropertyAssignment('directiveType', ts.createIdentifier(metadata.override.localName)), + ], false))); + } + + if (metadata.type === DirectiveDefinitionType.Component) { + properties.push(ts.createPropertyAssignment('encapsulation', ts.createPropertyAccess( + ts.createIdentifier('TemplateEncapsulation'), + ts.createIdentifier(TemplateEncapsulation[metadata.encapsulation])), + )); + + properties.push(ts.createPropertyAssignment('filters', ts.createArrayLiteral())); + + properties.push(ts.createPropertyAssignment('styles', ts.createArrayLiteral(map(metadata.styles, (style: string) => { + return ts.createLiteral(style); + }), true))); + + properties.push(ts.createPropertyAssignment('template', compileTemplate(metadata, compilerOptions, moduleResolutionHost))); + } + + forEach(metadata, (obj: any, key: string) => { + if (KNOWN_METADATA_OPTIONS.indexOf(key) >= 0) { + return; + } + + properties.push(ts.createPropertyAssignment(key, obj)); + }); + + return ts.createObjectLiteral(properties, true); +} + + +function compileTemplate(metadata: DirectiveDefinition, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost): ts.FunctionExpression +{ + const compiler = new Compiler((directive, checkAgainst) => { + return isClassInstanceOf(directive.node, checkAgainst.node, compilerOptions, moduleResolutionHost); + }); + + const template = compiler.compile(metadata).substr(7); + const templateSourceFile = ts.createSourceFile('/template.ts', template, ts.ScriptTarget.Latest); + + const declaration = templateSourceFile.statements[0]; + + return ts.createFunctionExpression( + undefined, + undefined, + undefined, + undefined, + [ + ts.createParameter([], [], undefined, 'template'), + ts.createParameter([], [], undefined, 'el'), + ts.createParameter([], [], undefined, 'component'), + ts.createParameter([], [], undefined, 'directivesProvider'), + ], + undefined, + declaration.body, + ); +} diff --git a/packages/compiler-cli/transformers/filterTransformer.ts b/packages/compiler-cli/transformers/filterTransformer.ts new file mode 100644 index 0000000..3a7a30b --- /dev/null +++ b/packages/compiler-cli/transformers/filterTransformer.ts @@ -0,0 +1,70 @@ +import {find, clone} from '@slicky/utils'; +import {AppendImportsBuffer} from '@slicky/typescript-api-utils'; +import {STATIC_FILTER_METADATA_STORAGE, FilterMetadata} from '@slicky/core/metadata'; +import {FileAnalyzer, FileDefinitionFilter} from '../analyzers'; +import * as ts from 'typescript'; + + +export function createFilterTransformer(fileAnalyzer: FileAnalyzer, compilerOptions: ts.CompilerOptions, moduleResolutionHost: ts.ModuleResolutionHost): ts.TransformerFactory +{ + return function filterTransformer(context: ts.TransformationContext): ts.Transformer + { + return (sourceFile: ts.SourceFile) => { + const analyzedFile = fileAnalyzer.analyzeFile(sourceFile); + const importsBuffer = new AppendImportsBuffer; + + function visit(node: ts.Node): ts.Node + { + if (ts.isClassDeclaration(node) && (node).name) { + const filterClass = node; + const filter: FileDefinitionFilter = find(analyzedFile.filters, (filter: FileDefinitionFilter) => { + return filter.metadata.className === (filterClass.name).text; + }); + + if (filter) { + importsBuffer.add('@slicky/core/metadata', undefined, 'FilterMetadata'); + + const members = clone(filterClass.members); + + members.push(ts.createProperty( + [], + [ + ts.createToken(ts.SyntaxKind.PublicKeyword), + ts.createToken(ts.SyntaxKind.StaticKeyword), + ], + STATIC_FILTER_METADATA_STORAGE, + undefined, + ts.createTypeReferenceNode('FilterMetadata', undefined), + createMetadataPropertyObject(filter.metadata), + )); + + return ts.createClassDeclaration( + [], + filterClass.modifiers, + filterClass.name, + filterClass.typeParameters, + filterClass.heritageClauses, + members, + ); + } + } + + return ts.visitEachChild(node, visit, context); + } + + sourceFile = ts.visitNode(sourceFile, visit); + importsBuffer.applyImports(sourceFile, compilerOptions, moduleResolutionHost); + + return sourceFile; + }; + } +} + + +function createMetadataPropertyObject(metadata: FilterMetadata): ts.ObjectLiteralExpression +{ + return ts.createObjectLiteral([ + ts.createPropertyAssignment('className', ts.createLiteral(metadata.className)), + ts.createPropertyAssignment('name', ts.createLiteral(metadata.name)), + ], true); +} diff --git a/packages/compiler-cli/transformers/index.ts b/packages/compiler-cli/transformers/index.ts new file mode 100644 index 0000000..594ceab --- /dev/null +++ b/packages/compiler-cli/transformers/index.ts @@ -0,0 +1,2 @@ +export * from './directiveTransformer'; +export * from './filterTransformer'; diff --git a/packages/compiler/compiler/plugins/exportAsPlugin.ts b/packages/compiler/compiler/plugins/exportAsPlugin.ts index 99eb573..05dbf9e 100644 --- a/packages/compiler/compiler/plugins/exportAsPlugin.ts +++ b/packages/compiler/compiler/plugins/exportAsPlugin.ts @@ -12,7 +12,7 @@ export class ExportAsPlugin extends AbstractSlickyEnginePlugin public onBeforeProcessDirective(element: _.ASTHTMLNodeElement, directive: ElementProcessingDirective, arg: OnProcessElementArgument): void { - if (exists(directive.directive.metadata.exportAs)) { + if (directive.directive.metadata.exportAs.length) { const exportInto = find(element.exports, (elementExport: _.ASTHTMLNodeTextAttribute) => { if (elementExport.value === '' || directive.directive.metadata.exportAs.indexOf(elementExport.value) >= 0) { return true; diff --git a/packages/core/metadata/directive.ts b/packages/core/metadata/directive.ts index d6924f6..f1dd3f1 100644 --- a/packages/core/metadata/directive.ts +++ b/packages/core/metadata/directive.ts @@ -23,7 +23,7 @@ export class DirectiveAnnotationDefinition public selector: string; - public exportAs: Array; + public exportAs: Array = []; public override: ClassType; diff --git a/packages/core/metadata/directiveMetadataLoader.ts b/packages/core/metadata/directiveMetadataLoader.ts index 0ff952e..e29ead9 100644 --- a/packages/core/metadata/directiveMetadataLoader.ts +++ b/packages/core/metadata/directiveMetadataLoader.ts @@ -1,7 +1,7 @@ import {ClassType} from '@slicky/lang'; import {stringify, isFunction, forEach, exists, camelCaseToHyphens, map, unique, merge, find, clone} from '@slicky/utils'; import {findAnnotation, getPropertiesMetadata} from '@slicky/reflection'; -import {RenderableTemplateFactory, TemplateEncapsulation} from '@slicky/templates/templates'; +import {TemplateEncapsulation} from '@slicky/templates/templates'; import {DirectiveAnnotationDefinition} from './directive'; import {ComponentAnnotationDefinition} from './component'; import {InputDefinition} from './input'; @@ -13,13 +13,14 @@ import {ChildDirectiveDefinition} from './childDirective'; import {ChildrenDirectiveDefinition} from './childrenDirective'; import {FilterInterface} from '../filters'; import {ExtensionsManager} from '../extensions'; +import {ComponentTemplateRenderFactory} from '../templates'; import {FilterMetadata, FilterMetadataLoader} from './filterMetadataLoader'; import {ModuleMetadataLoader, ModuleMetadata} from './moduleMetadataLoader'; -const STATIC_DIRECTIVE_METADATA_STORAGE = '__slicky__directive__metadata__'; -const STATIC_INNER_DIRECTIVES_STORAGE = '__slicky__inner_directives__'; -const STATIC_FILTERS_STORAGE = '__slicky__filters__'; +export const STATIC_DIRECTIVE_METADATA_STORAGE = '__SLICKY__DIRECTIVE__METADATA__'; +export const STATIC_INNER_DIRECTIVES_STORAGE = '__SLICKY__INNER__DIRECTIVES__'; +export const STATIC_FILTERS_STORAGE = '__SLICKY__FILTERS__'; export enum DirectiveDefinitionType @@ -64,6 +65,11 @@ export declare interface DirectiveDefinitionInnerDirective { metadata: DirectiveDefinition, directiveType?: ClassType, + localName?: string, + originalName?: string, + imported?: boolean, + path?: string, + node?: any, // ts.ClassDeclaration } @@ -86,6 +92,10 @@ export declare interface DirectiveDefinitionFilterMetadata { metadata: FilterMetadata, filterType?: ClassType, + localName?: string, + originalName?: string, + imported?: boolean, + path?: string, } @@ -95,7 +105,7 @@ export declare interface DirectiveDefinition id: string, className: string, selector: string, - exportAs?: Array, + exportAs: Array, onInit: boolean, onDestroy: boolean, onTemplateInit: boolean, @@ -109,7 +119,7 @@ export declare interface DirectiveDefinition override?: DirectiveDefinitionInnerDirective, childDirectives: Array, childrenDirectives: Array, - template?: string|RenderableTemplateFactory, + template?: string|ComponentTemplateRenderFactory, filters?: Array, styles?: Array, encapsulation?: TemplateEncapsulation, @@ -117,6 +127,21 @@ export declare interface DirectiveDefinition } +export declare interface PartialDirectiveDefinition +{ + id: string, + className: string, + selector: string, + [name: string]: any, +} + + +export declare interface PartialComponentDefinition extends PartialDirectiveDefinition +{ + template: string, +} + + export class DirectiveMetadataLoader { @@ -193,31 +218,22 @@ export class DirectiveMetadataLoader const name = stringify(directiveType); - const metadata: DirectiveDefinition = { + const metadata = createDirectiveMetadata({ type: type, id: exists(annotation.id) ? annotation.id : name, className: name, selector: annotation.selector, + exportAs: annotation.exportAs, onInit: isFunction(directiveType.prototype.onInit), onDestroy: isFunction(directiveType.prototype.onDestroy), onTemplateInit: isFunction(directiveType.prototype.onTemplateInit), onUpdate: isFunction(directiveType.prototype.onUpdate), onAttach: isFunction(directiveType.prototype.onAttach), directives: this.loadDirectivesMetadata(directiveType, annotation, modules), - inputs: [], - outputs: [], - elements: [], - events: [], - childDirectives: [], - childrenDirectives: [], - }; + }); this.loadPropertiesMetadata(metadata, directiveType); - if (annotation.exportAs) { - metadata.exportAs = annotation.exportAs; - } - if (annotation.override) { metadata.override = { directiveType: annotation.override, @@ -401,3 +417,69 @@ export class DirectiveMetadataLoader } } + + +export function createDirectiveMetadata(partialMetadata: PartialDirectiveDefinition): DirectiveDefinition +{ + partialMetadata.type = exists(partialMetadata.type) ? partialMetadata.type : DirectiveDefinitionType.Directive; + partialMetadata.exportAs = exists(partialMetadata.exportAs) ? partialMetadata.exportAs : []; + + return createMetadata(partialMetadata); +} + + +export function createComponentMetadata(partialMetadata: PartialComponentDefinition): DirectiveDefinition +{ + partialMetadata.type = exists(partialMetadata.type) ? partialMetadata.type : DirectiveDefinitionType.Component; + partialMetadata.encapsulation = exists(partialMetadata.encapsulation) ? partialMetadata.encapsulation : TemplateEncapsulation.Emulated; + partialMetadata.filters = exists(partialMetadata.filters) ? partialMetadata.filters : []; + partialMetadata.styles = exists(partialMetadata.styles) ? partialMetadata.styles : []; + + return createDirectiveMetadata(partialMetadata); +} + + +function createMetadata(partialMetadata: any): DirectiveDefinition +{ + const metadata: DirectiveDefinition = { + type: partialMetadata.type, + id: partialMetadata.id, + className: partialMetadata.className, + selector: partialMetadata.selector, + exportAs: partialMetadata.exportAs, + onInit: exists(partialMetadata.onInit) ? partialMetadata.onInit : false, + onDestroy: exists(partialMetadata.onDestroy) ? partialMetadata.onDestroy : false, + onTemplateInit: exists(partialMetadata.onTemplateInit) ? partialMetadata.onTemplateInit : false, + onUpdate: exists(partialMetadata.onUpdate) ? partialMetadata.onUpdate : false, + onAttach: exists(partialMetadata.onAttach) ? partialMetadata.onAttach : false, + inputs: exists(partialMetadata.inputs) ? partialMetadata.inputs : [], + outputs: exists(partialMetadata.outputs) ? partialMetadata.outputs : [], + elements: exists(partialMetadata.elements) ? partialMetadata.elements : [], + events: exists(partialMetadata.events) ? partialMetadata.events : [], + directives: exists(partialMetadata.directives) ? partialMetadata.directives : [], + childDirectives: exists(partialMetadata.childDirectives) ? partialMetadata.childDirectives : [], + childrenDirectives: exists(partialMetadata.childrenDirectives) ? partialMetadata.childrenDirectives : [], + }; + + if (exists(partialMetadata.template)) { + metadata.template = partialMetadata.template; + } + + if (exists(partialMetadata.encapsulation)) { + metadata.encapsulation = partialMetadata.encapsulation; + } + + if (exists(partialMetadata.filters)) { + metadata.filters = partialMetadata.filters; + } + + if (exists(partialMetadata.styles)) { + metadata.styles = partialMetadata.styles; + } + + if (exists(partialMetadata.override)) { + metadata.override = partialMetadata.override; + } + + return metadata; +} diff --git a/packages/core/metadata/filterMetadataLoader.ts b/packages/core/metadata/filterMetadataLoader.ts index 834fc49..59e4123 100644 --- a/packages/core/metadata/filterMetadataLoader.ts +++ b/packages/core/metadata/filterMetadataLoader.ts @@ -5,7 +5,7 @@ import {FilterDefinition} from './filter'; import {FilterInterface} from '../filters'; -const STATIC_FILTER_METADATA_STORAGE = '__slicky__filter__metadata__'; +export const STATIC_FILTER_METADATA_STORAGE = '__SLICKY__FILTER__METADATA__'; export declare interface FilterMetadata diff --git a/packages/core/templates/componentTemplate.ts b/packages/core/templates/componentTemplate.ts index d84df94..fc99b90 100644 --- a/packages/core/templates/componentTemplate.ts +++ b/packages/core/templates/componentTemplate.ts @@ -7,7 +7,7 @@ import {DirectiveFactory, DirectiveTypesProvider} from '../runtime'; import {DirectivesStorageTemplate} from './directivesStorageTemplate'; -export declare type ComponentTemplateRenderFactory = (template: ComponentTemplate, el: TemplateElement, ...args: Array) => void; +export declare type ComponentTemplateRenderFactory = (template: ComponentTemplate, el: TemplateElement, component: any, directivesProvider: DirectiveTypesProvider) => void; export class ComponentTemplate extends Template diff --git a/packages/core/tests/helpers.ts b/packages/core/tests/helpers.ts index 566d7e5..2fda83d 100644 --- a/packages/core/tests/helpers.ts +++ b/packages/core/tests/helpers.ts @@ -1,74 +1,23 @@ import {exists} from '@slicky/utils'; -import {TemplateEncapsulation} from '@slicky/templates/templates'; -import {DirectiveDefinition, DirectiveDefinitionType} from '../metadata'; +import {DirectiveDefinition, createDirectiveMetadata as _createDirectiveMetadata, createComponentMetadata as _createComponentMetadata} from '../metadata'; -export function createDirectiveMetadata(partialMetadata: any): DirectiveDefinition +export function createDirectiveMetadata(partialMetadata: any = {}): DirectiveDefinition { - partialMetadata.type = exists(partialMetadata.type) ? partialMetadata.type : DirectiveDefinitionType.Directive; partialMetadata.id = exists(partialMetadata.id) ? partialMetadata.id : 'TestDirective'; partialMetadata.className = exists(partialMetadata.className) ? partialMetadata.className : 'TestDirective'; partialMetadata.selector = exists(partialMetadata.selector) ? partialMetadata.selector : 'test-directive'; - return createMetadata(partialMetadata); + return _createDirectiveMetadata(partialMetadata); } -export function createComponentMetadata(partialMetadata: any): DirectiveDefinition +export function createComponentMetadata(partialMetadata: any = {}): DirectiveDefinition { - partialMetadata.type = exists(partialMetadata.type) ? partialMetadata.type : DirectiveDefinitionType.Component; partialMetadata.id = exists(partialMetadata.id) ? partialMetadata.id : 'TestComponent'; partialMetadata.className = exists(partialMetadata.className) ? partialMetadata.className : 'TestComponent'; partialMetadata.selector = exists(partialMetadata.selector) ? partialMetadata.selector : 'test-component'; partialMetadata.template = exists(partialMetadata.template) ? partialMetadata.template : ''; - partialMetadata.encapsulation = exists(partialMetadata.encapsulation) ? partialMetadata.encapsulation : TemplateEncapsulation.Emulated; - partialMetadata.filters = exists(partialMetadata.filters) ? partialMetadata.filters : []; - partialMetadata.styles = exists(partialMetadata.styles) ? partialMetadata.styles : []; - return createDirectiveMetadata(partialMetadata); -} - - -function createMetadata(partialMetadata: any): DirectiveDefinition -{ - const metadata: DirectiveDefinition = { - type: partialMetadata.type, - id: partialMetadata.id, - className: partialMetadata.className, - selector: partialMetadata.selector, - onInit: exists(partialMetadata.onInit) ? partialMetadata.onInit : false, - onDestroy: exists(partialMetadata.onDestroy) ? partialMetadata.onDestroy : false, - onTemplateInit: exists(partialMetadata.onTemplateInit) ? partialMetadata.onTemplateInit : false, - onUpdate: exists(partialMetadata.onUpdate) ? partialMetadata.onUpdate : false, - onAttach: exists(partialMetadata.onAttach) ? partialMetadata.onAttach : false, - inputs: exists(partialMetadata.inputs) ? partialMetadata.inputs : [], - outputs: exists(partialMetadata.outputs) ? partialMetadata.outputs : [], - elements: exists(partialMetadata.elements) ? partialMetadata.elements : [], - events: exists(partialMetadata.events) ? partialMetadata.events : [], - directives: exists(partialMetadata.directives) ? partialMetadata.directives : [], - childDirectives: exists(partialMetadata.childDirectives) ? partialMetadata.childDirectives : [], - childrenDirectives: exists(partialMetadata.childrenDirectives) ? partialMetadata.childrenDirectives : [], - }; - - if (exists(partialMetadata.exportAs)) { - metadata.exportAs = partialMetadata.exportAs; - } - - if (exists(partialMetadata.template)) { - metadata.template = partialMetadata.template; - } - - if (exists(partialMetadata.encapsulation)) { - metadata.encapsulation = partialMetadata.encapsulation; - } - - if (exists(partialMetadata.filters)) { - metadata.filters = partialMetadata.filters; - } - - if (exists(partialMetadata.styles)) { - metadata.styles = partialMetadata.styles; - } - - return metadata; + return _createComponentMetadata(partialMetadata); } diff --git a/packages/webpack-loader/index.ts b/packages/webpack-loader/index.ts index 9e68195..b42edfc 100644 --- a/packages/webpack-loader/index.ts +++ b/packages/webpack-loader/index.ts @@ -1,9 +1,24 @@ import {Compiler} from '@slicky/compiler-cli'; +import {FilterAnalyzer, DirectiveAnalyzer, FileAnalyzer} from '@slicky/compiler-cli/analyzers'; +import {fsModuleResolutionHost} from '@slicky/typescript-api-utils'; +import * as ts from 'typescript'; -export default function(source: string, sourcemap): void +const compilerOptions = {} || ts.getDefaultCompilerOptions(); +const moduleResolutionHost = fsModuleResolutionHost(); + +const filterAnalyzer = new FilterAnalyzer; +const directiveAnalyzer = new DirectiveAnalyzer(filterAnalyzer, compilerOptions, moduleResolutionHost); +const fileAnalyzer = new FileAnalyzer(directiveAnalyzer, filterAnalyzer); + +const compiler = new Compiler(fileAnalyzer, compilerOptions, moduleResolutionHost); + + +export default function(source: string): string { - const callback = this.async(); + return compiler.compileFile(this.resourcePath, source).sourceText; + + /*const callback = this.async(); const compiler = new Compiler; compiler.compileFile(this.resourcePath, (err, file) => { @@ -12,5 +27,5 @@ export default function(source: string, sourcemap): void } else { callback(null, file.source, sourcemap); } - }); + });*/ } diff --git a/packages/webpack-loader/package.json b/packages/webpack-loader/package.json index 271cfa6..7fbed29 100644 --- a/packages/webpack-loader/package.json +++ b/packages/webpack-loader/package.json @@ -15,8 +15,10 @@ "types": "./index.d.ts", "dependencies": { "@slicky/compiler-cli": "^0.3.9", + "@slicky/typescript-api-utils": "^0.0.1", "@slicky/utils": "^1.3.1", - "loader-utils": "^1.1.0" + "loader-utils": "^1.1.0", + "typescript": "^2.4.2" }, "devDependencies": { "@types/chai": "^4.0.3", diff --git a/yarn.lock b/yarn.lock index 3b21f50..bd22fbb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,7 +30,7 @@ dependencies: "@slicky/utils" "^1.0.11" -"@types/chai@^4.0.3": +"@types/chai@^4.0.3", "@types/chai@^4.0.5": version "4.0.5" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.5.tgz#b6e250e281b47e0192e236619e9b1afe62fd345c" @@ -84,7 +84,7 @@ version "2.2.44" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" -"@types/node@*", "@types/node@^8.0.20", "@types/node@^8.0.21", "@types/node@^8.0.22": +"@types/node@*", "@types/node@^8.0.20", "@types/node@^8.0.21", "@types/node@^8.0.22", "@types/node@^8.0.53": version "8.0.53" resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.53.tgz#396b35af826fa66aad472c8cb7b8d5e277f4e6d8" @@ -167,8 +167,8 @@ ajv@^4.9.1: json-stable-stringify "^1.0.1" ajv@^5.1.0, ajv@^5.1.5: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" + version "5.4.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.4.0.tgz#32d1cf08dbc80c432f426f12e10b2511f6b46474" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" @@ -3133,8 +3133,8 @@ node-pre-gyp@^0.6.39: tar-pack "^3.4.0" node-sass@^4.2.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.1.tgz#bec978ab33b5cf56825bf72922323a56ebaf4f66" + version "4.7.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.7.2.tgz#9366778ba1469eb01438a9e8592f4262bcb6794e" dependencies: async-foreach "^0.1.3" chalk "^1.1.1"