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 { 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
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -260,10 +260,10 @@ class FakeComponentFactory extends ComponentFactory<any> {
|
|||
|
||||
constructor(private identifyingInput: string) { super(); }
|
||||
|
||||
create(injector: Injector,
|
||||
projectableNodes?: any[][],
|
||||
rootSelectorOrNode?: string | any,
|
||||
ngModule?: NgModuleRef<any>): ComponentRef<any> {
|
||||
create(_injector: Injector,
|
||||
_projectableNodes?: any[][],
|
||||
_rootSelectorOrNode?: string | any,
|
||||
_ngModule?: NgModuleRef<any>): ComponentRef<any> {
|
||||
return jasmine.createSpy('ComponentRef') as any;
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ class FakeComponentFactory extends ComponentFactory<any> {
|
|||
class FakeComponentFactoryResolver extends ComponentFactoryResolver {
|
||||
constructor(private modulePath: string) { super(); }
|
||||
|
||||
resolveComponentFactory(component: Type<any>): ComponentFactory<any> {
|
||||
resolveComponentFactory(_component: Type<any>): ComponentFactory<any> {
|
||||
return new FakeComponentFactory(this.modulePath);
|
||||
}
|
||||
}
|
||||
|
@ -288,7 +288,7 @@ class FakeModuleRef extends NgModuleRef<WithCustomElementComponent> {
|
|||
}
|
||||
|
||||
destroy() {}
|
||||
onDestroy(callback: () => void) {}
|
||||
onDestroy(_callback: () => void) {}
|
||||
}
|
||||
|
||||
class FakeModuleFactory extends NgModuleFactory<any> {
|
||||
|
@ -297,7 +297,7 @@ class FakeModuleFactory extends NgModuleFactory<any> {
|
|||
|
||||
constructor(private modulePath: string) { super(); }
|
||||
|
||||
create(parentInjector: Injector | null): NgModuleRef<any> {
|
||||
create(_parentInjector: Injector | null): NgModuleRef<any> {
|
||||
return this.moduleRefToCreate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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];
|
||||
});
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ class MockScrollSpyService {
|
|||
return this.$$lastInfo;
|
||||
}
|
||||
|
||||
spyOn(headings: HTMLHeadingElement[]): ScrollSpyInfo {
|
||||
spyOn(_headings: HTMLHeadingElement[]): ScrollSpyInfo {
|
||||
return this.$$lastInfo = {
|
||||
active: new Subject<ScrollItem | null>(),
|
||||
unspy: jasmine.createSpy('unspy'),
|
||||
|
|
|
@ -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<void> { return null as any; }
|
||||
swapViews(onInsertedCb?: () => void): Observable<void> { 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<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> {
|
||||
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 unsubscribeSpy = spyOn(subscription, 'unsubscribe').and.callThrough();
|
||||
this.unsubscribeSpies.push(unsubscribeSpy);
|
||||
|
|
|
@ -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<typeof XRegExp.exec> & { [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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue