From f479de6d02328156ede70c6e7de9f50cd16a4fac Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 10 Apr 2018 14:38:16 -0700 Subject: [PATCH] patternMatcher: Just return 'undefined' for an invalid pattern (#23237) * patternMatcher: Just return 'undefined' for an invalid pattern * Fix tests --- .../unittests/services/patternMatcher.ts | 12 +++++----- src/services/navigateTo.ts | 1 + src/services/patternMatcher.ts | 23 +++++-------------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/harness/unittests/services/patternMatcher.ts b/src/harness/unittests/services/patternMatcher.ts index a3e2d1d5cff..5aee5d2f4eb 100644 --- a/src/harness/unittests/services/patternMatcher.ts +++ b/src/harness/unittests/services/patternMatcher.ts @@ -343,15 +343,11 @@ describe("PatternMatcher", () => { }); it("BlankPattern", () => { - const matches = getAllMatches("AddMetadataReference", ""); - - assert.isTrue(matches === undefined); + assertInvalidPattern(""); }); it("WhitespaceOnlyPattern", () => { - const matches = getAllMatches("AddMetadataReference", " "); - - assert.isTrue(matches === undefined); + assertInvalidPattern(" "); }); it("EachWordSeparately1", () => { @@ -449,6 +445,10 @@ describe("PatternMatcher", () => { }); }); + function assertInvalidPattern(pattern: string) { + assert.equal(ts.createPatternMatcher(pattern), undefined); + } + function getFirstMatch(candidate: string, pattern: string): ts.PatternMatch { const matches = ts.createPatternMatcher(pattern).getMatchesForLastSegmentOfPattern(candidate); return matches ? matches[0] : undefined; diff --git a/src/services/navigateTo.ts b/src/services/navigateTo.ts index 1a556cf33c0..4713f89dbde 100644 --- a/src/services/navigateTo.ts +++ b/src/services/navigateTo.ts @@ -10,6 +10,7 @@ namespace ts.NavigateTo { export function getNavigateToItems(sourceFiles: ReadonlyArray, checker: TypeChecker, cancellationToken: CancellationToken, searchValue: string, maxResultCount: number, excludeDtsFiles: boolean): NavigateToItem[] { const patternMatcher = createPatternMatcher(searchValue); + if (!patternMatcher) return emptyArray; let rawItems: RawNavigateToItem[] = []; // Search the declarations in all files and output matched NavigateToItem into array of NavigateToItem[] diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index 612fa57378d..84ef1244040 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -97,28 +97,22 @@ namespace ts { }; } - export function createPatternMatcher(pattern: string): PatternMatcher { + export function createPatternMatcher(pattern: string): PatternMatcher | undefined { // We'll often see the same candidate string many times when searching (For example, when // we see the name of a module that is used everywhere, or the name of an overload). As // such, we cache the information we compute about the candidate for the life of this // pattern matcher so we don't have to compute it multiple times. const stringToWordSpans = createMap(); - pattern = pattern.trim(); - - const dotSeparatedSegments = pattern.split(".").map(p => createSegment(p.trim())); - const invalidPattern = dotSeparatedSegments.length === 0 || forEach(dotSeparatedSegments, segmentIsInvalid); + const dotSeparatedSegments = pattern.trim().split(".").map(p => createSegment(p.trim())); + // A segment is considered invalid if we couldn't find any words in it. + if (dotSeparatedSegments.some(segment => !segment.subWordTextChunks.length)) return undefined; return { - getMatches: (containers, candidate) => skipMatch(candidate) ? undefined : getMatches(containers, candidate, dotSeparatedSegments, stringToWordSpans), - getMatchesForLastSegmentOfPattern: candidate => skipMatch(candidate) ? undefined : matchSegment(candidate, lastOrUndefined(dotSeparatedSegments), stringToWordSpans), + getMatches: (containers, candidate) => getMatches(containers, candidate, dotSeparatedSegments, stringToWordSpans), + getMatchesForLastSegmentOfPattern: candidate => matchSegment(candidate, last(dotSeparatedSegments), stringToWordSpans), patternContainsDots: dotSeparatedSegments.length > 1 }; - - // Quick checks so we can bail out when asked to match a candidate. - function skipMatch(candidate: string) { - return invalidPattern || !candidate; - } } function getMatches(candidateContainers: ReadonlyArray, candidate: string, dotSeparatedSegments: ReadonlyArray, stringToWordSpans: Map): PatternMatch[] | undefined { @@ -381,11 +375,6 @@ namespace ts { }; } - // A segment is considered invalid if we couldn't find any words in it. - function segmentIsInvalid(segment: Segment) { - return segment.subWordTextChunks.length === 0; - } - function isUpperCaseLetter(ch: number) { // Fast check for the ascii range. if (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) {