diff --git a/src/angular/config.ts b/src/angular/config.ts index 006e434c8..c09015046 100644 --- a/src/angular/config.ts +++ b/src/angular/config.ts @@ -31,7 +31,12 @@ export interface Config { export interface DirectiveDeclaration { selector: string; - exportAs: string; + exportAs?: string; + inputs?: string[]; + outputs?: string[]; + hostProperties?: string[]; + hostAttributes?: string[]; + hostListeners?: string[]; } let BUILD_TYPE = '<%= BUILD_TYPE %>'; @@ -66,7 +71,9 @@ export const Config: Config = { { selector: 'md-button-toggle-group:not([multiple])', exportAs: 'mdButtonToggleGroup' }, { selector: '[md-menu-trigger-for], [mat-menu-trigger-for], [mdMenuTriggerFor]', exportAs: 'mdMenuTrigger' }, { selector: '[md-tooltip], [mat-tooltip], [mdTooltip]', exportAs: 'mdTooltip' }, - { selector: 'md-select, mat-select', exportAs: 'mdSelect' } + { selector: 'md-select, mat-select', exportAs: 'mdSelect' }, + { selector: '[ngIf]', exportAs: 'ngIf', inputs: ['ngIf'] }, + { selector: '[ngSwitch]', exportAs: 'ngSwitch', inputs: ['ngSwitch'] } ], logLevel: BUILD_TYPE === 'dev' ? LogLevel.Debug : LogLevel.None diff --git a/src/angular/templates/basicTemplateAstVisitor.ts b/src/angular/templates/basicTemplateAstVisitor.ts index 6ae5bfc69..d5e475d7f 100644 --- a/src/angular/templates/basicTemplateAstVisitor.ts +++ b/src/angular/templates/basicTemplateAstVisitor.ts @@ -152,7 +152,16 @@ export class BasicTemplateAstVisitor extends SourceMappingVisitor implements ast visitText(text: ast.TextAst, context: any): any {} - visitDirective(ast: ast.DirectiveAst, context: any): any {} + visitDirective(ast: ast.DirectiveAst, context: any): any { + ast.inputs.forEach(o => this.visit(o, context)); + ast.hostProperties.forEach(p => this.visit(p, context)); + ast.hostEvents.forEach(e => this.visit(e, context)); + } - visitDirectiveProperty(ast: ast.BoundDirectivePropertyAst, context: any): any {} + visitDirectiveProperty(prop: ast.BoundDirectivePropertyAst, context: any): any { + if (ExpTypes.ASTWithSource(prop.value)) { + const ast: any = (prop.value).ast; + this.visitNg2TemplateAST(prop.value, this.templateStart + getExpressionDisplacement(prop)); + } + } } diff --git a/src/angular/templates/templateParser.ts b/src/angular/templates/templateParser.ts index 1141af45c..2b6ec248a 100644 --- a/src/angular/templates/templateParser.ts +++ b/src/angular/templates/templateParser.ts @@ -1,20 +1,20 @@ import { __core_private__ as r, NO_ERRORS_SCHEMA } from '@angular/core'; import * as compiler from '@angular/compiler'; -import { Config } from '../config'; +import { Config, DirectiveDeclaration } from '../config'; let refId = 0; -const dummyMetadataFactory = (selector: string, exportAs: string) => { +const dummyMetadataFactory = (declaration: DirectiveDeclaration) => { if (refId > 1e10) { refId = 0; } return { - inputs: {}, - outputs: {}, - hostListeners: {}, - hostProperties: {}, - hostAttributes: {}, + inputs: declaration.inputs || [], + outputs: declaration.outputs || [], + hostListeners: declaration.hostListeners || {}, + hostProperties: declaration.hostProperties || {}, + hostAttributes: declaration.hostAttributes || {}, isSummary: true, type: { diDeps: [], @@ -23,8 +23,8 @@ const dummyMetadataFactory = (selector: string, exportAs: string) => { reference: ++refId + '-ref' }, isComponent: false, - selector, - exportAs, + selector: declaration.selector, + exportAs: declaration.exportAs, providers: [], viewProviders: [], queries: [], @@ -41,8 +41,8 @@ const dummyMetadataFactory = (selector: string, exportAs: string) => { let defaultDirectives = []; -export const parseTemplate = (template: string, directives: { selector: string, exportAs: string }[] = []) => { - defaultDirectives = directives.map(d => dummyMetadataFactory(d.selector, d.exportAs)); +export const parseTemplate = (template: string, directives: DirectiveDeclaration[] = []) => { + defaultDirectives = directives.map(d => dummyMetadataFactory(d)); const TemplateParser = compiler.TemplateParser; const expressionParser = new compiler.Parser(new compiler.Lexer()); diff --git a/test/noAccessMissingMemberRule.spec.ts b/test/noAccessMissingMemberRule.spec.ts index 9c4bde3d1..53b958fc8 100644 --- a/test/noAccessMissingMemberRule.spec.ts +++ b/test/noAccessMissingMemberRule.spec.ts @@ -723,6 +723,50 @@ describe('no-access-missing-member', () => { }`; assertSuccess('no-access-missing-member', source); }); + + it('should succeed with array element access', () => { + let source = ` + @Component({ + template: '
' + }) + class Test { + }`; + assertFailure('no-access-missing-member', source, { + message: 'The property "context" that you\'re trying to access does not exist in the class declaration.', + startPosition: { + line: 2, + character: 21 + }, + endPosition: { + line: 2, + character: 28 + } + }); + }); + + + it('should succeed with array element access', () => { + let source = ` + @Component({ + template: \`
+ +
\` + }) + class Test { + }`; + assertFailure('no-access-missing-member', source, { + message: 'The property "context" that you\'re trying to access does not exist in the class declaration.', + startPosition: { + line: 2, + character: 21 + }, + endPosition: { + line: 2, + character: 28 + } + }); + }); + // TODO // it('should work with getters', () => { // let source = `