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:
Paul Gschwendtner 2021-06-04 16:57:07 +02:00 committed by Jessica Janiuk
parent 71e14a71f5
commit 2d0ff0a5d3
35 changed files with 36 additions and 34 deletions

View File

@ -96,4 +96,4 @@ export class HttpContext {
keys(): IterableIterator<HttpContextToken<unknown>> {
return this.map.keys();
}
}
}

View File

@ -7,4 +7,4 @@
*/
export * from './src/compiler';
export {NgCompilerHost} from './src/host';
export {NgCompilerHost} from './src/host';

View File

@ -38,4 +38,4 @@ runInEachFileSystem(() => {
expect(secondCompilation.safeToSkipEmit(fooSf)).toBeFalse();
});
});
});
});

View File

@ -10,4 +10,4 @@ export {ExportScope, ScopeData} from './src/api';
export {ComponentScopeReader, CompoundComponentScopeReader} from './src/component_scope';
export {DtsModuleScopeResolver, MetadataDtsModuleScopeResolver} from './src/dependency';
export {DeclarationData, LocalModuleScope, LocalModuleScopeRegistry, LocalNgModuleData} from './src/local';
export {TypeCheckScope, TypeCheckScopeRegistry} from './src/typecheck';
export {TypeCheckScope, TypeCheckScopeRegistry} from './src/typecheck';

View File

@ -62,4 +62,4 @@ export interface RemoteScope {
* Those pipes used by the component that requires this scope to be set remotely.
*/
pipes: Reference[];
}
}

View File

@ -1127,4 +1127,4 @@ function isIvyNgModule(clazz: ts.ClassDeclaration): boolean {
// No Ivy 'ɵmod' property found.
return false;
}
}

View File

@ -59,4 +59,4 @@ function hasProperty(node: ts.ObjectLiteralExpression, propertyName: string): bo
}
}
return false;
}
}

View File

@ -16,4 +16,4 @@ import * as ts from 'typescript';
export interface UpdateRecorder {
updateNode(node: ts.Node, newText: string): void;
commitUpdate(): void;
}
}

View File

@ -129,4 +129,4 @@ function getNamedImports(importDeclaration: ts.ImportDeclaration|undefined): ts.
}
return undefined;
}
}

View File

@ -21,4 +21,4 @@ export const enum InjectorMarkers {
* Marks that the current type is `Injector`
*/
Injector = -1
}
}

View File

@ -95,4 +95,4 @@ export class ElementRef<T = any> {
*/
export function unwrapElementRef<T, R>(value: T|ElementRef<R>): T|R {
return value instanceof ElementRef ? value.nativeElement : value;
}
}

View File

@ -202,4 +202,4 @@ interface QueryListInternal<T> extends QueryList<T> {
length: number;
last: T;
first: T;
}
}

View File

@ -31,4 +31,4 @@ export function assertPureTNodeType(type: TNodeType) {
throwError(`Expected TNodeType to have only a single type selected, but got ${
toTNodeTypeAsString(type)}.`);
}
}
}

View File

@ -129,4 +129,4 @@ export function assertOneOf(value: any, ...validValues: any[]) {
if (validValues.indexOf(value) !== -1) return true;
throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${
JSON.stringify(value)}.`);
}
}

View File

@ -48,4 +48,4 @@ const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
export function escapeCommentText(value: string): string {
return value.replace(
COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
}
}

View File

@ -40,4 +40,4 @@ describe('comment node text escaping', () => {
expect(script).toBeFalsy();
});
});
});
});

View File

@ -16,4 +16,4 @@ describe('InjectFlags', () => {
expect(InjectFlags.SkipSelf).toEqual(InternalInjectFlags.SkipSelf as number);
expect(InjectFlags.Optional).toEqual(InternalInjectFlags.Optional as number);
});
});
});

View File

@ -25,4 +25,4 @@ describe('node interfaces', () => {
.toEqual('Element|Container|ElementContainer|Projection|IcuContainer');
});
});
});
});

View File

@ -199,4 +199,4 @@ export function isDOMElement(obj: any): obj is Element {
*/
export function isDOMText(obj: any): obj is Text {
return obj instanceof Text;
}
}

View File

@ -34,4 +34,4 @@ describe('isShapeOf', () => {
expect(isShapeOf({required: true, extra: 'is ok'}, {required: true, missing: true}))
.toBeFalse();
});
});
});

View File

@ -116,4 +116,4 @@ function expectNgModuleDef(
function unwrap(values: Type<any>[]|(() => Type<any>[])): Type<any>[] {
return typeof values === 'function' ? values() : values;
}
}

View File

@ -252,4 +252,4 @@ export function matchI18nMutableOpCodes(expectedMutableOpCodes: string[]):
};
return matcher;
}
}

View File

@ -93,4 +93,4 @@ describe('render3 matchers', () => {
expect(matcher.jasmineToString!()).toEqual(`[#TEXT: "myText" != #TEXT: "other text"]`);
});
});
});
});

View File

@ -81,4 +81,4 @@ export class ViewFixture {
this.leaveView();
}
}
}
}

View File

@ -210,4 +210,4 @@ export class BuiltInControlValueAccessor extends BaseControlValueAccessor {
* @publicApi
*/
export const NG_VALUE_ACCESSOR =
new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');
new InjectionToken<ReadonlyArray<ControlValueAccessor>>('NgValueAccessor');

View File

@ -575,4 +575,4 @@ function getUniqueLocations<T extends ts.DocumentSpan>(locations: readonly T[]):
uniqueLocations.set(createLocationKey(location), location);
}
return Array.from(uniqueLocations.values());
}
}

View File

@ -413,4 +413,4 @@ function getRenameRequestPosition(renameRequest: RenameRequest): FilePosition {
renameRequest.requestNode.getStart() :
renameRequest.renamePosition.position;
return {fileName, position};
}
}

View File

@ -294,4 +294,4 @@ export function getParentClassMeta(requestNode: ts.Node, compiler: NgCompiler):
return null;
}
return compiler.getMeta(parentClass);
}
}

View File

@ -101,4 +101,4 @@ function last<T>(array: T[]): T {
throw new Error(`last() called on empty array`);
}
return array[array.length - 1];
}
}

View File

@ -374,4 +374,4 @@ export function getTemplateLocationFromShimLocation(
return null;
}
return {templateUrl, span};
}
}

View File

@ -103,4 +103,4 @@ const _ESCAPED_CHARS: [RegExp, string][] = [
function escapeXml(text: string): string {
return _ESCAPED_CHARS.reduce(
(text: string, entry: [RegExp, string]) => text.replace(entry[0], entry[1]), text);
}
}

View File

@ -73,4 +73,4 @@ describe('extractIcuPlaceholders()', () => {
'}\n }}\n}',
]);
});
});
});

View File

@ -181,4 +181,4 @@ export class RouterLinkActive implements OnChanges, OnDestroy, AfterContentInit
this.linkWithHref && isActiveCheckFn(this.linkWithHref) ||
this.links.some(isActiveCheckFn) || this.linksWithHrefs.some(isActiveCheckFn);
}
}
}

View File

@ -136,4 +136,4 @@ export function sortByMatchingOutlets(routes: Routes, outletName: string): Route
const sortedConfig = routes.filter(r => getOutlet(r) === outletName);
sortedConfig.push(...routes.filter(r => getOutlet(r) !== outletName));
return sortedConfig;
}
}

View File

@ -6,6 +6,7 @@
"node_modules/tslint-no-toplevel-property-access/rules"
],
"rules": {
"eofline": true,
"file-header": [
true,
{
@ -56,6 +57,7 @@
]
},
"jsRules": {
"eofline": true,
"file-header": [
true,
{