From b2666a2857d368b85948825d3ea0d96949a9a5b0 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 3 Oct 2019 12:46:38 +0300 Subject: [PATCH] build(docs-infra): enable more TypeScript strictness flags (#32980) PR Close #32980 --- .../custom-elements/api/api-list.component.ts | 30 +++++++------------ .../app/custom-elements/api/api.service.ts | 2 +- .../code/code.component.spec.ts | 2 +- .../custom-elements/code/code.component.ts | 6 ++-- .../contributor-list.component.spec.ts | 2 +- .../custom-elements/elements-loader.spec.ts | 14 ++++----- .../doc-viewer/doc-viewer.component.spec.ts | 4 +-- aio/src/app/shared/scroll-spy.service.spec.ts | 4 +-- .../search-results.component.spec.ts | 2 +- .../search-results.component.ts | 4 +-- aio/src/app/shared/toc.service.spec.ts | 2 +- aio/src/testing/doc-viewer-utils.ts | 13 +++++--- aio/tools/firebase-test-utils/FirebaseGlob.ts | 17 ++++++----- .../firebase-test-utils/FirebaseRedirect.ts | 13 ++++---- .../firebase-test-utils/FirebaseRedirector.ts | 3 +- aio/tsconfig.json | 3 ++ 16 files changed, 64 insertions(+), 57 deletions(-) diff --git a/aio/src/app/custom-elements/api/api-list.component.ts b/aio/src/app/custom-elements/api/api-list.component.ts index ab17aaf75a..4ef0d578ed 100644 --- a/aio/src/app/custom-elements/api/api-list.component.ts +++ b/aio/src/app/custom-elements/api/api-list.component.ts @@ -11,7 +11,7 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { combineLatest, Observable, ReplaySubject } from 'rxjs'; import { LocationService } from 'app/shared/location.service'; -import { ApiSection, ApiService } from './api.service'; +import { ApiItem, ApiSection, ApiService } from './api.service'; import { Option } from 'app/shared/select/select.component'; import { map } from 'rxjs/operators'; @@ -112,28 +112,20 @@ export class ApiListComponent implements OnInit { //////// Private ////////// private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) { - const items = section.items!.filter(item => { - return matchesType() && matchesStatus() && matchesQuery(); + const sectionNameMatches = !query || section.name.indexOf(query) !== -1; - function matchesQuery() { - return !query || - section.name.indexOf(query) !== -1 || - item.name.indexOf(query) !== -1; - } + const matchesQuery = (item: ApiItem) => + sectionNameMatches || item.name.indexOf(query!) !== -1; + const matchesStatus = (item: ApiItem) => + status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk); + const matchesType = (item: ApiItem) => + type === 'all' || type === item.docType; - function matchesStatus() { - return status === 'all' || - status === item.stability || - (status === 'security-risk' && item.securityRisk); - } - - function matchesType() { - return type === 'all' || type === item.docType; - } - }); + const items = section.items!.filter(item => + matchesType(item) && matchesStatus(item) && matchesQuery(item)); // If there are no items we still return an empty array if the section name matches and the type is 'package' - return items.length ? items : (type === 'package' && (!query || section.name.indexOf(query) !== -1)) ? [] : null; + return items.length ? items : (sectionNameMatches && type === 'package') ? [] : null; } // Get initial search criteria from URL search params diff --git a/aio/src/app/custom-elements/api/api.service.ts b/aio/src/app/custom-elements/api/api.service.ts index e7b6cc0b38..ae94866a4b 100644 --- a/aio/src/app/custom-elements/api/api.service.ts +++ b/aio/src/app/custom-elements/api/api.service.ts @@ -45,7 +45,7 @@ export class ApiService implements OnDestroy { this.fetchSections(); // TODO: get URL for fetchSections by configuration? // makes sectionsSubject hot; subscribe ensures stays alive (always refCount > 0); - this._sections.subscribe(sections => this.logger.log('ApiService got API sections') ); + this._sections.subscribe(sections => this.logger.log(`ApiService got API ${sections.length} section(s)`)); } return this._sections.pipe(tap(sections => { diff --git a/aio/src/app/custom-elements/code/code.component.spec.ts b/aio/src/app/custom-elements/code/code.component.spec.ts index cb297b6499..1a93817245 100644 --- a/aio/src/app/custom-elements/code/code.component.spec.ts +++ b/aio/src/app/custom-elements/code/code.component.spec.ts @@ -251,7 +251,7 @@ describe('CodeComponent', () => { actualCode = spy.calls.mostRecent().args[0]; expect(actualCode).toBe(expectedCode, `when linenums=${linenums}`); - expect(actualCode.match(/\r?\n/g).length).toBe(5); + expect(actualCode.match(/\r?\n/g)!.length).toBe(5); spy.calls.reset(); }); diff --git a/aio/src/app/custom-elements/code/code.component.ts b/aio/src/app/custom-elements/code/code.component.ts index c34f72e991..27246ab1d2 100644 --- a/aio/src/app/custom-elements/code/code.component.ts +++ b/aio/src/app/custom-elements/code/code.component.ts @@ -113,9 +113,9 @@ export class CodeComponent implements OnChanges { this.codeText = this.getCodeText(); // store the unformatted code as text (for copying) this.pretty - .formatCode(leftAlignedCode, this.language, this.getLinenums(leftAlignedCode)) + .formatCode(leftAlignedCode, this.language, this.getLinenums()) .pipe(tap(() => this.codeFormatted.emit())) - .subscribe(c => this.setCodeHtml(c), err => { /* ignore failure to format */ } + .subscribe(c => this.setCodeHtml(c), () => { /* ignore failure to format */ } ); } @@ -156,7 +156,7 @@ export class CodeComponent implements OnChanges { } /** Gets the calculated value of linenums (boolean/number). */ - getLinenums(code: string) { + getLinenums() { const linenums = typeof this.linenums === 'boolean' ? this.linenums : this.linenums === 'true' ? true : diff --git a/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts b/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts index 6d7b8e40a0..48d9bd2080 100644 --- a/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts +++ b/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts @@ -85,7 +85,7 @@ describe('ContributorListComponent', () => { searchResult: SearchResult = {}; search = jasmine.createSpy('search').and.callFake(() => this.searchResult); setSearch = jasmine.createSpy('setSearch') - .and.callFake((label: string, result: SearchResult) => { + .and.callFake((_label: string, result: SearchResult) => { this.searchResult = result; }); } diff --git a/aio/src/app/custom-elements/elements-loader.spec.ts b/aio/src/app/custom-elements/elements-loader.spec.ts index 36185a2067..ba4584d18b 100644 --- a/aio/src/app/custom-elements/elements-loader.spec.ts +++ b/aio/src/app/custom-elements/elements-loader.spec.ts @@ -260,10 +260,10 @@ class FakeComponentFactory extends ComponentFactory { constructor(private identifyingInput: string) { super(); } - create(injector: Injector, - projectableNodes?: any[][], - rootSelectorOrNode?: string | any, - ngModule?: NgModuleRef): ComponentRef { + create(_injector: Injector, + _projectableNodes?: any[][], + _rootSelectorOrNode?: string | any, + _ngModule?: NgModuleRef): ComponentRef { return jasmine.createSpy('ComponentRef') as any; } } @@ -271,7 +271,7 @@ class FakeComponentFactory extends ComponentFactory { class FakeComponentFactoryResolver extends ComponentFactoryResolver { constructor(private modulePath: string) { super(); } - resolveComponentFactory(component: Type): ComponentFactory { + resolveComponentFactory(_component: Type): ComponentFactory { return new FakeComponentFactory(this.modulePath); } } @@ -288,7 +288,7 @@ class FakeModuleRef extends NgModuleRef { } destroy() {} - onDestroy(callback: () => void) {} + onDestroy(_callback: () => void) {} } class FakeModuleFactory extends NgModuleFactory { @@ -297,7 +297,7 @@ class FakeModuleFactory extends NgModuleFactory { constructor(private modulePath: string) { super(); } - create(parentInjector: Injector | null): NgModuleRef { + create(_parentInjector: Injector | null): NgModuleRef { return this.moduleRefToCreate; } } diff --git a/aio/src/app/layout/doc-viewer/doc-viewer.component.spec.ts b/aio/src/app/layout/doc-viewer/doc-viewer.component.spec.ts index 965a734dff..ef241b1b2b 100644 --- a/aio/src/app/layout/doc-viewer/doc-viewer.component.spec.ts +++ b/aio/src/app/layout/doc-viewer/doc-viewer.component.spec.ts @@ -47,7 +47,7 @@ describe('DocViewerComponent', () => { parentFixture.detectChanges(); }; - beforeEach(() => renderSpy = spyOn(docViewer, 'render').and.returnValue([null])); + beforeEach(() => renderSpy = spyOn(docViewer, 'render').and.returnValue(of(undefined))); it('should render the new document', () => { setCurrentDoc('foo', 'bar'); @@ -87,7 +87,7 @@ describe('DocViewerComponent', () => { describe('#ngOnDestroy()', () => { it('should stop responding to document changes', () => { - const renderSpy = spyOn(docViewer, 'render').and.returnValue([undefined]); + const renderSpy = spyOn(docViewer, 'render').and.returnValue(of(undefined)); expect(renderSpy).not.toHaveBeenCalled(); diff --git a/aio/src/app/shared/scroll-spy.service.spec.ts b/aio/src/app/shared/scroll-spy.service.spec.ts index c2d2ed7be7..4563683c72 100644 --- a/aio/src/app/shared/scroll-spy.service.spec.ts +++ b/aio/src/app/shared/scroll-spy.service.spec.ts @@ -39,7 +39,7 @@ describe('ScrollSpiedElement', () => { describe('ScrollSpiedElementGroup', () => { describe('#calibrate()', () => { it('should calculate `top` for all spied elements', () => { - const spy = spyOn(ScrollSpiedElement.prototype, 'calculateTop').and.returnValue(0); + const spy = spyOn(ScrollSpiedElement.prototype, 'calculateTop'); const elems = [{}, {}, {}] as Element[]; const group = new ScrollSpiedElementGroup(elems); @@ -68,7 +68,7 @@ describe('ScrollSpiedElementGroup', () => { const tops = [50, 150, 100]; spyOn(ScrollSpiedElement.prototype, 'calculateTop').and.callFake( - function(this: ScrollSpiedElement, scrollTop: number, topOffset: number) { + function(this: ScrollSpiedElement) { this.top = tops[this.index]; }); diff --git a/aio/src/app/shared/search-results/search-results.component.spec.ts b/aio/src/app/shared/search-results/search-results.component.spec.ts index edd720c10c..e85eaa7a91 100644 --- a/aio/src/app/shared/search-results/search-results.component.spec.ts +++ b/aio/src/app/shared/search-results/search-results.component.spec.ts @@ -31,7 +31,7 @@ describe('SearchResultsComponent', () => { /** Pass the given search results to the component and trigger change detection. */ function setSearchResults(query: string, results: SearchResult[]) { component.searchResults = {query, results}; - component.ngOnChanges({}); + component.ngOnChanges(); fixture.detectChanges(); } diff --git a/aio/src/app/shared/search-results/search-results.component.ts b/aio/src/app/shared/search-results/search-results.component.ts index 6b401431b2..9e684c9dba 100644 --- a/aio/src/app/shared/search-results/search-results.component.ts +++ b/aio/src/app/shared/search-results/search-results.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { SearchResult, SearchResults, SearchArea } from 'app/search/interfaces'; /** @@ -27,7 +27,7 @@ export class SearchResultsComponent implements OnChanges { readonly topLevelFolders = ['guide', 'tutorial']; searchAreas: SearchArea[] = []; - ngOnChanges(changes: SimpleChanges) { + ngOnChanges() { this.searchAreas = this.processSearchResults(this.searchResults); } diff --git a/aio/src/app/shared/toc.service.spec.ts b/aio/src/app/shared/toc.service.spec.ts index d623e2dacd..ffe765e820 100644 --- a/aio/src/app/shared/toc.service.spec.ts +++ b/aio/src/app/shared/toc.service.spec.ts @@ -365,7 +365,7 @@ class MockScrollSpyService { return this.$$lastInfo; } - spyOn(headings: HTMLHeadingElement[]): ScrollSpyInfo { + spyOn(_headings: HTMLHeadingElement[]): ScrollSpyInfo { return this.$$lastInfo = { active: new Subject(), unspy: jasmine.createSpy('unspy'), diff --git a/aio/src/testing/doc-viewer-utils.ts b/aio/src/testing/doc-viewer-utils.ts index 6a3ca95137..fa2b1d1f61 100644 --- a/aio/src/testing/doc-viewer-utils.ts +++ b/aio/src/testing/doc-viewer-utils.ts @@ -20,9 +20,14 @@ export class TestDocViewerComponent extends DocViewerComponent { currViewContainer: HTMLElement; nextViewContainer: HTMLElement; - prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void { return null as any; } - render(doc: DocumentContents): Observable { return null as any; } - swapViews(onInsertedCb?: () => void): Observable { return null as any; } + // Only used for type-casting; the actual implementation is irrelevant. + prepareTitleAndToc(_targetElem: HTMLElement, _docId: string): () => void { return null as any; } + + // Only used for type-casting; the actual implementation is irrelevant. + render(_doc: DocumentContents): Observable { return null as any; } + + // Only used for type-casting; the actual implementation is irrelevant. + swapViews(_onInsertedCb?: () => void): Observable { return null as any; } } @@ -82,7 +87,7 @@ export class TestModule { } export class ObservableWithSubscriptionSpies extends Observable { unsubscribeSpies: jasmine.Spy[] = []; - subscribeSpy = spyOn(this, 'subscribe').and.callFake((...args: any[]) => { + subscribeSpy = spyOn(this as Observable, 'subscribe').and.callFake((...args: any[]) => { const subscription = super.subscribe(...args); const unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough(); this.unsubscribeSpies.push(unsubscribeSpy); diff --git a/aio/tools/firebase-test-utils/FirebaseGlob.ts b/aio/tools/firebase-test-utils/FirebaseGlob.ts index d4378c1a8e..6db7470cbb 100644 --- a/aio/tools/firebase-test-utils/FirebaseGlob.ts +++ b/aio/tools/firebase-test-utils/FirebaseGlob.ts @@ -47,18 +47,21 @@ export class FirebaseGlob { } } - test(url: string) { + test(url: string): boolean { return XRegExp.test(url, this.regex); } - match(url: string) { + match(url: string): { [key: string]: string } | undefined { const match = XRegExp.exec(url, this.regex) as ReturnType & { [captured: string]: string }; - if (match) { - const result: { [key: string]: string } = {}; - const names = this.regex.xregexp.captureNames || []; - names.forEach(name => result[name] = (match[name])); - return result; + + if (!match) { + return undefined; } + + const result: { [key: string]: string } = {}; + const names = this.regex.xregexp.captureNames || []; + names.forEach(name => result[name] = (match[name])); + return result; } } diff --git a/aio/tools/firebase-test-utils/FirebaseRedirect.ts b/aio/tools/firebase-test-utils/FirebaseRedirect.ts index 9dee3bd011..b8983a7678 100644 --- a/aio/tools/firebase-test-utils/FirebaseRedirect.ts +++ b/aio/tools/firebase-test-utils/FirebaseRedirect.ts @@ -5,12 +5,15 @@ export class FirebaseRedirect { glob = new FirebaseGlob(this.source); constructor(public source: string, public destination: string) {} - replace(url: string) { + replace(url: string): string | undefined { const match = this.glob.match(url); - if (match) { - const paramReplacers = Object.keys(this.glob.namedParams).map(name => [ XRegExp(`:${name}`, 'g'), match[name] ]); - const restReplacers = Object.keys(this.glob.restParams).map(name => [ XRegExp(`:${name}\\*`, 'g'), match[name] ]); - return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]); + + if (!match) { + return undefined; } + + const paramReplacers = Object.keys(this.glob.namedParams).map(name => [ XRegExp(`:${name}`, 'g'), match[name] ]); + const restReplacers = Object.keys(this.glob.restParams).map(name => [ XRegExp(`:${name}\\*`, 'g'), match[name] ]); + return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]); } } diff --git a/aio/tools/firebase-test-utils/FirebaseRedirector.ts b/aio/tools/firebase-test-utils/FirebaseRedirector.ts index b9228270e6..36af0420b7 100644 --- a/aio/tools/firebase-test-utils/FirebaseRedirector.ts +++ b/aio/tools/firebase-test-utils/FirebaseRedirector.ts @@ -11,7 +11,7 @@ export class FirebaseRedirector { this.redirects = redirects.map(redirect => new FirebaseRedirect(redirect.source, redirect.destination)); } - redirect(url: string) { + redirect(url: string): string { let ttl = 50; while (ttl > 0) { const newUrl = this.doRedirect(url); @@ -24,6 +24,7 @@ export class FirebaseRedirector { } throw new Error('infinite redirect loop'); } + private doRedirect(url: string) { for (const redirect of this.redirects) { const newUrl = redirect.replace(url); diff --git a/aio/tsconfig.json b/aio/tsconfig.json index 01bb149599..d7427181d1 100644 --- a/aio/tsconfig.json +++ b/aio/tsconfig.json @@ -19,7 +19,10 @@ ], "skipLibCheck": true, "strict": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, "noUnusedLocals": true, + "noUnusedParameters": true, // disabled because this is on by default in tsc 2.7 breaking our codebase - we need to refactor "strictPropertyInitialization": false },