fix(compiler): Report references to non-exported symbols.
Includes fixes to places now reported as errors. Part of #8310
This commit is contained in:
parent
6195a45ae2
commit
9925aa89dc
@ -6,14 +6,14 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
|
import {Directive, ElementRef, Host, Input, OnDestroy, OpaqueToken, Optional, Renderer, Type, forwardRef} from '@angular/core';
|
||||||
|
|
||||||
import {MapWrapper} from '../../facade/collection';
|
import {MapWrapper} from '../../facade/collection';
|
||||||
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../../facade/lang';
|
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../../facade/lang';
|
||||||
|
|
||||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
|
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
|
||||||
|
|
||||||
const SELECT_MULTIPLE_VALUE_ACCESSOR = {
|
export const SELECT_MULTIPLE_VALUE_ACCESSOR = {
|
||||||
provide: NG_VALUE_ACCESSOR,
|
provide: NG_VALUE_ACCESSOR,
|
||||||
useExisting: forwardRef(() => SelectMultipleControlValueAccessor),
|
useExisting: forwardRef(() => SelectMultipleControlValueAccessor),
|
||||||
multi: true
|
multi: true
|
||||||
|
@ -35,7 +35,7 @@ import {NG_VALIDATORS, Validators} from '../validators';
|
|||||||
*/
|
*/
|
||||||
export interface Validator { validate(c: AbstractControl): {[key: string]: any}; }
|
export interface Validator { validate(c: AbstractControl): {[key: string]: any}; }
|
||||||
|
|
||||||
const REQUIRED = Validators.required;
|
export const REQUIRED = Validators.required;
|
||||||
|
|
||||||
export const REQUIRED_VALIDATOR: any = {
|
export const REQUIRED_VALIDATOR: any = {
|
||||||
provide: NG_VALIDATORS,
|
provide: NG_VALIDATORS,
|
||||||
|
@ -594,6 +594,10 @@ function expandedMessage(error: any): string {
|
|||||||
error.context && error.context.name ? `Calling function '${error.context.name}', f` : 'F';
|
error.context && error.context.name ? `Calling function '${error.context.name}', f` : 'F';
|
||||||
return prefix +
|
return prefix +
|
||||||
'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function';
|
'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function';
|
||||||
|
case 'Reference to a local symbol':
|
||||||
|
if (error.context && error.context.name) {
|
||||||
|
return `Reference to a local (non-exported) symbol '${error.context.name}'. Consider exporting the symbol`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return error.message;
|
return error.message;
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Directive, ElementRef, Host, Input, OnDestroy, Optional, Renderer, forwardRef} from '@angular/core';
|
import {Directive, ElementRef, Host, Input, OnDestroy, OpaqueToken, Optional, Renderer, Type, forwardRef} from '@angular/core';
|
||||||
|
|
||||||
import {MapWrapper} from '../facade/collection';
|
import {MapWrapper} from '../facade/collection';
|
||||||
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../facade/lang';
|
import {StringWrapper, isBlank, isPresent, isPrimitive, isString, looseIdentical} from '../facade/lang';
|
||||||
|
|
||||||
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
|
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from './control_value_accessor';
|
||||||
|
|
||||||
const SELECT_MULTIPLE_VALUE_ACCESSOR = {
|
export const SELECT_MULTIPLE_VALUE_ACCESSOR = {
|
||||||
provide: NG_VALUE_ACCESSOR,
|
provide: NG_VALUE_ACCESSOR,
|
||||||
useExisting: forwardRef(() => SelectMultipleControlValueAccessor),
|
useExisting: forwardRef(() => SelectMultipleControlValueAccessor),
|
||||||
multi: true
|
multi: true
|
||||||
|
@ -297,13 +297,19 @@ export class MetadataCollector {
|
|||||||
} else {
|
} else {
|
||||||
varValue = errorSym('Variable not initialized', nameNode);
|
varValue = errorSym('Variable not initialized', nameNode);
|
||||||
}
|
}
|
||||||
|
let exported = false;
|
||||||
if (variableStatement.flags & ts.NodeFlags.Export ||
|
if (variableStatement.flags & ts.NodeFlags.Export ||
|
||||||
variableDeclaration.flags & ts.NodeFlags.Export) {
|
variableDeclaration.flags & ts.NodeFlags.Export) {
|
||||||
if (!metadata) metadata = {};
|
if (!metadata) metadata = {};
|
||||||
metadata[nameNode.text] = varValue;
|
metadata[nameNode.text] = varValue;
|
||||||
|
exported = true;
|
||||||
}
|
}
|
||||||
if (isPrimitive(varValue)) {
|
if (isPrimitive(varValue)) {
|
||||||
locals.define(nameNode.text, varValue);
|
locals.define(nameNode.text, varValue);
|
||||||
|
} else if (!exported) {
|
||||||
|
locals.define(
|
||||||
|
nameNode.text,
|
||||||
|
errorSym('Reference to a local symbol', nameNode, {name: nameNode.text}));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Destructuring (or binding) declarations are not supported,
|
// Destructuring (or binding) declarations are not supported,
|
||||||
|
@ -24,6 +24,7 @@ describe('Collector', () => {
|
|||||||
'exported-functions.ts',
|
'exported-functions.ts',
|
||||||
'exported-enum.ts',
|
'exported-enum.ts',
|
||||||
'exported-consts.ts',
|
'exported-consts.ts',
|
||||||
|
'local-symbol-ref.ts',
|
||||||
're-exports.ts',
|
're-exports.ts',
|
||||||
'static-field-reference.ts',
|
'static-field-reference.ts',
|
||||||
'static-method.ts',
|
'static-method.ts',
|
||||||
@ -486,6 +487,28 @@ describe('Collector', () => {
|
|||||||
{from: 'angular2/core'}
|
{from: 'angular2/core'}
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should collect an error symbol if collecting a reference to a non-exported symbol', () => {
|
||||||
|
let source = program.getSourceFile('/local-symbol-ref.ts');
|
||||||
|
let metadata = collector.getMetadata(source);
|
||||||
|
expect(metadata.metadata).toEqual({
|
||||||
|
REQUIRED_VALIDATOR: {
|
||||||
|
__symbolic: 'error',
|
||||||
|
message: 'Reference to a local symbol',
|
||||||
|
line: 3,
|
||||||
|
character: 9,
|
||||||
|
context: {name: 'REQUIRED'}
|
||||||
|
},
|
||||||
|
SomeComponent: {
|
||||||
|
__symbolic: 'class',
|
||||||
|
decorators: [{
|
||||||
|
__symbolic: 'call',
|
||||||
|
expression: {__symbolic: 'reference', module: 'angular2/core', name: 'Component'},
|
||||||
|
arguments: [{providers: [{__symbolic: 'reference', name: 'REQUIRED_VALIDATOR'}]}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: Do not use \` in a template literal as it confuses clang-format
|
// TODO: Do not use \` in a template literal as it confuses clang-format
|
||||||
@ -799,6 +822,22 @@ const FILES: Directory = {
|
|||||||
export {Foo as OtherModule} from './static-field-reference.ts';
|
export {Foo as OtherModule} from './static-field-reference.ts';
|
||||||
export * from 'angular2/core';
|
export * from 'angular2/core';
|
||||||
`,
|
`,
|
||||||
|
'local-symbol-ref.ts': `
|
||||||
|
import {Component, Validators} from 'angular2/core';
|
||||||
|
|
||||||
|
const REQUIRED = Validators.required;
|
||||||
|
|
||||||
|
export const REQUIRED_VALIDATOR: any = {
|
||||||
|
provide: 'SomeToken',
|
||||||
|
useValue: REQUIRED,
|
||||||
|
multi: true
|
||||||
|
};
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
providers: [REQUIRED_VALIDATOR]
|
||||||
|
})
|
||||||
|
export class SomeComponent {}
|
||||||
|
`,
|
||||||
'node_modules': {
|
'node_modules': {
|
||||||
'angular2': {
|
'angular2': {
|
||||||
'core.d.ts': `
|
'core.d.ts': `
|
||||||
@ -849,6 +888,9 @@ const FILES: Directory = {
|
|||||||
export interface OnInit {
|
export interface OnInit {
|
||||||
ngOnInit(): any;
|
ngOnInit(): any;
|
||||||
}
|
}
|
||||||
|
export class Validators {
|
||||||
|
static required(): void;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
'common.d.ts': `
|
'common.d.ts': `
|
||||||
export declare class NgFor {
|
export declare class NgFor {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user