Skip to content

Commit 1959bff

Browse files
author
Andy Hanson
committed
Merge branch 'master' into patternMatcher_fns
2 parents e314ea0 + 72e92a0 commit 1959bff

File tree

3 files changed

+21
-111
lines changed

3 files changed

+21
-111
lines changed

src/harness/unittests/services/patternMatcher.ts

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ describe("PatternMatcher", () => {
127127

128128
assert.equal(ts.PatternMatchKind.camelCase, match.kind);
129129
assert.equal(true, match.isCaseSensitive);
130-
assertInRange(match.camelCaseWeight, 1, 1 << 30);
131130
});
132131

133132
it("PreferCaseSensitiveCamelCaseMatchPartialPattern", () => {
@@ -237,30 +236,6 @@ describe("PatternMatcher", () => {
237236
assert.equal(false, match.isCaseSensitive);
238237
});
239238

240-
it("PreferCaseSensitiveRelativeWeights1", () => {
241-
const match1 = getFirstMatch("FogBarBaz", "FB");
242-
const match2 = getFirstMatch("FooFlobBaz", "FB");
243-
244-
// We should prefer something that starts at the beginning if possible
245-
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
246-
});
247-
248-
it("PreferCaseSensitiveRelativeWeights2", () => {
249-
const match1 = getFirstMatch("BazBarFooFooFoo", "FFF");
250-
const match2 = getFirstMatch("BazFogBarFooFoo", "FFF");
251-
252-
// Contiguous things should also be preferred
253-
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
254-
});
255-
256-
it("PreferCaseSensitiveRelativeWeights3", () => {
257-
const match1 = getFirstMatch("FogBarFooFoo", "FFF");
258-
const match2 = getFirstMatch("BarFooFooFoo", "FFF");
259-
260-
// The weight of being first should be greater than the weight of being contiguous
261-
assertInRange(match1.camelCaseWeight, match2.camelCaseWeight + 1, 1 << 30);
262-
});
263-
264239
it("AllLowerPattern1", () => {
265240
const match = getFirstMatch("FogBarChangedEventArgs", "changedeventargs");
266241

@@ -507,11 +482,6 @@ describe("PatternMatcher", () => {
507482
}
508483
}
509484

510-
function assertInRange(val: number, low: number, high: number) {
511-
assert.isTrue(val >= low);
512-
assert.isTrue(val <= high);
513-
}
514-
515485
function verifyBreakIntoCharacterSpans(original: string, ...parts: string[]): void {
516486
assertArrayEquals(parts, breakIntoCharacterSpans(original));
517487
}

src/services/navigateTo.ts

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,7 @@ namespace ts.NavigateTo {
5656
}
5757
}
5858

59-
const matchKind = bestMatchKind(containerMatches);
60-
const isCaseSensitive = allMatchesAreCaseSensitive(containerMatches);
61-
rawItems.push({ name, fileName, matchKind, isCaseSensitive, declaration });
59+
rawItems.push({ name, fileName, matchKind: Math.min(...matches.map(m => m.kind)), isCaseSensitive: matches.every(m => m.isCaseSensitive), declaration });
6260
}
6361
}
6462

@@ -75,19 +73,6 @@ namespace ts.NavigateTo {
7573
}
7674
}
7775

78-
function allMatchesAreCaseSensitive(matches: ReadonlyArray<PatternMatch>): boolean {
79-
Debug.assert(matches.length > 0);
80-
81-
// This is a case sensitive match, only if all the submatches were case sensitive.
82-
for (const match of matches) {
83-
if (!match.isCaseSensitive) {
84-
return false;
85-
}
86-
}
87-
88-
return true;
89-
}
90-
9176
function tryAddSingleDeclarationName(declaration: Declaration, containers: string[]): boolean {
9277
const name = getNameOfDeclaration(declaration);
9378
if (name && isPropertyNameLiteral(name)) {
@@ -125,16 +110,14 @@ namespace ts.NavigateTo {
125110
return false;
126111
}
127112

128-
function getContainers(declaration: Declaration): string[] {
113+
function getContainers(declaration: Declaration): string[] | undefined {
129114
const containers: string[] = [];
130115

131116
// First, if we started with a computed property name, then add all but the last
132117
// portion into the container array.
133118
const name = getNameOfDeclaration(declaration);
134-
if (name.kind === SyntaxKind.ComputedPropertyName) {
135-
if (!tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) {
136-
return undefined;
137-
}
119+
if (name.kind === SyntaxKind.ComputedPropertyName && !tryAddComputedPropertyName(name.expression, containers, /*includeLastPortion*/ false)) {
120+
return undefined;
138121
}
139122

140123
// Now, walk up our containers, adding all their names to the container array.
@@ -151,20 +134,6 @@ namespace ts.NavigateTo {
151134
return containers;
152135
}
153136

154-
function bestMatchKind(matches: ReadonlyArray<PatternMatch>): PatternMatchKind {
155-
Debug.assert(matches.length > 0);
156-
let bestMatchKind = PatternMatchKind.camelCase;
157-
158-
for (const match of matches) {
159-
const kind = match.kind;
160-
if (kind < bestMatchKind) {
161-
bestMatchKind = kind;
162-
}
163-
}
164-
165-
return bestMatchKind;
166-
}
167-
168137
function compareNavigateToItems(i1: RawNavigateToItem, i2: RawNavigateToItem) {
169138
// TODO(cyrusn): get the gamut of comparisons that VS already uses here.
170139
return compareValues(i1.matchKind, i2.matchKind)

src/services/patternMatcher.ts

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,10 @@ namespace ts {
1515
// better than substring matches which are better than CamelCase matches.
1616
kind: PatternMatchKind;
1717

18-
// If this was a camel case match, how strong the match is. Higher number means
19-
// it was a better match.
20-
camelCaseWeight?: number;
21-
2218
// If this was a match where all constituent parts of the candidate and search pattern
2319
// matched case sensitively or case insensitively. Case sensitive matches of the kind
2420
// are better matches than insensitive matches.
2521
isCaseSensitive: boolean;
26-
27-
// Whether or not this match occurred with the punctuation from the search pattern stripped
28-
// out or not. Matches without the punctuation stripped are better than ones with punctuation
29-
// stripped.
30-
punctuationStripped: boolean;
3122
}
3223

3324
// The pattern matcher maintains an internal cache of information as it is used. Therefore,
@@ -99,12 +90,10 @@ namespace ts {
9990
characterSpans: TextSpan[];
10091
}
10192

102-
function createPatternMatch(kind: PatternMatchKind, punctuationStripped: boolean, isCaseSensitive: boolean, camelCaseWeight?: number): PatternMatch {
93+
function createPatternMatch(kind: PatternMatchKind, isCaseSensitive: boolean): PatternMatch {
10394
return {
10495
kind,
105-
punctuationStripped,
106-
isCaseSensitive,
107-
camelCaseWeight
96+
isCaseSensitive
10897
};
10998
}
11099

@@ -184,18 +173,18 @@ namespace ts {
184173
return spans;
185174
}
186175

187-
function matchTextChunk(candidate: string, chunk: TextChunk, punctuationStripped: boolean, stringToWordSpans: Map<TextSpan[]>): PatternMatch {
176+
function matchTextChunk(candidate: string, chunk: TextChunk, stringToWordSpans: Map<TextSpan[]>): PatternMatch {
188177
const index = indexOfIgnoringCase(candidate, chunk.textLowerCase);
189178
if (index === 0) {
190179
if (chunk.text.length === candidate.length) {
191180
// a) Check if the part matches the candidate entirely, in an case insensitive or
192181
// sensitive manner. If it does, return that there was an exact match.
193-
return createPatternMatch(PatternMatchKind.exact, punctuationStripped, /*isCaseSensitive:*/ candidate === chunk.text);
182+
return createPatternMatch(PatternMatchKind.exact, /*isCaseSensitive:*/ candidate === chunk.text);
194183
}
195184
else {
196185
// b) Check if the part is a prefix of the candidate, in a case insensitive or sensitive
197186
// manner. If it does, return that there was a prefix match.
198-
return createPatternMatch(PatternMatchKind.prefix, punctuationStripped, /*isCaseSensitive:*/ startsWith(candidate, chunk.text));
187+
return createPatternMatch(PatternMatchKind.prefix, /*isCaseSensitive:*/ startsWith(candidate, chunk.text));
199188
}
200189
}
201190

@@ -212,8 +201,7 @@ namespace ts {
212201
const wordSpans = getWordSpans(candidate, stringToWordSpans);
213202
for (const span of wordSpans) {
214203
if (partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ true)) {
215-
return createPatternMatch(PatternMatchKind.substring, punctuationStripped,
216-
/*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false));
204+
return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ partStartsWith(candidate, span, chunk.text, /*ignoreCase:*/ false));
217205
}
218206
}
219207
}
@@ -223,22 +211,18 @@ namespace ts {
223211
// candidate in a case *sensitive* manner. If so, return that there was a substring
224212
// match.
225213
if (candidate.indexOf(chunk.text) > 0) {
226-
return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ true);
214+
return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ true);
227215
}
228216
}
229217

230218
if (!isLowercase) {
231219
// e) If the part was not entirely lowercase, then attempt a camel cased match as well.
232220
if (chunk.characterSpans.length > 0) {
233221
const candidateParts = getWordSpans(candidate, stringToWordSpans);
234-
let camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false);
235-
if (camelCaseWeight !== undefined) {
236-
return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ true, /*camelCaseWeight:*/ camelCaseWeight);
237-
}
238-
239-
camelCaseWeight = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true);
240-
if (camelCaseWeight !== undefined) {
241-
return createPatternMatch(PatternMatchKind.camelCase, punctuationStripped, /*isCaseSensitive:*/ false, /*camelCaseWeight:*/ camelCaseWeight);
222+
const isCaseSensitive = tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ false) ? true
223+
: tryCamelCaseMatch(candidate, candidateParts, chunk, /*ignoreCase:*/ true) ? false : undefined;
224+
if (isCaseSensitive !== undefined) {
225+
return createPatternMatch(PatternMatchKind.camelCase, isCaseSensitive);
242226
}
243227
}
244228
}
@@ -253,7 +237,7 @@ namespace ts {
253237
// (Pattern: fogbar, Candidate: quuxfogbarFogBar).
254238
if (chunk.text.length < candidate.length) {
255239
if (index > 0 && isUpperCaseLetter(candidate.charCodeAt(index))) {
256-
return createPatternMatch(PatternMatchKind.substring, punctuationStripped, /*isCaseSensitive:*/ false);
240+
return createPatternMatch(PatternMatchKind.substring, /*isCaseSensitive:*/ false);
257241
}
258242
}
259243
}
@@ -281,7 +265,7 @@ namespace ts {
281265
// Note: if the segment contains a space or an asterisk then we must assume that it's a
282266
// multi-word segment.
283267
if (!containsSpaceOrAsterisk(segment.totalTextChunk.text)) {
284-
const match = matchTextChunk(candidate, segment.totalTextChunk, /*punctuationStripped:*/ false, stringToWordSpans);
268+
const match = matchTextChunk(candidate, segment.totalTextChunk, stringToWordSpans);
285269
if (match) {
286270
return [match];
287271
}
@@ -329,7 +313,7 @@ namespace ts {
329313

330314
for (const subWordTextChunk of subWordTextChunks) {
331315
// Try to match the candidate with this word
332-
const result = matchTextChunk(candidate, subWordTextChunk, /*punctuationStripped:*/ true, stringToWordSpans);
316+
const result = matchTextChunk(candidate, subWordTextChunk, stringToWordSpans);
333317
if (!result) {
334318
return undefined;
335319
}
@@ -372,7 +356,7 @@ namespace ts {
372356
return true;
373357
}
374358

375-
function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): number {
359+
function tryCamelCaseMatch(candidate: string, candidateParts: TextSpan[], chunk: TextChunk, ignoreCase: boolean): boolean {
376360
const chunkCharacterSpans = chunk.characterSpans;
377361

378362
// Note: we may have more pattern parts than candidate parts. This is because multiple
@@ -388,24 +372,11 @@ namespace ts {
388372
while (true) {
389373
// Let's consider our termination cases
390374
if (currentChunkSpan === chunkCharacterSpans.length) {
391-
// We did match! We shall assign a weight to this
392-
let weight = 0;
393-
394-
// Was this contiguous?
395-
if (contiguous) {
396-
weight += 1;
397-
}
398-
399-
// Did we start at the beginning of the candidate?
400-
if (firstMatch === 0) {
401-
weight += 2;
402-
}
403-
404-
return weight;
375+
return true;
405376
}
406377
else if (currentCandidate === candidateParts.length) {
407378
// No match, since we still have more of the pattern to hit
408-
return undefined;
379+
return false;
409380
}
410381

411382
let candidatePart = candidateParts[currentCandidate];

0 commit comments

Comments
 (0)