diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy index 74c126d0b2f2..3842ce8badd4 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy @@ -2642,4 +2642,10 @@ class Abc { myFixture.type('\n') myFixture.checkResult("class Test {boolean}") } + + void testPinyinMatcher() { + myFixture.configureByText("Test.java", "class Test {void test() {int \u4F60\u597D = 1;nh}}") + myFixture.completeBasic(); + myFixture.checkResult("class Test {void test() {int \u4F60\u597D = 1;\u4F60\u597D}}") + } } diff --git a/platform/util/text-matching/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/text-matching/src/com/intellij/psi/codeStyle/NameUtil.java index ac81b7e88f51..9c99e78a8e90 100644 --- a/platform/util/text-matching/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/text-matching/src/com/intellij/psi/codeStyle/NameUtil.java @@ -320,7 +320,11 @@ public final class NameUtil { public MinusculeMatcher build() { MinusculeMatcher matcher = typoTolerant ? FixingLayoutTypoTolerantMatcher.create(pattern, caseSensitivity, separators) : new FixingLayoutMatcher(pattern, caseSensitivity, separators); - return preferStartMatches ? new PreferStartMatchMatcherWrapper(matcher) : matcher; + if (preferStartMatches) { + matcher = new PreferStartMatchMatcherWrapper(matcher); + } + matcher = PinyinMatcher.create(matcher); + return matcher; } } diff --git a/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinDataGenerator.java b/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinDataGenerator.java new file mode 100644 index 000000000000..8c658e07d1fa --- /dev/null +++ b/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinDataGenerator.java @@ -0,0 +1,145 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.psi.codeStyle; + +import org.jetbrains.annotations.NotNull; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +/** + * Generates data arrays for {@link PinyinMatcher} using uc-to-py.tbl as the input. + * "uc-to-py.tbl" is "Unicode do Pinyin table" created by stolfi + * + * It contains unicode code point names and the respective pinyin readings, like "4F60 (ni3)" + * If you have data in other formats, you should update the {@link #readMappings()} and {@link Mapping#parse(String)} + * methods correspondingly. Other parts of code are input-independent. + */ +class PinyinDataGenerator { + private static final int LINE_LENGTH = 100; + + @SuppressWarnings("UseOfSystemOutOrSystemErr") + private static void generate() throws IOException { + List mappings = readMappings(); + List initials = generateInitials(mappings); + System.out.println(dumpInitialsEncoding(initials)); + System.out.println(dumpData(mappings, initials)); + } + + @NotNull + private static String dumpData(List mappings, List initials) { + Map encoding = initials.stream() + .collect(Collectors.toMap(s -> s, s -> (char) (PinyinMatcher.BASE_CHAR + initials.indexOf(s)))); + + Map map = mappings.stream() + .collect(Collectors.toMap(mapping -> mapping.codePoint, m -> encoding.get(m.charString()))); + StringBuilder result = new StringBuilder("DATA =\n\""); + int lastCodePoint = mappings.stream().mapToInt(m -> m.codePoint).max().orElseThrow(NoSuchElementException::new); + int curLineLength = 0; + for (int i = PinyinMatcher.BASE_CODE_POINT; i <= lastCodePoint; i++) { + char ch = map.getOrDefault(i, ' '); + String charRepresentation; + if (ch == '"' || ch == '\\') { + charRepresentation = "\\" + ch; + } else if (ch < 127) { + charRepresentation = Character.toString(ch); + } else { + charRepresentation = String.format("\\u%04X", (int) ch); + } + result.append(charRepresentation); + curLineLength += charRepresentation.length(); + if (curLineLength > LINE_LENGTH) { + curLineLength = 0; + result.append("\" +\n\""); + } + } + result.append("\";"); + return result.toString(); + } + + private static String dumpInitialsEncoding(List initials) { + String encodingStr = String.join(",", initials); + String formattedEncodingStr = IntStream.rangeClosed(0, encodingStr.length() / LINE_LENGTH) + .mapToObj(pos -> encodingStr.substring(pos * LINE_LENGTH, Math.min(pos * LINE_LENGTH + LINE_LENGTH, encodingStr.length()))) + .collect(Collectors.joining("\" +\n\"", "\"", "\"")); + return "ENCODING =\n(" + formattedEncodingStr + ").split(\",\");"; + } + + @NotNull + private static List generateInitials(List mappings) { + return mappings.stream().map(Mapping::charString).distinct() + .sorted(Comparator.comparing(String::length).thenComparing(Comparator.naturalOrder())) + .collect(Collectors.toList()); + } + + @NotNull + private static List readMappings() throws IOException { + List mappings; + try (InputStream stream = PinyinDataGenerator.class.getResourceAsStream("uc-to-py.tbl")) { + if (stream == null) { + throw new IllegalStateException("Please put uc-to-py.tbl next to this class"); + } + mappings = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8)).lines() + .map(Mapping::parse) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + return mappings; + } + + private static final class Mapping { + private final int codePoint; + private final long chars; + + Mapping(int codePoint, long chars) { + this.codePoint = codePoint; + this.chars = chars; + } + + String charString() { + return BitSet.valueOf(new long[]{chars}).stream().mapToObj(bit -> Character.toString((char)(bit + 'a'))) + .collect(Collectors.joining()); + } + + static Mapping parse(String line) { + if (line.startsWith("#")) { + return null; + } + line = line.trim(); + Pattern pattern = Pattern.compile("([0-9A-F]{4}) \\((.+\\))"); + Matcher matcher = pattern.matcher(line); + if (!matcher.matches()) { + return null; + } + int codePoint = Integer.parseInt(matcher.group(1), 16); + if (codePoint < PinyinMatcher.BASE_CODE_POINT) { + return null; + } + String[] readings = matcher.group(2).split(","); + long chars = 0; + for (String reading : readings) { + reading = reading.replaceFirst("^\\d+:", ""); + if (reading.isEmpty() || reading.equals("none0")) { + return null; + } + char firstChar = reading.charAt(0); + if (firstChar < 'a' || firstChar > 'z') { + return null; + } + chars |= (1L << (firstChar - 'a')); + } + return new Mapping(codePoint, chars); + } + } + + public static void main(String[] args) throws IOException { + generate(); + } +} diff --git a/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinMatcher.java b/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinMatcher.java new file mode 100644 index 000000000000..a5a9695cdd15 --- /dev/null +++ b/platform/util/text-matching/src/com/intellij/psi/codeStyle/PinyinMatcher.java @@ -0,0 +1,306 @@ +// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.psi.codeStyle; + +import com.intellij.openapi.util.TextRange; +import com.intellij.util.containers.FList; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PinyinMatcher extends MinusculeMatcher { + static final int BASE_CODE_POINT = 0x4e00; + static final char BASE_CHAR = '!'; + /** + * To generate {@code ENCODING} and {@code DATA}, see {@link PinyinDataGenerator} class. + */ + private static final String[] ENCODING = + ("a,b,c,d,e,f,g,h,j,k,l,m,n,o,p,q,r,s,t,w,x,y,z,ac,ad,ae,ag,ah,as,aw,ax,ay,bf,bh,bk,bm,bn,bp,bs,bt,cd," + + "ch,cj,cl,cn,cq,cs,ct,cx,cy,cz,dh,dj,dk,dn,ds,dt,dw,dx,dy,dz,em,en,er,ew,ey,fl,fm,fp,fr,fx,fy,gh,gj,g" + + "k,gl,gq,gs,gt,gw,gx,gy,gz,hj,hk,hm,ho,hp,hr,hs,hw,hx,hy,jk,jl,jn,jq,js,jt,jx,jy,jz,kl,kq,ks,kw,kx,ky" + + ",kz,lm,ln,lp,lr,ls,lt,lx,ly,lz,mn,mp,ms,mt,mw,my,nr,ns,nt,nw,nx,ny,nz,oq,ow,pq,ps,py,qs,qt,qw,qx,qy," + + "qz,rs,st,sw,sx,sy,sz,tx,ty,tz,wx,wy,wz,xy,xz,yz,ach,ahk,any,blm,bpq,bpt,cds,csz,ctx,dst,dty,eow,ghk," + + "gjq,gkl,gqs,gst,gyz,hqx,psy,qsz,sxy,bgsy,fgsyz,fgqsyz").split(","); + private static final String DATA = + "6]*025-\u009B7225)\"6,'##7\u0081/220\"6#$2#$0+$6+6\"22)'6\u00A67))&'##+7]-4$47U+)/&6@--))3\u009C6-747" + + "(&\u00957//0('OO66-\u0097)0655'$--2-2)-)-2--,+-156&2-m----m7\u00CB'++6)+-6722%#6*66(04)22''65606\u0081" + + "34*3)(6#(,-5)3+()60\"65$+$411)-4621+$7)/N\"7))\"1#&2+-#7237&55#(310'r$$+6##226,,1)#607/44))6&$&70" + + "/6$$465*6)!4)&&5)\"#&376(u6S624S#652P+#5547#5-\"'--5\"5+720O\"2\u00CB/62!7Y(,$7\"0\"2#4$7766H7(\"32\u00B6" + + "\\&7k-3-\u00B2)640-*-/((+5'6\"&,)_\")(('03)#62523*7k+6#*'+62,756!+,%+Y##5'761)5)7+-\u00857S0*#--)4()#" + + "7##0+)2323\"-(F365#%05**4\u00866&+70+6()52/2&5+,/\"\u00B3\u00A95\u00B2563##-6+++2)5&()5/)\"P&&6!\"\u00BD" + + "5\"##7\"76#+4+#7''\"322,$3)#5/P(603'\u007F)5#)&7*)7)0-+74+2+($7\"4)-#)76720-6#06-7#))46\"134/6&34%\u0084" + + "#2*$7#3\"6(67066)57#&\"77,)655O$S7.33\"7+)4&#k2#25&61+16',\"$3()520)##2\"566324&\")$73-\"#-7+#677/2!S" + + "677200#2(706$5+\"/)++,0506$7520)37/5+#'+0$#47&(#3$\u0085)2&5)%))\u00B7+\"'525),6))0/&7!26)-26$)5*)#$)" + + "27-\"!13##+-)0,4-0-#+++*\"$\"7726(0#+34+##12(++7-36+-`46765#755'$*$\u009B3S%$%)32662\u0089$0$&,5$C)+*" + + "14-0+\u00B3\"'+5-+'3'5\"\u0081)$S-6)2)6)#),1-6,'1#)#7'),7,'5,,165*)-6,2',776,*-&5,\"$3'e\"(#)(*6+/&,$" + + "5+5))2,20'72)+\u0081$+$')6#!+#,7#2$)++-5$)&&&&)#-&--&&/&*(*'$/\u00885*o>#)$((7$$$11#&06)*0##4)$5(4)+6" + + "++7'#�)2,+7/\"))F+2\"#)''$#**$%72\u00ACO#*)'#'*$)3)++76#5*+0##')#+3&/#0#7'4\")$0\u00B37))\"6)(2)$$4" + + "'&2)'7*#)#\u00B7++&2/*K'0)(77+)/+')'))3())6)7##,+7+60\"')4,+)*57$7-)0267,+)++)*645,*)+(2*)(\",#+66,*5" + + ")0+\",++*,$55*46542+,+/2)00K0560&)3)$5,55++#10\"G6)\"'46--''\"#-5/)3'/!/&'$)0\"(\"-Og)67)*)*(50&'0S*&" + + "(6'*($*++2$)05\u00A8\u00A46!6\"-\u00A4250-2724(\"254(54\"S75\u00C4,-I)\"\u0092\"*\"\"7\u0088+6+5'45))" + + "4@07,642)0+2\u008155)04)%05-\u00BE(%3+78+666277/-*67O/3+2(37#&6O656+)\u00B2$#)\u0081!'62+8++66622+000" + + "-+$572OO2O!$6#)62&2'\"&122702\"5)/2)62$1#*'j+'Y*7)\u00B4\"$*3#260/\u00BB(23#+$)-(,\u00BB,K'567i)$#3,(" + + "+357|6+!,.56)#+36&F00)/e\"$&%(\u00B6u20(7644#-#5#$4(w4'6)+%',90#4'&)(#2-3,6Y.+\"6'-04%20/4-,+16$7277+" + + "60/7pS45\u00BF-5/652(,$0\u0086'73$//\"&A(7(()6&$74*'k7\"+$-725(0%%'7[6+7,,76)7\u00CC275u(*(35%55k6+6!" + + "/23(|$4u76$/5!'*6$5\"}-}-*$-)-,6(6+/,'\u00C9#2+-7(*55+\"77+\",+2&\"(('2'66''\"(2#6!)35'+537,#\u00A076" + + "$0$0,-'$-++27(-')74&6|0242#%+0!)6-63+253(!7-*772$(+!55344#)(003$$47\"##(607&+5/2+70'/727-'+6$0P\"$+5-" + + "3#3!)$*64-267+)((]7#*\u009D6676\u00A5,(6#(((5()*7425($-5+62#06\u00C4/2+6S4,6/-*56)+*#(36(=50262(5@2,#" + + "(*Y2#\u009D2')/402'7)+442#(2\u007F(20-(-2-'-$!-3\"!!+#7,2\u00B43$0)#)*32#)-5/+'j5(('.57#\u00B2/$,,(+$" + + "'36\"6-),5},1S/+5)7S*752(d+055#$v547/#*#7#$63#)650(+\u00B2$(6/)05-+266$7.7)-}(0%762)6!6\u0084*6/$'5$$" + + "-2//67-$(3w1(|6$/#))(3#--#3+(\"6-6(,(7++--?,6+++,$#//5(,5$*6#61$+35)#((7-?#+##+6+-725-)77+----4(602-\u0080" + + "(56-33Y*6)/6#((6%'*#434+')1+''3'36'6(/6(6+\u008160'#46\u0081*/66%\u00CE333+(6}++363326+-67\u00B8'64'/" + + "6$007\u00B4$0--*#\u00AD-,))77\"530&\u0085*$&&\"3*x7*\"5$))*$))3+\"4&7//3*0373'/$4-3/)6&!+0,*'5\"I#+7&" + + "(7#++++!-/-5Y)*+##+'6($7&'6$$'#66&'6$5*22%-$(6*$-$*--!55}\"/\"66(5##'!/&06))$,+5#2)7++F#-\"25')6-$6\"" + + "\u00B9)2F#4)+7*7$$3!#2\"*7$676/)702)-~*3*-)])'6aF'3+-60-!#T-3#6(\"+'$7(F\"6Y,)1:'*76(%66\"),#$3!&7)7(" + + "'#)-+'(+$45))*63#6*222,Y4#3307+/\"27$34#5'7!'6*3645+-+#/\"#++.0,,722+#,\")#2$7*6$#7)'0)$2,#6Y700+-707" + + "522\"/*$&0,$$772T$3\\,&(3$6#-!0)0*6/\"$)6653+)x$105+,(*6$(1-+*+634x++1++1#56+\"-21-7726,\u008877((*6(" + + "5*2,7267'#5&\"-\"20+&7\u00845--5*546,2$$60-''0,,6(#$733&'66B'2H336\"6*j$-*6)\"^+($6/)\u0081-&5&$-*7(\u00AC" + + "*2\"6)37\"5(&$2\"$!24/!4!)+$6)2&(\"+#\u009D-$-0)3)-#(5&)21&4(7&,$1&)6547/$)*76)6,/#67-6-5&\"63&6&46'$" + + "\"-777$-6357%,,0\"20%(5&7-\",&+7721260)'2547)2/163)2)'2*))'\u008E))6-7))5(')*6,+/666#56#'0724(4+61)+/" + + "52+#5,-2,4*+#$-*-6-/2)\u00C57($7%/35\u009B464566264+5)0#057$#+!%%+,#/)/#+4\"520(&413&-)3-0)()0$5(4+\"" + + "6S#&)+@+*66-+$5-(6#23664-#)356431,$10-40#,&)$57,(,!65-4,670\u00B053+,12/44)(!-\"53'76/56611#+,/!,'*0)" + + "276#6,6)2-5\u00B6/+-\"!//6/6+5,67*6-+$'6)7##y-+,7((!-0-\"'4037,55,++('$75-(5(156#),&&564#&2\"220+\u00D0" + + "--$6#!--,3#)#6/-5-636#--6,-,25-$+6+62+)-+56220,++67+7)))*677#2&\"755,23\")'-5-#(+2-,#)2#67-&7+5\"1---" + + "6+,-13'7062!32416(6)7,'$(7'7$\u00B96\"22#2*526(6325'#0'577\"(65j2#1(,**\"\u00B2O7)6)6,*0(7)&-\"(,0(62" + + "-)-76\"*-0,#)'0(4+2-7245*(+)(66\"0#\"&#$25$+$2/&7&\u00B3*\u0081\u00817\u00B9752$$5)2%%%')2#226'#+55-\u00B9" + + "\u00B96++6\u0098444'6$*7)''''''26#*-)\u00B9\u009E)/#5\"))303)4$22F)5#5-75-,%+/3&\u00B453++5#+)5))+)\u00B4" + + "5#\u00B7-245+%--+r014(26#20-6\"6!64)%)0&40#00#)0'5!+$\"776)'*'5\"+306&5)+3/6$*60(/,!3+#-$-*5,356-(*+%" + + "&5$++%'0Y6,2!4(\u00B4,+)3*6-5+6\u00817+)%%66\"00&&-+65($2#3')(56\u00B9+*++50*##3-()+0,**7'#6@'+++)$#'" + + "6$(74\u00BB/62)\"7)$7'677(646&0$367276%7*+6,'))(32,\u0088467+t6647#21*060+3$54#$1)!+42074\"$#06-#)--2" + + "7)+-#$#$Y+777!#0077$$56\"+5#\"0)6+7+++)$$7\u0081'606)765-666%5)5*2$!7-61$+7666-)+\u00B2++$65)#6*64-0#" + + "#+$$-666-6#'#7()5##+'70)'-4--#00)62\"77|6)5)-5)&7\"2\"$2&-2&/75($473$,//3&+77\"7$,66/0)12$7207205\"$'" + + "I/724$4#207',$(75,44&6\"/-'/(Y,)3(72,,\"'7,\"7)#&7(&S\"\"-,0$&,\"I,#)5+'/-)\"\"5'6(66);/37;7,0\"0$#'6" + + "\")5+4-*6$/$6,'#&3/&567375$753'*\u009836\"\"#+\")!2*6322066,2#5&)((+\u00B2++2)/0))\u0081!*+6+$+6##325" + + ",84&;-'\"05++++-6536+36563$/)(-('-*\"60\u008F&)667\"66%22%22'$6(&(43#0\"2$7)3&$,5(#-)76,04215)$7)\u0081" + + "\"Y\u0081\"\"2Y)'-&\"*-\"5Y*\u0081(,*4)))'$++3(7((6666((2573666##\"$\"/6/76##73)e764#\"$+&47#4)$55(6(" + + "+(4#75)3#-+#$/5-0#7S7+65))O)\"(&54/6457/#$77\"$##)4)(,+5\"055\"6+1$$')11#333'0$#74,5&63,,7#4)456647\u00B4" + + "*6\"7###330-(5-455*(*&(324.##)6\"#,/776*\"--7/\"3(()$+27$$636&)/56-'&5\"6057\"(5#/553-7$--6#\u009D525" + + "+(*,75+3($(*'(5522(06((#)65'+(75#5-(%\u0088Y3'0506/*$(a-36*#-6,66),*0666)5\u00AE+3((03\"60(5\",6(20#\u0087" + + "446++(#66+--a0504,#&\"$##,+)''5$0*3+5**-0#$'#)46))+6((0633-4#((5#54(a17)6$)##$\"0#$'$-657$(#015#\"(73" + + "0#\"54'0466\"5(,\"6,6\u0088$6%#,0*6!06-'672+&-**0'622062(-')#35*76#22\"*65(66+236#503(62,-2#/,,'#####" + + ",\u009F73!2,'07)(*+.2)6+243,0760*$7+)006/+76#73#00/\"\"#)7#+/*(0#6655$3$$$2)#5&&++#(05,)+4#)#532/6#5-" + + "$3)2()4($000#*56!,6+2)(,+!+6'5#66$,!,$0,+,#7--66\"75*6&+,#-#,+(51#))(\u00B46+-,3)'s7'64)\u00AC21|#4)'" + + ")0(07$0)$#))O*)*'$7N'))6)6+|75|#$0(((%2+,(+&2F$)2662(&622#70+/F$1A-737$k6*(2##'*4307#*,26-\"#150F)6&!" + + "5/77%$7#)6*\"#)4(6)\"07764-627/3$*\u00B4/&/\"!73*+0-(\"\"7/3//36776\"(-6$#/7,,O6#0,#)A77$#,-+&/\"/+-'" + + "0)3\"33\u00C0)7/7\"\"$-)*+)06+-\"70(k2)7-''0237*#5#(/\u00BD2-\"#'7*$$70!\u008F7')*$\u009D3+7+$4)-)7+6" + + "\u00BA3\u0084-$)7)(5-!3-#\"'37#22*,\u008F)/)632-4\u0084#&)4))3*(37/+\"(2-)226)\"(\")67+23+2\")($-40/2" + + "+,,&\")$4!)67##)3\"---74\u00AC5#$2+0'$2$/$7')300/20+66)7+'6(2$+#3#\")3*36#7)30*\"\u00A7)+'--7X-O2'/6-" + + ")7))66*-(1/4275,\u00C7-#27762(\"6(67!\u008464*#)3++#*))3)('#2X5606#7\"6--+40#'+7')'060##722\"#1F#2*6$" + + "7-5)20'522),%#-23)3/\"$+3(74504N#7%5-0#7'4%2'22\"6\"232#2+##'\"&2$0-7+##'+++7q(7#3(#-,)'67!7#,2*2237," + + ",7O*\")6'0+)6)//+$51*765##2-(2(($7-+7(S))#$X#\"#)5+\"&0\"S773/0$--5+)#3(0\u00BA)'6+*+277/#)$2#0)()0*$" + + "5'/\"!)6--2,)37$5+#)6166-()\"-'7)*,)5+3\"2++17/6+22S-5)(++(6++00S0+26,1#-#52+),+S+37+$4$j)++-7''05//2" + + "*6''''\"&7\"$*,4''#5,#'$5),#)2$6#!\"5)$+-\"P$$6'2*6$0$5$))65v2!0!7$7&2+055)-07\\+\"+5545\u0081\u00817" + + "\")7+&\"\"+6+4$2+)(5)67)43$)#6&07\u008177$725770+7#$7&5(\u00B92/6-F07,+//+&&5))-776+2)-607&/&7'26\u009B" + + ")))(1$)775355'+'(3$5#2*624,,3#46\"!7\")*2(&('#5,(&0(65567&32)67\"565/7+#(,7,\"5(77226&$,-#4$!\"!7+5*3" + + "S2((5*\u008B))7)23(6'52566((()45*75O2\"774(((#43777/\u0085526500)'767!4++#457-5'656(&,*(6$420,-)-!6#6" + + "2/,)*'4#0(6+!)',75(,,#-7(F(5#+5$)/+356)*$66+335&07(6552)\")-!612,56F+#*$-6(+51+-++236#660\u00BD'7((2#" + + "#2,SS37#5u60&F661/\"&+&0--327++\u0086,(43S\u0081\u00816743+-,+,$4,\"77\u00B4-71\"/$$$+0))\"53#2-7006'" + + "4#25&47+5##1G7$7,#6''$602'3---+2,6,,26(&\")$'\u009C5##F2(5M7#2\"2)66'),/\"4!&&6&-5(6$576+1%,7'\u00AES" + + "6-$27-++)#20&-55*/357'5))jA,6622-\"Y6+\"-+(\"A7$#6&\",'011,727562j37--6$77S$'-)!A)\"$*-7\"+#727/2'S6#" + + ")27+,-1\u00B4-\"77+$+-\u0095+625207\u00AC+R57+2k*\"1\u0084\"1\"7#6#57)7%%6&'*+7+-6('7#'7+&)('3'4*1!!)" + + "67*70322())5$767-6--7617$00(i)75227\"3*)\"\"&13)5++&04)'#+036,\"+/7$537!'\"$(771\"')(4-)3)5+*2#&2,4++" + + "$#62)35*72#&4)+\"--37++)7++0\"+#0,00#'#$&/\"F(7#7)+/66'($3'4$5�#+\u00AC7&*+777'&�-4'+()6#" + + "))O7+07S6)F)77\"/$#2--)'5$0-*-+7----/2-32$6&44$)7)6\u00B4566#7#\u0085(S4\"\"6(516+6\"(*)*2&53)),,#u(+" + + "+3-66,25567/$))6#X6#4,$))~061(+\u0095-'/-'3+66#+)---5)67&-,+1'))367\"267,2)6)(i&70,265127#63+1307223*" + + "5'0*'2/3'5]-)2'#0#0(,5''7306$)~7-+\"7-50+(60'''3(N2#\"6()((*66'*''#,)$7\u0095+#S+502&3')2+++,+#2*O3\"" + + "+)2727,,-63/7250()#--0-6%5707#/2(*776755$&',4N\u009D++051&73+623#3,)#2))3()-53-17P7&01(#k++'#----)$-+" + + "--632)3+-652275#')760/6+&($)2\"\"$#7\u00CA)))07)0$6\"22+\u0095#,633,0-\"()0\u0097-6'~6%060,7j#)*/$#-," + + "67'0++2+-#+,(.+\u0086'$6\u0095&72+-#-7+6+7#)%2(-6++-5-)5+6)6665-\"#+)224#00--6++7+$)-++7+\u007F\"-6+-" + + "0#(5660.5##0*6)5556*+*25:\u00AD0(#0****#2-6556056'43).(3(5/55(\u00B2-+#6*6#(77#\"40\"\"4)0#2#2722+#6+" + + "'$$2)7,,6,#632$2552#)/00206+6&\u00B46#($)6-64Q\"3)26$#(#6$$)+\"$))2.$76062\u0088\u008865$(('0)6.($654" + + "',,,!7$6\"\"\"//\"#,--/-)72,35%15),(0$-3/)$#\"2-,2263()32+,+31#/+727,+0$\u00B4$,),0/-0$5#&1--&2$0065(" + + "6!6*06$$+0666227\"6$2+-3&'370\"7,#($(#7#4&$53,002/(044521i)#4--\u00B07#0,'40)1)(30)\"\"'47&5)(-0&55\u00A9" + + "6466(6O#$6]((0,1,Y,4#3\"27//77'+,7&.++#&4(,,2)733$(+,6&&6377'762*))506)70F(D\"7#+6'('&,2(/#&72-#+/F\u00AC" + + "2-)672+55&/,36)6'\"5\u0092+$\u00905/7)67)6((7#64()6+2)%5&277645*7)+-!$6,+6,0)/455(52*3\u0081)%71/557i" + + "(,(4\u00AC/40+6))\u0081))727#-u)+#(|-5)+047\u0084(\",765\"${(6/6+(+(+'&4+#&663+())#4,2#/523*/-()52-3R" + + "553%23)#3+22+23$+++4p6($-1)72&'5226#76*4(3$(4)'+(37$0$)75\u00BB0''(+37/(#20&#+-)3#+7/&23/$6-6+',)++6#" + + "0(6-2x#(6+(06\u00813,76,\"641&06*)262+7$-)\u0099/566221(7)-6030$&7\"4p$4415#4''6(5,*,666(,5,7(-*2%/,+" + + "00,3#4#3,5,5)/))(&56672)7(36\",232R)7-\u0081)-6\u00B0+(6-\"60#+#6#-742,6+u-)5+''--/)'3626+6,72*334+'2" + + ",726+,/4+#4\u00AC40#226\u00AE26561(22-3214/##/4#,($((57$7\u00BB&)i'7332\")('6'\u0092762,6#+++5\"365(\"" + + "\"7)*22$,!+|(6#&6',06/)6)\u00AC5)+++)'#+7'0+6#)##3.365,3,2(++4+0&56,7,*\u0093/277#5(u)6O+#36)#6(52'65" + + "--5+74/6)/5()4/)/4\u00B2005+52$(,12+776$4$3#5u-2372(\"2##23/+422I)I()+#'#(22/(6+(&((5)25!++-6+\u00997" + + "$(756+25+,76u#+$6!(+#,$Y62/)30)7+-')&2)2(#32$27+\"+,22,-6\u00BB,)0\")(1S4366$#()+)!/74\"'05\"*&-\")Z+" + + "+++66+2)6$4(5/2\"#,+)F2#'F(5+0(61+)56245((7\u0092+$&(+--6,)+)6&+6)6#$1)+&267&2++#060&'06(-27+6+,$3$)#" + + "-(\"7++-4+056'66(\",'$(55-(+77)75#777#607&-j4/6+#/*/6*/,#+m*$'57'540\"$577*7&\"$$+75)3F)/33\"6Y(77$42" + + "+#/-(2+3)550+(6555647624337*(+5757/6('7(*-&26(-3)1-5&)#/\u0083734(/+2((-2+55)556(7\u0081Y504--(6(," + + ")Y\"&+*(#5#\u009B()&6)#&/0#505S666)6'1/6-2#2----#(*7$6(&+55())\"674335\u00A1-#6))6,246501,(574&026+7-" + + "''\"(65--\"433#26\"(55456((565-*-65,+641--0+5\"\"#+)26+&263)76(67!4+(.1),-2#7)55565#(#6016507$$2)&2+6" + + "+32&&65+,36),--6665+37#250#+(75+4657(--+15*5)#Y6(+\"1+,\"1$+!5*2-++)+655+6-\u00AF6+#)3'-#,3+7++#67+/7" + + "/76!4-))&6\"$6672%\u00C2#*770$0/\"/2)/$633\"$\"\"\"6-$6#-#/),3,+1,&,,146&\"2)'6'2,$000735,*04'5++/)'7" + + "\"01$))\u0081&/*)V#5\"+),24+$32)5+$+//\"5#4*#00\"&0\"##<)7',6*\"(6((76*-$076\"/)-2/53(+&/-26'6)$\"'5-" + + "(()v7)(23123+$52*7626\",5)+562+\"762+75)(&6F0-\"6++)0*6'7,#6776,##2+-+(7(4&4657,46536-|)(\"66,#62\",(" + + "62,6$62(-67#(,)),7#!!(#\")\"\"(\"+636+252-5')$(*55355-\"(-,+-'2+35,1(-+5005,7\u0092+6240'$+\")($#')60" + + "6R,(4&\u009B)6A\"\"6)6)4),$/4(50+$6!/$&55\"#')2/#*12267),2+\"77)&+)))+'57'6565+270*5\"%565('#5\"/-$6(" + + "4%#Y44#),\"35#(5600++5&+65++)+22-4$\"7#,6)#+424$#7/#(0%*#0\"4+#'6$\"+0/F070&-0$)(6,,#535$1,741(5#)76+" + + "05$66-(66(12+-12644))6,3+3++'30#)76!\"3#*7#)6##0+6205!+,76-64+4$-750$++02('/)&)+)-)!\"#07$)'3((223-6)" + + "&\"247+5)51('+$+71+707'2++++7+6,55'$7('\"$/(7/\"1+4-t\u00AB\"/&$4.---(+6/#-)##-$,\"#/\"77-#605+$.,7\"" + + "+74/$466'$233(#202##122262+&6\"--36)27$&-$/Y(Y07,\"0+5+#,6&&'3))04&3,-/)4$-+\"7Q,,#-'\"$7+\u00AC+/-e(" + + "66,)6+2$#($#)4)##3+)#+$3+))#\"$$\u00D1-$2276#-$\")+'')7525\u00A2+6#6\"))55#\"6+7#&7//'*#50$7&73))&)$)" + + "57\"-76)0#36)4($6#7(6,$)533,/52/+7#$42+2(56/7'3&,+#)3!#\"\",'$%46#675$27\u00866(&+6236'4(*\u008466+2)" + + "#5'64)#\"++#2\u00A2$$\"37\"2#+67#77220$++,)66(&++0++5&$6(@\"5''-6466/+\u007F2$+$++\")#65)7-+(+)$56606" + + "3$+++\"-'/&$&\"\"0\"77,$/)('#+',))/'!%((\"{#05!)(((7#(56/()!5(+/()/'/7)0#07'))77'7$,066\"77/(6(6\"4(!" + + "76)(6*&'$/&0O$+7,+)5)/'!+57$!'+,$'5,,70435$55/&X,,\u00B226,/&,$,,*5*26762($7*)262,,777,$6$677#75\",+2" + + "3,$6%,5#*),7366,7,77,22(($##)%455*+)23(4+20+@)7++2)22$/F,(-+')#76(,55('-#),$(53*'1,5&4,#*,4*$#*250,,," + + "2776$*,2#+#,/#),(1/5\u00AD/7$22+#5*6534+*)6!(7)'7\u00814#)-56(,,F,+')5,(+,+',5#3*7,\u00CB+62#)2627(26" + + ")7)#$!)7(FX$0)7'43*05&*$,2$)+&,-|*70*)&%6/7627#$/6-&&,706*33$77%&,7+\"-//+/+/\"/27!++3-+*#*07*i%-)+\u008A" + + "!l*56$/5-(250-40-*50#+(655,+-##4+6,06#*6--+#)-27*/67*#070+)\"$,$)(+!20+\"6$40+4$'F0#16$$73)6\"*\"427$" + + "5$3-/)$3#-0-&500,'-2%#+23F(/42+#355+/46$7*+-0'7#0!/++*0#6+\"0,0#70#-)2+07$)5+$$(/70$+))570$)67((7+*#)" + + "0$\u00B9)//6/0!*)61,/7\"-,#5k++7++&0/6+++,\"2'+7622+126203,565\u00AE07\"2#-62673&&,772,70(722##\u0097" + + "+6543/7'57\u0086'7'2)7j*$$(30''7++\")$7+O\"7(6567(7&645636,2$-776)'3#,3-5065)2O5(2+-\u0097$+1637+166+" + + "50(352137#'65\"-00S&(6*,7)\"76\u00C1*\"/-+67/\"+,#-067772)73)#37((677)1$67(-&5*+&72+*')3#3226++'717\"" + + "\"\u008177*+/*\"#762--65\")&\"-)S75#$4+76)577$)\u0081'''12-)*,2,7)+\u00B1)6402-6(0)25/)73-+2-2(1-6-)3" + + "4#('+\"-1)+754)050*62)6#73+076\"\"6\"67)0$4'67#63)#)5#*#4$**752-*$-\u00BB4466)0663+63$)+54*#)-*+##/7#" + + "00$770+#n&\u00CD#(\u0081\u00D6n\u00D52,)77++\"))7\u00D4\u00A9)(32)$62)0)/$27#$#()*)77+/6#',7-$)5\"2)7" + + "72676('5#/\")6$225$7-#'+0,\"32&#\"&$7$+7-&'&)'&2,/-)0+-\"+'0#665\"0'$))021&*73)$(#7*+\"2$7#&\u00853/+" + + "+)')(357#2277523K6'*'#*'6-05)/+7\"\"\"'#'6)7'#7027+\")+2)&7'*00)#'6#)\"703+$51)-\"255/72(\u00B376#&4$" + + "2))(5,/&7(0(0,0-*-+6(36#'&17'-05#'/$+\"7#2#70++)\"+(\"$#6/2#//$6,7\u008D5'6(#*#/7)'2+7+-2#-2+$+5\"" + + ",2$+$$&),*$0$(2+75+27-/0/')$+6\"$2*'0+\"7+-+*66(733,#)-0377&270*3++)366++-++0670+\"$7+2+667\u00BB,$&2" + + "72-5+57-#70-\"\"42*1&\"O6+#3-\"+')/,#\u00A37+23+52(3S#6\u00BD+7\"-&,0-+5&+#j+6+)0#\"#+7)'-223\"1,(57(" + + ")7#+5&-\"r5'30-#73,2&7*),22-#+)*\"(27)-3-+7$-3+,,)\u0084'7)6)#756i6i41440-73-&)2#/62(7)&61$)2&2#)7\")" + + "&707#(7+5&52\"70+72'6&37$#2757)\")/27*)1(5)7#'\")*(#''3\u0084*)0'+5F5&j3136+505($32)5()7))#,7+#02\"35" + + "40'5Y55(5&32$*&)(76)&)5-7+$+++#02007040524034'4\"7#'#l+07\"#+,0)37'7675+)&1,67&+5-2-55)*51,\u0081$7$," + + ",65\"20\"('7,4&46',)+7F663'76##$)6752-'-6)67-\"'/7)#02652513&67'1(7352773(#\"&#+2657+70,7+,/+,57)22e2" + + "\"62,\u00BD0(5\u0084-515(077722+6&+#7)1#15((750-$2(\u00842))(\u00AE#)\u0086\"#6-2625)\"0~/570/+,+57*6" + + "5+5#-+#6#5577+5$+++,)6i7\u00ACi6)4*)146(#/2'-17l&74&77-25'5&+725777\")$\"1)*1$((j5)+))3'5)5523)Y)" + + "5+650'24,2\"#3+0774+77*5),+3,\u00816(2$$F5'7($+\",6)&17&#'#+6)\"/,+62,25+27)0\u00D2(\u00867&5'&0&0" + + "\"/(-'6605'73-046+3+'4'44(-+&,&'7),','\"'3)&\u0092677'767!&+22/,+F&+#4\")73+)),7+F))+6,03,666&\"'6'07" + + "'+67$50651000(2566056')365&2&2++'-0#6'6#4&(###e5/6+6/++705555500((22()]#&32#7)52/74(((((!/6+0-+/0!&6(" + + "5$6+-*,70'''$$%21%-]+37'#(6F/#20))(#++)3.+-)/7+)+(6,(%7$6$206#$$('7--$7#+764++7-3%6$'-+(2+/))\"$'45/#" + + "--36#*+*#+4*++#!223*-7$--)33+667226227716+)0*#'$((615176$'1'#4#'70&&\"//)&76-!*1'646)/055&*)32775247$" + + "$&\"\"03\"'37*7-/7&/757/)27\",0(*6656+$*+)-6/*6'i'$7)55%!5/-7-#37#,5#5,,)5-*270-,-+4\"440))6(#+23,#25" + + "-)#553/#-e$3--/'+++7#)+2/\"+/')S$3-))\u00946@12I&&)&04$/'7$4,1]7#l.$!5-22-671%236)4)6)$\"#&5-,433F0+4" + + "2327'6\"+)/5'+\"-#+'/#\")&3,57+)6+75#+3/-#+#'53&7)2(#152&62'$*-3+\"6)#6)\u0094+23'0#\"5\u009D(75\"5*\u0094" + + "6+(7+07+-7#04p7+'7)-Q)'Q,-77')$7537)56#66#55)665))5222)23223$//'(3#2547$#26-/3&\"#(&F\"+7)#+77Y\"5'#\u0084" + + "+(/5-&7&+26+3-4\",-)(27\",$-\"#62##+$-6P-$0+6))(,0++#2'+))26&/66##6+3)@-3))/46#,,'06625$50\u009B7(275" + + "F&344702401&*j+7)006&\"15)((&4)'760!#,\\&1(#66\"6-4+/%5##\u00A32\u00B661+3\u00B0$,0+1*,/\"',66\u0081/" + + "1*\u00A3-\"\"2065\"(67$)$-'(/,&2'\"4&7,&\u0081,,\"S,7$#')+---560',+16'\u00AC##657+4$*#)#'',S))&677)(6" + + "#&11#,37-75(*0'$)5##)%!2#1)\u00B6(/+)\u009017$)1\"#0(\u0081$-1|\u00BB+6\u00AC)26,(76$4#$&16(\"\"6$322" + + "##4\"5'+/7,+7)$022#&),,5)#\u00B2)636#p(6#)46M25+e%,4)-,*++2\u00BA35(666-#,,#\u00B9)$0$)7'++)4)-*(/7''" + + "&+##2#7,#\"+3\"(\"0)50$)/$)73'('+&)!4\"767)+323$(\u0081(#3#\"#(&+0,/4$2(663\u00814#--3)3+--,--$666520" + + "*5\u009B66&+55-74#56F,!%+6(')477)\"15\u00D3!0)&++/&(((63775\u00AF'0),(2/'$704\"4/)(7)$6)#045*3|520+76" + + "6,62$7'-0#**-)+4/-262#267+-,(026+)5F#53+(707/#6#6*///-25&67))1#%,(27,-5+5'+14i#23+125\"6'\"7'-5#-+-)+" + + "#+6-6,$5437/!+#5/\u00A4)#)43#66)+\"+\u00B2\"7+0,6+)F'($2+22$,5\u009B\"$#725\u00B9(!,+#7#/),#-()6)-26*" + + "#(2*0,S70$++*!\"+4)\u00AC2A,.#$\u0084\u008111+60#(),6\"60+1(%3&)7&1&*2165&)$432556420)62+654)(2$+5665" + + "(\"(!4(4)#5+,6+)#O0+*6$335\"72\u0094&$5'52)*(2556\"225$/4-#,1/3\u00817#7%-6'#50&)5*)\"$,+)S,00\u0094-" + + ".52+655+6++)$7/36,(\"&233004+(2'6-+\u00B47!+75#+(3a110(+23,6/65))5,-2)--E16\u00946)++606+346+06&,+*+)" + + "$-++3&74*7(+),+(+)-+)--+056+,\"((+-+750#(5#&55+(6())'\"677*\"52J0$)0$2-$7\u00B36'7t(,'2|#26,5&%/#0441" + + "\"/66)016NP6)(0076(,4&&('7&1)&#$\"5-3067/#6u()+&17'/\"57$\"\"'1\u0081\u00B33+'$'6+#0,'#((,&64+765*)+6" + + "/)i264,00''7,-7)-205+0\u00B26)\u00B0#\"b(25&27&574&++\"#66)$63$3(472&),006)\u0096,025++$33*'(6\"&/4$6" + + "62001-04+'4$%\"74#66'#-\u0096*)|3,5,6)25(6\"14&6,4&156\u00AD,|62#3773&6*,+$(0$\u0094p6)-+#16)3+/25556" + + "4+2\"11)45(06\"(36$-((5,,64636#--,-2\u00B4##$!+473#/0/6)++076)24)477,,'+,5#+,5-7,5,72037//)0\"+/'5)7(" + + "&+))(6#)2\u009D54#52-#$+526)$#0752+06#+75+775,501),(1(7)\"(,&+)\u0096,+#+0-+$57+++&6/1')6-5#00$#,0)77" + + "5(-/-57,%,,2|6*6-+5\u00B453+)56(4$#4$7(066\"'6\"#62#&'&O)-7$1775\u00AE51710))6,#!-(1)3+$\"/67\"23)(55" + + "76/A$4&'771/6,--*5#0F65-\"-&6#*1)\u0081#,)%'17'6#+--7$-**-2)*#+)2/'66#+00)6\"7220+++*)&3F'36+###$\"+O" + + "//&6+'6$\u00B57)0)7'*-32\"$u$55(6\"\"&636(\"S+--63'$(161-)2\"3#2-6)0(*+++\u00BC2+6$554\"#)02\"5-/)" + + "7)7)$7&\"55\"1,+!$(#2-#+\")$23\"+/17-242\"5\"#++55+7$-72)/6-6556&\u00AA--&\"())\u0084'\"6')/,,,,22S+)" + + ",3+67)524536+%$0/),/'07)'$)+0)4)0++2$'\u0084'6',2#+))5$36')0)))#)7#)'$7$2(0'7\u0084''J\u0084(052-)+77" + + "\"5(2'75#56+)56566$&00)()&5$(#35)6156203)56%&662265)5-#675&5#2527|662#(2(5777'777'&)$+$6+-/7'2)!73607" + + "/\"5N\"$737#76556((2#)2(#''0()('5(2#3,7,%(65'%\"Y#+7**463)712+%*%23$\"#6(002!65#)544'2/()\u00B37\u00B3" + + "$-#2)*0#5245$-6Y/###7)03#4)0)77707+)7(+2\"(/6$5/252((%7$5&/3)067#5(6!5-#&766(5'-0,64-372)\"-(('6,\u00B2" + + ",50#\u00A122\"#0\u00B3)655366(6\"#0+,,27,)77++#.'57!!)76(),#((#57252$7-+%6))7)\"(74\u00867\u00B4037/2" + + "577$20)))+-6!7/((6621-073(7(-6)6)($757+24#+6\"76%#4#6#16+#(7(76$76$6)$&1))(31203565)1)(.)6-5%+52&2&)7" + + "'(/725727$7#07\"66*+2'2)(#72($'0'567'5#(57)4604'6(*\u00B32:077-$7&*4622Y#+72326,#$()5564%65#7!6$,/5,$" + + "256\"20,),7),3\u00860+/)607#r0(6)(((\u00AC5(+($+$)\u0088#c$4\"25&77662#(3636)\"(%#5()*'0&5\"(67)&5(4(" + + "\"$7&67\"# matchingFragments(@NotNull String name) { + int i; + int len = Math.min(name.length(), myPattern.length()); + for (i = 0; i < len; i++) { + char c = name.charAt(i); + if (c < BASE_CODE_POINT || c >= BASE_CODE_POINT + DATA.length()) break; + int code = DATA.charAt(c - BASE_CODE_POINT) - BASE_CHAR; + if (code < 0 || ENCODING[code].indexOf(myPattern.charAt(i)) == -1) break; + } + if (i > 0) { + return FList.emptyList().prepend(TextRange.create(0, i)); + } + return null; + } + + @Override + public int matchingDegree(@NotNull String name, + boolean valueStartCaseMatch, + @Nullable FList fragments) { + if (fragments != null && fragments.size() == 1) { + return 500 + fragments.getHead().getLength(); + } + return Integer.MIN_VALUE; + } + + static MinusculeMatcher create(MinusculeMatcher delegate) { + String pattern = delegate.getPattern(); + if (pattern.startsWith("*")) { + pattern = pattern.substring(1); + } + for (int i = 0; i < pattern.length(); i++) { + char c = pattern.charAt(i); + if (c < 'a' || c > 'z' || c == 'i' || c == 'u' || c == 'v') return delegate; + } + return new MatcherWithFallback(delegate, new PinyinMatcher(pattern)); + } +}