• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1describe("unittests:: services:: PatternMatcher", () => {
2    describe("BreakIntoCharacterSpans", () => {
3        it("EmptyIdentifier", () => {
4            verifyBreakIntoCharacterSpans("");
5        });
6
7        it("SimpleIdentifier", () => {
8            verifyBreakIntoCharacterSpans("foo", "foo");
9        });
10
11        it("PrefixUnderscoredIdentifier", () => {
12            verifyBreakIntoCharacterSpans("_foo", "_", "foo");
13        });
14
15        it("UnderscoredIdentifier", () => {
16            verifyBreakIntoCharacterSpans("f_oo", "f", "_", "oo");
17        });
18
19        it("PostfixUnderscoredIdentifier", () => {
20            verifyBreakIntoCharacterSpans("foo_", "foo", "_");
21        });
22
23        it("PrefixUnderscoredIdentifierWithCapital", () => {
24            verifyBreakIntoCharacterSpans("_Foo", "_", "Foo");
25        });
26
27        it("MUnderscorePrefixed", () => {
28            verifyBreakIntoCharacterSpans("m_foo", "m", "_", "foo");
29        });
30
31        it("CamelCaseIdentifier", () => {
32            verifyBreakIntoCharacterSpans("FogBar", "Fog", "Bar");
33        });
34
35        it("MixedCaseIdentifier", () => {
36            verifyBreakIntoCharacterSpans("fogBar", "fog", "Bar");
37        });
38
39        it("TwoCharacterCapitalIdentifier", () => {
40            verifyBreakIntoCharacterSpans("UIElement", "U", "I", "Element");
41        });
42
43        it("NumberSuffixedIdentifier", () => {
44            verifyBreakIntoCharacterSpans("Foo42", "Foo", "42");
45        });
46
47        it("NumberContainingIdentifier", () => {
48            verifyBreakIntoCharacterSpans("Fog42Bar", "Fog", "42", "Bar");
49        });
50
51        it("NumberPrefixedIdentifier", () => {
52            verifyBreakIntoCharacterSpans("42Bar", "42", "Bar");
53        });
54    });
55
56    describe("BreakIntoWordSpans", () => {
57        it("VarbatimIdentifier", () => {
58            verifyBreakIntoWordSpans("@int:", "int");
59        });
60
61        it("AllCapsConstant", () => {
62            verifyBreakIntoWordSpans("C_STYLE_CONSTANT", "C", "_", "STYLE", "_", "CONSTANT");
63        });
64
65        it("SingleLetterPrefix1", () => {
66            verifyBreakIntoWordSpans("UInteger", "U", "Integer");
67        });
68
69        it("SingleLetterPrefix2", () => {
70            verifyBreakIntoWordSpans("IDisposable", "I", "Disposable");
71        });
72
73        it("TwoCharacterCapitalIdentifier", () => {
74            verifyBreakIntoWordSpans("UIElement", "UI", "Element");
75        });
76
77        it("XDocument", () => {
78            verifyBreakIntoWordSpans("XDocument", "X", "Document");
79        });
80
81        it("XMLDocument1", () => {
82            verifyBreakIntoWordSpans("XMLDocument", "XML", "Document");
83        });
84
85        it("XMLDocument2", () => {
86            verifyBreakIntoWordSpans("XmlDocument", "Xml", "Document");
87        });
88
89        it("TwoUppercaseCharacters", () => {
90            verifyBreakIntoWordSpans("SimpleUIElement", "Simple", "UI", "Element");
91        });
92    });
93
94    describe("SingleWordPattern", () => {
95        it("PreferCaseSensitiveExact", () => {
96            assertSegmentMatch("Foo", "Foo", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true });
97        });
98
99        it("PreferCaseSensitiveExactInsensitive", () => {
100            assertSegmentMatch("foo", "Foo", { kind: ts.PatternMatchKind.exact, isCaseSensitive: false });
101        });
102
103        it("PreferCaseSensitivePrefix", () => {
104            assertSegmentMatch("Foo", "Fo", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
105        });
106
107        it("PreferCaseSensitivePrefixCaseInsensitive", () => {
108            assertSegmentMatch("Foo", "fo", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false });
109        });
110
111        it("PreferCaseSensitiveCamelCaseMatchSimple", () => {
112            assertSegmentMatch("FogBar", "FB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
113        });
114
115        it("PreferCaseSensitiveCamelCaseMatchPartialPattern", () => {
116            assertSegmentMatch("FogBar", "FoB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
117        });
118
119        it("PreferCaseSensitiveCamelCaseMatchToLongPattern1", () => {
120            assertSegmentMatch("FogBar", "FBB", undefined);
121        });
122
123        it("PreferCaseSensitiveCamelCaseMatchToLongPattern2", () => {
124            assertSegmentMatch("FogBar", "FoooB", undefined);
125        });
126
127        it("CamelCaseMatchPartiallyUnmatched", () => {
128            assertSegmentMatch("FogBarBaz", "FZ", undefined);
129        });
130
131        it("CamelCaseMatchCompletelyUnmatched", () => {
132            assertSegmentMatch("FogBarBaz", "ZZ", undefined);
133        });
134
135        it("TwoUppercaseCharacters", () => {
136            assertSegmentMatch("SimpleUIElement", "SiUI", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
137        });
138
139        it("PreferCaseSensitiveLowercasePattern", () => {
140            assertSegmentMatch("FogBar", "b", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false });
141        });
142
143        it("PreferCaseSensitiveLowercasePattern2", () => {
144            assertSegmentMatch("FogBar", "fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false });
145        });
146
147        it("PreferCaseSensitiveTryUnderscoredName", () => {
148            assertSegmentMatch("_fogBar", "_fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
149        });
150
151        it("PreferCaseSensitiveTryUnderscoredName2", () => {
152            assertSegmentMatch("_fogBar", "fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
153        });
154
155        it("PreferCaseSensitiveTryUnderscoredNameInsensitive", () => {
156            assertSegmentMatch("_FogBar", "_fB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false });
157        });
158
159        it("PreferCaseSensitiveMiddleUnderscore", () => {
160            assertSegmentMatch("Fog_Bar", "FB", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
161        });
162
163        it("PreferCaseSensitiveMiddleUnderscore2", () => {
164            assertSegmentMatch("Fog_Bar", "F_B", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
165        });
166
167        it("PreferCaseSensitiveMiddleUnderscore3", () => {
168            assertSegmentMatch("Fog_Bar", "F__B", undefined);
169        });
170
171        it("PreferCaseSensitiveMiddleUnderscore4", () => {
172            assertSegmentMatch("Fog_Bar", "f_B", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false });
173        });
174
175        it("PreferCaseSensitiveMiddleUnderscore5", () => {
176            assertSegmentMatch("Fog_Bar", "F_b", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: false });
177        });
178
179        it("AllLowerPattern1", () => {
180            assertSegmentMatch("FogBarChangedEventArgs", "changedeventargs", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false });
181        });
182
183        it("AllLowerPattern2", () => {
184            assertSegmentMatch("FogBarChangedEventArgs", "changedeventarrrgh", undefined);
185        });
186
187        it("AllLowerPattern3", () => {
188            assertSegmentMatch("ABCDEFGH", "bcd", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false });
189        });
190
191        it("AllLowerPattern4", () => {
192            assertSegmentMatch("AbcdefghijEfgHij", "efghij", undefined);
193        });
194    });
195
196    describe("MultiWordPattern", () => {
197        it("ExactWithLowercase", () => {
198            assertSegmentMatch("AddMetadataReference", "addmetadatareference", { kind: ts.PatternMatchKind.exact, isCaseSensitive: false });
199        });
200
201        it("SingleLowercasedSearchWord1", () => {
202            assertSegmentMatch("AddMetadataReference", "add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false });
203        });
204
205        it("SingleLowercasedSearchWord2", () => {
206            assertSegmentMatch("AddMetadataReference", "metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false });
207        });
208
209        it("SingleUppercaseSearchWord1", () => {
210            assertSegmentMatch("AddMetadataReference", "Add", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
211        });
212
213        it("SingleUppercaseSearchWord2", () => {
214            assertSegmentMatch("AddMetadataReference", "Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true });
215        });
216
217        it("SingleUppercaseSearchLetter1", () => {
218            assertSegmentMatch("AddMetadataReference", "A", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
219        });
220
221        it("SingleUppercaseSearchLetter2", () => {
222            assertSegmentMatch("AddMetadataReference", "M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true });
223        });
224
225        it("TwoLowercaseWords0", () => {
226            assertSegmentMatch("AddMetadataReference", "add metadata", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false });
227        });
228
229        it("TwoLowercaseWords1", () => {
230            assertSegmentMatch("AddMetadataReference", "A M", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
231        });
232
233        it("TwoLowercaseWords2", () => {
234            assertSegmentMatch("AddMetadataReference", "AM", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
235        });
236
237        it("TwoLowercaseWords3", () => {
238            assertSegmentMatch("AddMetadataReference", "ref Metadata", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true });
239        });
240
241        it("TwoLowercaseWords4", () => {
242            assertSegmentMatch("AddMetadataReference", "ref M", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true });
243        });
244
245        it("MixedCamelCase", () => {
246            assertSegmentMatch("AddMetadataReference", "AMRe", { kind: ts.PatternMatchKind.camelCase, isCaseSensitive: true });
247        });
248
249        it("BlankPattern", () => {
250            assertInvalidPattern("");
251        });
252
253        it("WhitespaceOnlyPattern", () => {
254            assertInvalidPattern(" ");
255        });
256
257        it("EachWordSeparately1", () => {
258            assertSegmentMatch("AddMetadataReference", "add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: false });
259        });
260
261        it("EachWordSeparately2", () => {
262            assertSegmentMatch("AddMetadataReference", "Add meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
263        });
264
265        it("EachWordSeparately3", () => {
266            assertSegmentMatch("AddMetadataReference", "Add Meta", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
267        });
268
269        it("MixedCasing", () => {
270            assertSegmentMatch("AddMetadataReference", "mEta", undefined);
271        });
272
273        it("MixedCasing2", () => {
274            assertSegmentMatch("AddMetadataReference", "Data", undefined);
275        });
276
277        it("AsteriskSplit", () => {
278            assertSegmentMatch("GetKeyWord", "K*W", { kind: ts.PatternMatchKind.substring, isCaseSensitive: true });
279        });
280
281        it("LowercaseSubstring1", () => {
282            assertSegmentMatch("Operator", "a", undefined);
283        });
284
285        it("LowercaseSubstring2", () => {
286            assertSegmentMatch("FooAttribute", "a", { kind: ts.PatternMatchKind.substring, isCaseSensitive: false });
287        });
288    });
289
290    describe("DottedPattern", () => {
291        it("DottedPattern1", () => {
292            assertFullMatch("Foo.Bar.Baz", "Quux", "B.Q", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
293        });
294
295        it("DottedPattern2", () => {
296            assertFullMatch("Foo.Bar.Baz", "Quux", "C.Q", undefined);
297        });
298
299        it("DottedPattern3", () => {
300            assertFullMatch("Foo.Bar.Baz", "Quux", "B.B.Q", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
301        });
302
303        it("DottedPattern4", () => {
304            assertFullMatch("Foo.Bar.Baz", "Quux", "Baz.Quux", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true });
305        });
306
307        it("DottedPattern5", () => {
308            assertFullMatch("Foo.Bar.Baz", "Quux", "F.B.B.Quux", { kind: ts.PatternMatchKind.prefix, isCaseSensitive: true });
309        });
310
311        it("DottedPattern6", () => {
312            assertFullMatch("Foo.Bar.Baz", "Quux", "F.F.B.B.Quux", undefined);
313        });
314
315        it("DottedPattern7", () => {
316            assertSegmentMatch("UIElement", "UIElement", { kind: ts.PatternMatchKind.exact, isCaseSensitive: true });
317            assertSegmentMatch("GetKeyword", "UIElement", undefined);
318        });
319    });
320
321    function assertSegmentMatch(candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void {
322        assert.deepEqual(ts.createPatternMatcher(pattern)!.getMatchForLastSegmentOfPattern(candidate), expected);
323    }
324
325    function assertInvalidPattern(pattern: string) {
326        assert.equal(ts.createPatternMatcher(pattern), undefined);
327    }
328
329    function assertFullMatch(dottedContainer: string, candidate: string, pattern: string, expected: ts.PatternMatch | undefined): void {
330        assert.deepEqual(ts.createPatternMatcher(pattern)!.getFullMatch(dottedContainer.split("."), candidate), expected);
331    }
332
333    function spanListToSubstrings(identifier: string, spans: ts.TextSpan[]) {
334        return spans.map(s => identifier.substr(s.start, s.length));
335    }
336
337    function breakIntoCharacterSpans(identifier: string) {
338        return spanListToSubstrings(identifier, ts.breakIntoCharacterSpans(identifier));
339    }
340
341    function breakIntoWordSpans(identifier: string) {
342        return spanListToSubstrings(identifier, ts.breakIntoWordSpans(identifier));
343    }
344
345    function verifyBreakIntoCharacterSpans(original: string, ...parts: string[]): void {
346        assert.deepEqual(parts, breakIntoCharacterSpans(original));
347    }
348
349    function verifyBreakIntoWordSpans(original: string, ...parts: string[]): void {
350        assert.deepEqual(parts, breakIntoWordSpans(original));
351    }
352});
353