ci: add lint error for files with missing trailing new-line (#42478)
For quite a while it is an unspoken convention to add a trailing new-line files within the Angular repository. This was never enforced automatically, but has been frequently raised in pull requests through manual review. This commit sets up a lint rule so that this is "officially" enforced and doesn't require manual review. PR Close #42478
This commit is contained in:
parent
71e14a71f5
commit
2d0ff0a5d3
|
@ -96,4 +96,4 @@ export class HttpContext {
|
||||||
keys(): IterableIterator<HttpContextToken<unknown>> {
|
keys(): IterableIterator<HttpContextToken<unknown>> {
|
||||||
return this.map.keys();
|
return this.map.keys();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './src/compiler';
|
export * from './src/compiler';
|
||||||
export {NgCompilerHost} from './src/host';
|
export {NgCompilerHost} from './src/host';
|
||||||
|
|
|
@ -38,4 +38,4 @@ runInEachFileSystem(() => {
|
||||||
expect(secondCompilation.safeToSkipEmit(fooSf)).toBeFalse();
|
expect(secondCompilation.safeToSkipEmit(fooSf)).toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,4 +10,4 @@ export {ExportScope, ScopeData} from './src/api';
|
||||||
export {ComponentScopeReader, CompoundComponentScopeReader} from './src/component_scope';
|
export {ComponentScopeReader, CompoundComponentScopeReader} from './src/component_scope';
|
||||||
export {DtsModuleScopeResolver, MetadataDtsModuleScopeResolver} from './src/dependency';
|
export {DtsModuleScopeResolver, MetadataDtsModuleScopeResolver} from './src/dependency';
|
||||||
export {DeclarationData, LocalModuleScope, LocalModuleScopeRegistry, LocalNgModuleData} from './src/local';
|
export {DeclarationData, LocalModuleScope, LocalModuleScopeRegistry, LocalNgModuleData} from './src/local';
|
||||||
export {TypeCheckScope, TypeCheckScopeRegistry} from './src/typecheck';
|
export {TypeCheckScope, TypeCheckScopeRegistry} from './src/typecheck';
|
||||||
|
|
|
@ -62,4 +62,4 @@ export interface RemoteScope {
|
||||||
* Those pipes used by the component that requires this scope to be set remotely.
|
* Those pipes used by the component that requires this scope to be set remotely.
|
||||||
*/
|
*/
|
||||||
pipes: Reference[];
|
pipes: Reference[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1127,4 +1127,4 @@ function isIvyNgModule(clazz: ts.ClassDeclaration): boolean {
|
||||||
|
|
||||||
// No Ivy 'ɵmod' property found.
|
// No Ivy 'ɵmod' property found.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,4 +59,4 @@ function hasProperty(node: ts.ObjectLiteralExpression, propertyName: string): bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,4 @@ import * as ts from 'typescript';
|
||||||
export interface UpdateRecorder {
|
export interface UpdateRecorder {
|
||||||
updateNode(node: ts.Node, newText: string): void;
|
updateNode(node: ts.Node, newText: string): void;
|
||||||
commitUpdate(): void;
|
commitUpdate(): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,4 +129,4 @@ function getNamedImports(importDeclaration: ts.ImportDeclaration|undefined): ts.
|
||||||
}
|
}
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,4 @@ export const enum InjectorMarkers {
|
||||||
* Marks that the current type is `Injector`
|
* Marks that the current type is `Injector`
|
||||||
*/
|
*/
|
||||||
Injector = -1
|
Injector = -1
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,4 +95,4 @@ export class ElementRef<T = any> {
|
||||||
*/
|
*/
|
||||||
export function unwrapElementRef<T, R>(value: T|ElementRef<R>): T|R {
|
export function unwrapElementRef<T, R>(value: T|ElementRef<R>): T|R {
|
||||||
return value instanceof ElementRef ? value.nativeElement : value;
|
return value instanceof ElementRef ? value.nativeElement : value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,4 +202,4 @@ interface QueryListInternal<T> extends QueryList<T> {
|
||||||
length: number;
|
length: number;
|
||||||
last: T;
|
last: T;
|
||||||
first: T;
|
first: T;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,4 +31,4 @@ export function assertPureTNodeType(type: TNodeType) {
|
||||||
throwError(`Expected TNodeType to have only a single type selected, but got ${
|
throwError(`Expected TNodeType to have only a single type selected, but got ${
|
||||||
toTNodeTypeAsString(type)}.`);
|
toTNodeTypeAsString(type)}.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,4 +129,4 @@ export function assertOneOf(value: any, ...validValues: any[]) {
|
||||||
if (validValues.indexOf(value) !== -1) return true;
|
if (validValues.indexOf(value) !== -1) return true;
|
||||||
throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${
|
throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${
|
||||||
JSON.stringify(value)}.`);
|
JSON.stringify(value)}.`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,4 +48,4 @@ const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
|
||||||
export function escapeCommentText(value: string): string {
|
export function escapeCommentText(value: string): string {
|
||||||
return value.replace(
|
return value.replace(
|
||||||
COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
|
COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,4 +40,4 @@ describe('comment node text escaping', () => {
|
||||||
expect(script).toBeFalsy();
|
expect(script).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,4 +16,4 @@ describe('InjectFlags', () => {
|
||||||
expect(InjectFlags.SkipSelf).toEqual(InternalInjectFlags.SkipSelf as number);
|
expect(InjectFlags.SkipSelf).toEqual(InternalInjectFlags.SkipSelf as number);
|
||||||
expect(InjectFlags.Optional).toEqual(InternalInjectFlags.Optional as number);
|
expect(InjectFlags.Optional).toEqual(InternalInjectFlags.Optional as number);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,4 +25,4 @@ describe('node interfaces', () => {
|
||||||
.toEqual('Element|Container|ElementContainer|Projection|IcuContainer');
|
.toEqual('Element|Container|ElementContainer|Projection|IcuContainer');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -199,4 +199,4 @@ export function isDOMElement(obj: any): obj is Element {
|
||||||
*/
|
*/
|
||||||
export function isDOMText(obj: any): obj is Text {
|
export function isDOMText(obj: any): obj is Text {
|
||||||
return obj instanceof Text;
|
return obj instanceof Text;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,4 @@ describe('isShapeOf', () => {
|
||||||
expect(isShapeOf({required: true, extra: 'is ok'}, {required: true, missing: true}))
|
expect(isShapeOf({required: true, extra: 'is ok'}, {required: true, missing: true}))
|
||||||
.toBeFalse();
|
.toBeFalse();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -116,4 +116,4 @@ function expectNgModuleDef(
|
||||||
|
|
||||||
function unwrap(values: Type<any>[]|(() => Type<any>[])): Type<any>[] {
|
function unwrap(values: Type<any>[]|(() => Type<any>[])): Type<any>[] {
|
||||||
return typeof values === 'function' ? values() : values;
|
return typeof values === 'function' ? values() : values;
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,4 +252,4 @@ export function matchI18nMutableOpCodes(expectedMutableOpCodes: string[]):
|
||||||
};
|
};
|
||||||
|
|
||||||
return matcher;
|
return matcher;
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,4 +93,4 @@ describe('render3 matchers', () => {
|
||||||
expect(matcher.jasmineToString!()).toEqual(`[#TEXT: "myText" != #TEXT: "other text"]`);
|
expect(matcher.jasmineToString!()).toEqual(`[#TEXT: "myText" != #TEXT: "other text"]`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,4 +81,4 @@ export class ViewFixture {
|
||||||
this.leaveView();
|
this.leaveView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,4 +210,4 @@ export class BuiltInControlValueAccessor extends BaseControlValueAccessor {
|
||||||
* @publicApi
|
* @publicApi
|
||||||
*/
|
*/
|
||||||
export const NG_VALUE_ACCESSOR =
|
export const NG_VALUE_ACCESSOR =
|
||||||
new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');
|
new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');
|
||||||
|
|
|
@ -575,4 +575,4 @@ function getUniqueLocations<T extends ts.DocumentSpan>(locations: readonly T[]):
|
||||||
uniqueLocations.set(createLocationKey(location), location);
|
uniqueLocations.set(createLocationKey(location), location);
|
||||||
}
|
}
|
||||||
return Array.from(uniqueLocations.values());
|
return Array.from(uniqueLocations.values());
|
||||||
}
|
}
|
||||||
|
|
|
@ -413,4 +413,4 @@ function getRenameRequestPosition(renameRequest: RenameRequest): FilePosition {
|
||||||
renameRequest.requestNode.getStart() :
|
renameRequest.requestNode.getStart() :
|
||||||
renameRequest.renamePosition.position;
|
renameRequest.renamePosition.position;
|
||||||
return {fileName, position};
|
return {fileName, position};
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,4 +294,4 @@ export function getParentClassMeta(requestNode: ts.Node, compiler: NgCompiler):
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return compiler.getMeta(parentClass);
|
return compiler.getMeta(parentClass);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,4 +101,4 @@ function last<T>(array: T[]): T {
|
||||||
throw new Error(`last() called on empty array`);
|
throw new Error(`last() called on empty array`);
|
||||||
}
|
}
|
||||||
return array[array.length - 1];
|
return array[array.length - 1];
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,4 +374,4 @@ export function getTemplateLocationFromShimLocation(
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return {templateUrl, span};
|
return {templateUrl, span};
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,4 +103,4 @@ const _ESCAPED_CHARS: [RegExp, string][] = [
|
||||||
function escapeXml(text: string): string {
|
function escapeXml(text: string): string {
|
||||||
return _ESCAPED_CHARS.reduce(
|
return _ESCAPED_CHARS.reduce(
|
||||||
(text: string, entry: [RegExp, string]) => text.replace(entry[0], entry[1]), text);
|
(text: string, entry: [RegExp, string]) => text.replace(entry[0], entry[1]), text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,4 +73,4 @@ describe('extractIcuPlaceholders()', () => {
|
||||||
'}\n }}\n}',
|
'}\n }}\n}',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -181,4 +181,4 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit
|
||||||
this.linkWithHref && isActiveCheckFn(this.linkWithHref) ||
|
this.linkWithHref && isActiveCheckFn(this.linkWithHref) ||
|
||||||
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,4 +136,4 @@ export function sortByMatchingOutlets(routes: Routes, outletName: string): Route
|
||||||
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
|
||||||
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
|
||||||
return sortedConfig;
|
return sortedConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"node_modules/tslint-no-toplevel-property-access/rules"
|
"node_modules/tslint-no-toplevel-property-access/rules"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"eofline": true,
|
||||||
"file-header": [
|
"file-header": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"jsRules": {
|
"jsRules": {
|
||||||
|
"eofline": true,
|
||||||
"file-header": [
|
"file-header": [
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue