build(docs-infra): enable more TypeScript strictness flags (#32980)
PR Close #32980
This commit is contained in:
parent
9abc1f9156
commit
b2666a2857
|
@ -11,7 +11,7 @@ import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||||
import { combineLatest, Observable, ReplaySubject } from 'rxjs';
|
import { combineLatest, Observable, ReplaySubject } from 'rxjs';
|
||||||
|
|
||||||
import { LocationService } from 'app/shared/location.service';
|
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 { Option } from 'app/shared/select/select.component';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
@ -112,28 +112,20 @@ export class ApiListComponent implements OnInit {
|
||||||
//////// Private //////////
|
//////// Private //////////
|
||||||
|
|
||||||
private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) {
|
private filterSection(section: ApiSection, { query, status, type }: SearchCriteria) {
|
||||||
const items = section.items!.filter(item => {
|
const sectionNameMatches = !query || section.name.indexOf(query) !== -1;
|
||||||
return matchesType() && matchesStatus() && matchesQuery();
|
|
||||||
|
|
||||||
function matchesQuery() {
|
const matchesQuery = (item: ApiItem) =>
|
||||||
return !query ||
|
sectionNameMatches || item.name.indexOf(query!) !== -1;
|
||||||
section.name.indexOf(query) !== -1 ||
|
const matchesStatus = (item: ApiItem) =>
|
||||||
item.name.indexOf(query) !== -1;
|
status === 'all' || status === item.stability || (status === 'security-risk' && item.securityRisk);
|
||||||
}
|
const matchesType = (item: ApiItem) =>
|
||||||
|
type === 'all' || type === item.docType;
|
||||||
|
|
||||||
function matchesStatus() {
|
const items = section.items!.filter(item =>
|
||||||
return status === 'all' ||
|
matchesType(item) && matchesStatus(item) && matchesQuery(item));
|
||||||
status === item.stability ||
|
|
||||||
(status === 'security-risk' && item.securityRisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchesType() {
|
|
||||||
return type === 'all' || type === item.docType;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// If there are no items we still return an empty array if the section name matches and the type is 'package'
|
// 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
|
// Get initial search criteria from URL search params
|
||||||
|
|
|
@ -45,7 +45,7 @@ export class ApiService implements OnDestroy {
|
||||||
this.fetchSections(); // TODO: get URL for fetchSections by configuration?
|
this.fetchSections(); // TODO: get URL for fetchSections by configuration?
|
||||||
|
|
||||||
// makes sectionsSubject hot; subscribe ensures stays alive (always refCount > 0);
|
// 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 => {
|
return this._sections.pipe(tap(sections => {
|
||||||
|
|
|
@ -251,7 +251,7 @@ describe('CodeComponent', () => {
|
||||||
actualCode = spy.calls.mostRecent().args[0];
|
actualCode = spy.calls.mostRecent().args[0];
|
||||||
|
|
||||||
expect(actualCode).toBe(expectedCode, `when linenums=${linenums}`);
|
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();
|
spy.calls.reset();
|
||||||
});
|
});
|
||||||
|
|
|
@ -113,9 +113,9 @@ export class CodeComponent implements OnChanges {
|
||||||
this.codeText = this.getCodeText(); // store the unformatted code as text (for copying)
|
this.codeText = this.getCodeText(); // store the unformatted code as text (for copying)
|
||||||
|
|
||||||
this.pretty
|
this.pretty
|
||||||
.formatCode(leftAlignedCode, this.language, this.getLinenums(leftAlignedCode))
|
.formatCode(leftAlignedCode, this.language, this.getLinenums())
|
||||||
.pipe(tap(() => this.codeFormatted.emit()))
|
.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). */
|
/** Gets the calculated value of linenums (boolean/number). */
|
||||||
getLinenums(code: string) {
|
getLinenums() {
|
||||||
const linenums =
|
const linenums =
|
||||||
typeof this.linenums === 'boolean' ? this.linenums :
|
typeof this.linenums === 'boolean' ? this.linenums :
|
||||||
this.linenums === 'true' ? true :
|
this.linenums === 'true' ? true :
|
||||||
|
|
|
@ -85,7 +85,7 @@ describe('ContributorListComponent', () => {
|
||||||
searchResult: SearchResult = {};
|
searchResult: SearchResult = {};
|
||||||
search = jasmine.createSpy('search').and.callFake(() => this.searchResult);
|
search = jasmine.createSpy('search').and.callFake(() => this.searchResult);
|
||||||
setSearch = jasmine.createSpy('setSearch')
|
setSearch = jasmine.createSpy('setSearch')
|
||||||
.and.callFake((label: string, result: SearchResult) => {
|
.and.callFake((_label: string, result: SearchResult) => {
|
||||||
this.searchResult = result;
|
this.searchResult = result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,10 +260,10 @@ class FakeComponentFactory extends ComponentFactory<any> {
|
||||||
|
|
||||||
constructor(private identifyingInput: string) { super(); }
|
constructor(private identifyingInput: string) { super(); }
|
||||||
|
|
||||||
create(injector: Injector,
|
create(_injector: Injector,
|
||||||
projectableNodes?: any[][],
|
_projectableNodes?: any[][],
|
||||||
rootSelectorOrNode?: string | any,
|
_rootSelectorOrNode?: string | any,
|
||||||
ngModule?: NgModuleRef<any>): ComponentRef<any> {
|
_ngModule?: NgModuleRef<any>): ComponentRef<any> {
|
||||||
return jasmine.createSpy('ComponentRef') as any;
|
return jasmine.createSpy('ComponentRef') as any;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +271,7 @@ class FakeComponentFactory extends ComponentFactory<any> {
|
||||||
class FakeComponentFactoryResolver extends ComponentFactoryResolver {
|
class FakeComponentFactoryResolver extends ComponentFactoryResolver {
|
||||||
constructor(private modulePath: string) { super(); }
|
constructor(private modulePath: string) { super(); }
|
||||||
|
|
||||||
resolveComponentFactory(component: Type<any>): ComponentFactory<any> {
|
resolveComponentFactory(_component: Type<any>): ComponentFactory<any> {
|
||||||
return new FakeComponentFactory(this.modulePath);
|
return new FakeComponentFactory(this.modulePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ class FakeModuleRef extends NgModuleRef<WithCustomElementComponent> {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {}
|
destroy() {}
|
||||||
onDestroy(callback: () => void) {}
|
onDestroy(_callback: () => void) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeModuleFactory extends NgModuleFactory<any> {
|
class FakeModuleFactory extends NgModuleFactory<any> {
|
||||||
|
@ -297,7 +297,7 @@ class FakeModuleFactory extends NgModuleFactory<any> {
|
||||||
|
|
||||||
constructor(private modulePath: string) { super(); }
|
constructor(private modulePath: string) { super(); }
|
||||||
|
|
||||||
create(parentInjector: Injector | null): NgModuleRef<any> {
|
create(_parentInjector: Injector | null): NgModuleRef<any> {
|
||||||
return this.moduleRefToCreate;
|
return this.moduleRefToCreate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ describe('DocViewerComponent', () => {
|
||||||
parentFixture.detectChanges();
|
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', () => {
|
it('should render the new document', () => {
|
||||||
setCurrentDoc('foo', 'bar');
|
setCurrentDoc('foo', 'bar');
|
||||||
|
@ -87,7 +87,7 @@ describe('DocViewerComponent', () => {
|
||||||
|
|
||||||
describe('#ngOnDestroy()', () => {
|
describe('#ngOnDestroy()', () => {
|
||||||
it('should stop responding to document changes', () => {
|
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();
|
expect(renderSpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ describe('ScrollSpiedElement', () => {
|
||||||
describe('ScrollSpiedElementGroup', () => {
|
describe('ScrollSpiedElementGroup', () => {
|
||||||
describe('#calibrate()', () => {
|
describe('#calibrate()', () => {
|
||||||
it('should calculate `top` for all spied elements', () => {
|
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 elems = [{}, {}, {}] as Element[];
|
||||||
const group = new ScrollSpiedElementGroup(elems);
|
const group = new ScrollSpiedElementGroup(elems);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ describe('ScrollSpiedElementGroup', () => {
|
||||||
const tops = [50, 150, 100];
|
const tops = [50, 150, 100];
|
||||||
|
|
||||||
spyOn(ScrollSpiedElement.prototype, 'calculateTop').and.callFake(
|
spyOn(ScrollSpiedElement.prototype, 'calculateTop').and.callFake(
|
||||||
function(this: ScrollSpiedElement, scrollTop: number, topOffset: number) {
|
function(this: ScrollSpiedElement) {
|
||||||
this.top = tops[this.index];
|
this.top = tops[this.index];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ describe('SearchResultsComponent', () => {
|
||||||
/** Pass the given search results to the component and trigger change detection. */
|
/** Pass the given search results to the component and trigger change detection. */
|
||||||
function setSearchResults(query: string, results: SearchResult[]) {
|
function setSearchResults(query: string, results: SearchResult[]) {
|
||||||
component.searchResults = {query, results};
|
component.searchResults = {query, results};
|
||||||
component.ngOnChanges({});
|
component.ngOnChanges();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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';
|
import { SearchResult, SearchResults, SearchArea } from 'app/search/interfaces';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +27,7 @@ export class SearchResultsComponent implements OnChanges {
|
||||||
readonly topLevelFolders = ['guide', 'tutorial'];
|
readonly topLevelFolders = ['guide', 'tutorial'];
|
||||||
searchAreas: SearchArea[] = [];
|
searchAreas: SearchArea[] = [];
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges() {
|
||||||
this.searchAreas = this.processSearchResults(this.searchResults);
|
this.searchAreas = this.processSearchResults(this.searchResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -365,7 +365,7 @@ class MockScrollSpyService {
|
||||||
return this.$$lastInfo;
|
return this.$$lastInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
spyOn(headings: HTMLHeadingElement[]): ScrollSpyInfo {
|
spyOn(_headings: HTMLHeadingElement[]): ScrollSpyInfo {
|
||||||
return this.$$lastInfo = {
|
return this.$$lastInfo = {
|
||||||
active: new Subject<ScrollItem | null>(),
|
active: new Subject<ScrollItem | null>(),
|
||||||
unspy: jasmine.createSpy('unspy'),
|
unspy: jasmine.createSpy('unspy'),
|
||||||
|
|
|
@ -20,9 +20,14 @@ export class TestDocViewerComponent extends DocViewerComponent {
|
||||||
currViewContainer: HTMLElement;
|
currViewContainer: HTMLElement;
|
||||||
nextViewContainer: HTMLElement;
|
nextViewContainer: HTMLElement;
|
||||||
|
|
||||||
prepareTitleAndToc(targetElem: HTMLElement, docId: string): () => void { return null as any; }
|
// Only used for type-casting; the actual implementation is irrelevant.
|
||||||
render(doc: DocumentContents): Observable<void> { return null as any; }
|
prepareTitleAndToc(_targetElem: HTMLElement, _docId: string): () => void { return null as any; }
|
||||||
swapViews(onInsertedCb?: () => void): Observable<void> { return null as any; }
|
|
||||||
|
// Only used for type-casting; the actual implementation is irrelevant.
|
||||||
|
render(_doc: DocumentContents): Observable<void> { return null as any; }
|
||||||
|
|
||||||
|
// Only used for type-casting; the actual implementation is irrelevant.
|
||||||
|
swapViews(_onInsertedCb?: () => void): Observable<void> { return null as any; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,7 +87,7 @@ export class TestModule { }
|
||||||
|
|
||||||
export class ObservableWithSubscriptionSpies<T = void> extends Observable<T> {
|
export class ObservableWithSubscriptionSpies<T = void> extends Observable<T> {
|
||||||
unsubscribeSpies: jasmine.Spy[] = [];
|
unsubscribeSpies: jasmine.Spy[] = [];
|
||||||
subscribeSpy = spyOn(this, 'subscribe').and.callFake((...args: any[]) => {
|
subscribeSpy = spyOn(this as Observable<T>, 'subscribe').and.callFake((...args: any[]) => {
|
||||||
const subscription = super.subscribe(...args);
|
const subscription = super.subscribe(...args);
|
||||||
const unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough();
|
const unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough();
|
||||||
this.unsubscribeSpies.push(unsubscribeSpy);
|
this.unsubscribeSpies.push(unsubscribeSpy);
|
||||||
|
|
|
@ -47,19 +47,22 @@ export class FirebaseGlob {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test(url: string) {
|
test(url: string): boolean {
|
||||||
return XRegExp.test(url, this.regex);
|
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<typeof XRegExp.exec> & { [captured: string]: string };
|
const match = XRegExp.exec(url, this.regex) as ReturnType<typeof XRegExp.exec> & { [captured: string]: string };
|
||||||
if (match) {
|
|
||||||
|
if (!match) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const result: { [key: string]: string } = {};
|
const result: { [key: string]: string } = {};
|
||||||
const names = this.regex.xregexp.captureNames || [];
|
const names = this.regex.xregexp.captureNames || [];
|
||||||
names.forEach(name => result[name] = (match[name]));
|
names.forEach(name => result[name] = (match[name]));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceModifiedPattern(_: string, modifier: string, pattern: string) {
|
function replaceModifiedPattern(_: string, modifier: string, pattern: string) {
|
||||||
|
|
|
@ -5,12 +5,15 @@ export class FirebaseRedirect {
|
||||||
glob = new FirebaseGlob(this.source);
|
glob = new FirebaseGlob(this.source);
|
||||||
constructor(public source: string, public destination: string) {}
|
constructor(public source: string, public destination: string) {}
|
||||||
|
|
||||||
replace(url: string) {
|
replace(url: string): string | undefined {
|
||||||
const match = this.glob.match(url);
|
const match = this.glob.match(url);
|
||||||
if (match) {
|
|
||||||
|
if (!match) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const paramReplacers = Object.keys(this.glob.namedParams).map(name => [ XRegExp(`:${name}`, 'g'), match[name] ]);
|
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] ]);
|
const restReplacers = Object.keys(this.glob.restParams).map(name => [ XRegExp(`:${name}\\*`, 'g'), match[name] ]);
|
||||||
return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]);
|
return XRegExp.replaceEach(this.destination, [...paramReplacers, ...restReplacers]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export class FirebaseRedirector {
|
||||||
this.redirects = redirects.map(redirect => new FirebaseRedirect(redirect.source, redirect.destination));
|
this.redirects = redirects.map(redirect => new FirebaseRedirect(redirect.source, redirect.destination));
|
||||||
}
|
}
|
||||||
|
|
||||||
redirect(url: string) {
|
redirect(url: string): string {
|
||||||
let ttl = 50;
|
let ttl = 50;
|
||||||
while (ttl > 0) {
|
while (ttl > 0) {
|
||||||
const newUrl = this.doRedirect(url);
|
const newUrl = this.doRedirect(url);
|
||||||
|
@ -24,6 +24,7 @@ export class FirebaseRedirector {
|
||||||
}
|
}
|
||||||
throw new Error('infinite redirect loop');
|
throw new Error('infinite redirect loop');
|
||||||
}
|
}
|
||||||
|
|
||||||
private doRedirect(url: string) {
|
private doRedirect(url: string) {
|
||||||
for (const redirect of this.redirects) {
|
for (const redirect of this.redirects) {
|
||||||
const newUrl = redirect.replace(url);
|
const newUrl = redirect.replace(url);
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
],
|
],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
// disabled because this is on by default in tsc 2.7 breaking our codebase - we need to refactor
|
// disabled because this is on by default in tsc 2.7 breaking our codebase - we need to refactor
|
||||||
"strictPropertyInitialization": false
|
"strictPropertyInitialization": false
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue