mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -191,19 +191,19 @@ class _RegExLexer implements FlexLexer {
|
||||
"\1\17\1\20\1\21\1\22\1\2\1\23\1\24\1\25"+
|
||||
"\1\26\1\27\1\30\1\31\1\30\1\32\1\33\1\34"+
|
||||
"\1\10\1\35\1\2\1\36\1\37\1\23\1\40\1\41"+
|
||||
"\1\42\1\43\1\44\1\45\1\1\1\46\1\47\2\50"+
|
||||
"\1\51\1\52\1\0\1\53\1\54\1\55\1\56\1\57"+
|
||||
"\1\60\1\10\1\61\1\62\1\63\1\64\1\10\1\64"+
|
||||
"\1\65\2\66\1\67\1\70\1\71\1\72\1\73\1\74"+
|
||||
"\1\75\1\10\1\76\1\77\1\100\1\0\1\101\1\102"+
|
||||
"\1\103\1\104\1\0\1\105\1\106\1\107\1\110\1\111"+
|
||||
"\1\0\1\112\1\0\1\113\1\0\1\114\1\115\1\116"+
|
||||
"\2\72\1\117\1\120\1\121\1\122\1\123\1\124\1\125"+
|
||||
"\1\126\1\0\1\113\1\0\1\127\2\72\1\117\1\130"+
|
||||
"\1\113\1\72\1\117\1\72\1\131\4\72";
|
||||
"\1\42\1\43\1\44\1\45\1\1\1\26\1\46\1\47"+
|
||||
"\2\50\1\51\1\52\1\0\1\53\1\54\1\55\1\56"+
|
||||
"\1\57\1\60\1\10\1\61\1\62\1\63\1\64\1\10"+
|
||||
"\1\64\1\65\2\66\1\67\1\70\1\71\1\72\1\73"+
|
||||
"\1\74\1\75\1\10\1\76\1\77\1\100\1\0\1\101"+
|
||||
"\1\102\1\103\1\104\1\0\1\105\1\106\1\107\1\110"+
|
||||
"\1\111\1\0\1\112\1\0\1\113\1\0\1\114\1\115"+
|
||||
"\1\116\2\72\1\117\1\120\1\121\1\122\1\123\1\124"+
|
||||
"\1\125\1\126\1\0\1\113\1\0\1\127\2\72\1\117"+
|
||||
"\1\130\1\113\1\72\1\117\1\72\1\131\4\72";
|
||||
|
||||
private static int [] zzUnpackAction() {
|
||||
int [] result = new int[138];
|
||||
int [] result = new int[139];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -235,20 +235,20 @@ class _RegExLexer implements FlexLexer {
|
||||
"\0\u03e0\0\u04d8\0\u03e0\0\u0516\0\u03e0\0\u0554\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u0592\0\u03e0\0\u05d0\0\u03e0\0\u060e\0\u03e0\0\u064c"+
|
||||
"\0\u03e0\0\u03e0\0\u045c\0\u03e0\0\u03e0\0\u03e0\0\u068a\0\u06c8"+
|
||||
"\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u0706\0\u0744\0\u03e0"+
|
||||
"\0\u0782\0\u07c0\0\u03e0\0\u07fe\0\u083c\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u03e0\0\u03e0\0\u087a\0\u08b8\0\u03e0\0\u03e0\0\u08f6"+
|
||||
"\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u0934\0\u0972\0\u03e0\0\u03e0"+
|
||||
"\0\u09b0\0\u03e0\0\u03e0\0\u03e0\0\u09ee\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u0a2c\0\u0a6a\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u0aa8"+
|
||||
"\0\u03e0\0\u0ae6\0\u0b24\0\u0b62\0\u03e0\0\u03e0\0\u03e0\0\u0ba0"+
|
||||
"\0\u0bde\0\u0c1c\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u0c5a\0\u0c98\0\u0cd6\0\u03e0\0\u0d14\0\u03e0\0\u0d52"+
|
||||
"\0\u03e0\0\u03e0\0\u0d90\0\u0dce\0\u0e0c\0\u03e0\0\u0e4a\0\u0e88"+
|
||||
"\0\u0ec6\0\u0f04";
|
||||
"\0\u03e0\0\u03e0\0\u0706\0\u03e0\0\u03e0\0\u03e0\0\u0744\0\u0782"+
|
||||
"\0\u03e0\0\u07c0\0\u07fe\0\u03e0\0\u083c\0\u087a\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u08b8\0\u08f6\0\u03e0\0\u03e0"+
|
||||
"\0\u0934\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u0972\0\u09b0\0\u03e0"+
|
||||
"\0\u03e0\0\u09ee\0\u03e0\0\u03e0\0\u03e0\0\u0a2c\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u03e0\0\u0a6a\0\u0aa8\0\u03e0\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u0ae6\0\u03e0\0\u0b24\0\u0b62\0\u0ba0\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u0bde\0\u0c1c\0\u0c5a\0\u03e0\0\u03e0\0\u03e0\0\u03e0\0\u03e0"+
|
||||
"\0\u03e0\0\u03e0\0\u0c98\0\u0cd6\0\u0d14\0\u03e0\0\u0d52\0\u03e0"+
|
||||
"\0\u0d90\0\u03e0\0\u03e0\0\u0dce\0\u0e0c\0\u0e4a\0\u03e0\0\u0e88"+
|
||||
"\0\u0ec6\0\u0f04\0\u0f42";
|
||||
|
||||
private static int [] zzUnpackRowMap() {
|
||||
int [] result = new int[138];
|
||||
int [] result = new int[139];
|
||||
int offset = 0;
|
||||
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -287,66 +287,67 @@ class _RegExLexer implements FlexLexer {
|
||||
"\1\64\7\43\1\64\4\43\1\64\20\43\1\62\1\43"+
|
||||
"\1\63\1\43\1\27\63\43\5\65\1\66\5\65\1\67"+
|
||||
"\1\65\1\70\10\65\26\67\1\65\3\67\3\65\1\67"+
|
||||
"\4\65\1\71\5\65\65\13\1\72\10\13\13\65\1\46"+
|
||||
"\12\65\26\46\1\65\3\46\3\65\1\46\6\65\1\73"+
|
||||
"\16\65\1\46\12\65\26\46\1\65\3\46\1\65\1\74"+
|
||||
"\1\65\1\46\17\65\1\66\5\65\1\46\12\65\26\46"+
|
||||
"\1\65\3\46\3\65\1\46\13\65\2\44\2\65\1\66"+
|
||||
"\5\65\1\46\3\65\1\44\6\65\26\46\1\44\3\46"+
|
||||
"\3\65\1\46\12\65\13\75\1\46\4\75\1\32\5\75"+
|
||||
"\26\46\1\75\3\46\3\75\1\46\4\75\1\76\5\75"+
|
||||
"\120\0\1\77\64\0\1\100\1\101\5\0\1\102\55\0"+
|
||||
"\1\103\1\104\1\105\4\106\1\103\1\107\1\103\1\107"+
|
||||
"\1\110\1\103\1\111\1\112\1\103\1\107\5\106\2\113"+
|
||||
"\1\114\1\115\3\116\3\117\1\120\2\121\2\122\3\123"+
|
||||
"\1\110\1\124\1\125\1\126\1\104\1\127\1\130\1\131"+
|
||||
"\2\103\1\112\1\110\1\103\1\112\1\103\1\112\6\103"+
|
||||
"\47\0\1\132\27\0\2\44\14\0\1\44\34\0\1\44"+
|
||||
"\4\65\1\71\5\65\65\13\1\72\10\13\13\65\1\73"+
|
||||
"\12\65\26\73\1\65\3\73\3\65\1\73\6\65\1\74"+
|
||||
"\16\65\1\73\12\65\26\73\1\65\3\73\1\65\1\75"+
|
||||
"\1\65\1\73\17\65\1\66\5\65\1\73\12\65\26\73"+
|
||||
"\1\65\3\73\3\65\1\73\13\65\2\44\2\65\1\66"+
|
||||
"\5\65\1\73\3\65\1\44\6\65\26\73\1\44\3\73"+
|
||||
"\3\65\1\73\12\65\13\76\1\46\4\76\1\32\5\76"+
|
||||
"\26\46\1\76\3\46\3\76\1\46\4\76\1\77\5\76"+
|
||||
"\120\0\1\100\64\0\1\101\1\102\5\0\1\103\55\0"+
|
||||
"\1\104\1\105\1\106\4\107\1\104\1\110\1\104\1\110"+
|
||||
"\1\111\1\104\1\112\1\113\1\104\1\110\5\107\2\114"+
|
||||
"\1\115\1\116\3\117\3\120\1\121\2\122\2\123\3\124"+
|
||||
"\1\111\1\125\1\126\1\127\1\105\1\130\1\131\1\132"+
|
||||
"\2\104\1\113\1\111\1\104\1\113\1\104\1\113\6\104"+
|
||||
"\47\0\1\133\27\0\2\44\14\0\1\44\34\0\1\44"+
|
||||
"\22\0\2\46\1\0\2\46\5\0\5\46\6\0\32\46"+
|
||||
"\3\0\1\46\23\0\1\133\75\0\1\134\1\135\5\0"+
|
||||
"\1\102\47\0\1\136\5\0\1\103\1\104\1\105\4\106"+
|
||||
"\1\103\3\107\1\110\1\103\1\111\1\112\1\103\1\107"+
|
||||
"\5\106\2\113\1\114\1\115\3\116\3\117\1\120\2\121"+
|
||||
"\2\122\3\123\1\110\1\124\1\125\1\126\1\104\1\127"+
|
||||
"\1\130\1\131\2\103\1\112\1\110\1\103\1\112\1\103"+
|
||||
"\1\112\6\103\71\0\1\137\17\0\1\67\12\0\26\67"+
|
||||
"\3\0\1\46\23\0\1\134\75\0\1\135\1\136\5\0"+
|
||||
"\1\103\47\0\1\137\5\0\1\104\1\105\1\106\4\107"+
|
||||
"\1\104\3\110\1\111\1\104\1\112\1\113\1\104\1\110"+
|
||||
"\5\107\2\114\1\115\1\116\3\117\3\120\1\121\2\122"+
|
||||
"\2\123\3\124\1\111\1\125\1\126\1\127\1\105\1\130"+
|
||||
"\1\131\1\132\2\104\1\113\1\111\1\104\1\113\1\104"+
|
||||
"\1\113\6\104\71\0\1\140\17\0\1\67\12\0\26\67"+
|
||||
"\1\0\3\67\3\0\1\67\25\0\1\70\12\0\26\70"+
|
||||
"\1\0\3\70\3\0\1\70\23\0\1\140\70\0\1\141"+
|
||||
"\37\0\1\142\13\0\1\143\1\144\6\0\1\145\1\0"+
|
||||
"\1\145\1\146\1\147\1\150\11\0\1\100\75\0\1\151"+
|
||||
"\1\152\64\0\2\104\51\0\1\104\23\0\1\153\51\0"+
|
||||
"\1\153\27\0\1\154\147\0\1\155\1\156\14\0\76\157"+
|
||||
"\1\0\2\160\3\0\1\161\20\0\2\160\1\0\1\160"+
|
||||
"\4\0\3\160\5\0\2\160\3\0\1\160\22\0\2\162"+
|
||||
"\24\0\2\162\1\0\1\162\4\0\3\162\5\0\2\162"+
|
||||
"\3\0\1\162\101\0\1\163\1\164\25\0\1\165\144\0"+
|
||||
"\1\166\12\0\1\167\75\0\1\170\1\171\1\0\5\172"+
|
||||
"\1\0\70\172\11\0\1\151\66\0\1\173\51\0\1\173"+
|
||||
"\52\0\1\174\45\0\2\175\24\0\2\175\1\0\1\175"+
|
||||
"\4\0\3\175\5\0\2\175\3\0\1\175\22\0\2\176"+
|
||||
"\4\0\1\177\17\0\2\176\1\0\1\176\4\0\3\176"+
|
||||
"\5\0\2\176\3\0\1\176\22\0\2\200\24\0\2\200"+
|
||||
"\1\0\1\200\4\0\3\200\5\0\2\200\3\0\1\200"+
|
||||
"\21\0\5\172\1\201\70\172\2\0\1\202\51\0\1\202"+
|
||||
"\30\0\1\116\67\0\2\203\4\0\1\175\17\0\2\203"+
|
||||
"\1\0\1\203\4\0\3\203\5\0\2\203\3\0\1\203"+
|
||||
"\22\0\2\204\24\0\2\204\1\0\1\204\4\0\3\204"+
|
||||
"\5\0\2\204\3\0\1\204\22\0\2\205\4\0\1\175"+
|
||||
"\17\0\2\205\1\0\1\205\4\0\3\205\5\0\2\205"+
|
||||
"\3\0\1\205\22\0\2\206\24\0\2\206\1\0\1\206"+
|
||||
"\4\0\3\206\5\0\2\206\3\0\1\206\22\0\2\207"+
|
||||
"\4\0\1\175\17\0\2\207\1\0\1\207\4\0\3\207"+
|
||||
"\5\0\2\207\3\0\1\207\22\0\2\210\4\0\1\175"+
|
||||
"\17\0\2\210\1\0\1\210\4\0\3\210\5\0\2\210"+
|
||||
"\3\0\1\210\22\0\2\211\4\0\1\175\17\0\2\211"+
|
||||
"\1\0\1\211\4\0\3\211\5\0\2\211\3\0\1\211"+
|
||||
"\22\0\2\212\4\0\1\175\17\0\2\212\1\0\1\212"+
|
||||
"\4\0\3\212\5\0\2\212\3\0\1\212\22\0\2\212"+
|
||||
"\4\0\1\177\17\0\2\212\1\0\1\212\4\0\3\212"+
|
||||
"\5\0\2\212\3\0\1\212\21\0";
|
||||
"\1\0\3\70\3\0\1\70\13\0\2\73\10\0\5\73"+
|
||||
"\6\0\32\73\3\0\1\73\23\0\1\141\70\0\1\142"+
|
||||
"\37\0\1\143\13\0\1\144\1\145\6\0\1\146\1\0"+
|
||||
"\1\146\1\147\1\150\1\151\11\0\1\101\75\0\1\152"+
|
||||
"\1\153\64\0\2\105\51\0\1\105\23\0\1\154\51\0"+
|
||||
"\1\154\27\0\1\155\147\0\1\156\1\157\14\0\76\160"+
|
||||
"\1\0\2\161\3\0\1\162\20\0\2\161\1\0\1\161"+
|
||||
"\4\0\3\161\5\0\2\161\3\0\1\161\22\0\2\163"+
|
||||
"\24\0\2\163\1\0\1\163\4\0\3\163\5\0\2\163"+
|
||||
"\3\0\1\163\101\0\1\164\1\165\25\0\1\166\144\0"+
|
||||
"\1\167\12\0\1\170\75\0\1\171\1\172\1\0\5\173"+
|
||||
"\1\0\70\173\11\0\1\152\66\0\1\174\51\0\1\174"+
|
||||
"\52\0\1\175\45\0\2\176\24\0\2\176\1\0\1\176"+
|
||||
"\4\0\3\176\5\0\2\176\3\0\1\176\22\0\2\177"+
|
||||
"\4\0\1\200\17\0\2\177\1\0\1\177\4\0\3\177"+
|
||||
"\5\0\2\177\3\0\1\177\22\0\2\201\24\0\2\201"+
|
||||
"\1\0\1\201\4\0\3\201\5\0\2\201\3\0\1\201"+
|
||||
"\21\0\5\173\1\202\70\173\2\0\1\203\51\0\1\203"+
|
||||
"\30\0\1\117\67\0\2\204\4\0\1\176\17\0\2\204"+
|
||||
"\1\0\1\204\4\0\3\204\5\0\2\204\3\0\1\204"+
|
||||
"\22\0\2\205\24\0\2\205\1\0\1\205\4\0\3\205"+
|
||||
"\5\0\2\205\3\0\1\205\22\0\2\206\4\0\1\176"+
|
||||
"\17\0\2\206\1\0\1\206\4\0\3\206\5\0\2\206"+
|
||||
"\3\0\1\206\22\0\2\207\24\0\2\207\1\0\1\207"+
|
||||
"\4\0\3\207\5\0\2\207\3\0\1\207\22\0\2\210"+
|
||||
"\4\0\1\176\17\0\2\210\1\0\1\210\4\0\3\210"+
|
||||
"\5\0\2\210\3\0\1\210\22\0\2\211\4\0\1\176"+
|
||||
"\17\0\2\211\1\0\1\211\4\0\3\211\5\0\2\211"+
|
||||
"\3\0\1\211\22\0\2\212\4\0\1\176\17\0\2\212"+
|
||||
"\1\0\1\212\4\0\3\212\5\0\2\212\3\0\1\212"+
|
||||
"\22\0\2\213\4\0\1\176\17\0\2\213\1\0\1\213"+
|
||||
"\4\0\3\213\5\0\2\213\3\0\1\213\22\0\2\213"+
|
||||
"\4\0\1\200\17\0\2\213\1\0\1\213\4\0\3\213"+
|
||||
"\5\0\2\213\3\0\1\213\21\0";
|
||||
|
||||
private static int [] zzUnpackTrans() {
|
||||
int [] result = new int[3906];
|
||||
int [] result = new int[3968];
|
||||
int offset = 0;
|
||||
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
|
||||
return result;
|
||||
@@ -387,15 +388,15 @@ class _RegExLexer implements FlexLexer {
|
||||
"\12\0\1\1\5\0\2\11\1\1\2\11\2\1\12\11"+
|
||||
"\1\1\1\11\1\1\1\11\1\1\3\11\1\1\1\11"+
|
||||
"\1\1\1\11\1\1\1\11\1\1\2\11\1\1\3\11"+
|
||||
"\2\1\5\11\2\1\1\11\1\0\1\1\1\11\2\1"+
|
||||
"\6\11\2\1\2\11\1\1\4\11\2\1\2\11\1\1"+
|
||||
"\3\11\1\0\4\11\1\0\1\1\4\11\1\0\1\11"+
|
||||
"\1\0\1\1\1\0\3\11\3\1\7\11\1\0\1\1"+
|
||||
"\1\0\1\11\1\1\1\11\1\1\2\11\3\1\1\11"+
|
||||
"\4\1";
|
||||
"\2\1\2\11\1\1\3\11\2\1\1\11\1\0\1\1"+
|
||||
"\1\11\2\1\6\11\2\1\2\11\1\1\4\11\2\1"+
|
||||
"\2\11\1\1\3\11\1\0\4\11\1\0\1\1\4\11"+
|
||||
"\1\0\1\11\1\0\1\1\1\0\3\11\3\1\7\11"+
|
||||
"\1\0\1\1\1\0\1\11\1\1\1\11\1\1\2\11"+
|
||||
"\3\1\1\11\4\1";
|
||||
|
||||
private static int [] zzUnpackAttribute() {
|
||||
int [] result = new int[138];
|
||||
int [] result = new int[139];
|
||||
int offset = 0;
|
||||
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
|
||||
return result;
|
||||
|
||||
@@ -217,7 +217,8 @@ public class RegExpParser implements PsiParser {
|
||||
|
||||
// DEFLIST
|
||||
if (parseClassIntersection(builder)) {
|
||||
while (RegExpTT.CHARACTERS2.contains(builder.getTokenType()) ||
|
||||
while (RegExpTT.CHARACTERS.contains(builder.getTokenType()) ||
|
||||
builder.getTokenType() == RegExpTT.CHAR_CLASS ||
|
||||
builder.getTokenType() == RegExpTT.CLASS_BEGIN ||
|
||||
builder.getTokenType() == RegExpTT.PROPERTY ||
|
||||
builder.getTokenType() == RegExpTT.BRACKET_EXPRESSION_BEGIN) {
|
||||
@@ -257,9 +258,14 @@ public class RegExpParser implements PsiParser {
|
||||
else if (token == RegExpTT.BRACKET_EXPRESSION_BEGIN) {
|
||||
parseBracketExpression(builder);
|
||||
}
|
||||
else if (RegExpTT.CHARACTERS2.contains(token)) {
|
||||
else if (RegExpTT.CHARACTERS.contains(token)) {
|
||||
parseSimpleClassdef(builder);
|
||||
}
|
||||
else if (token == RegExpTT.CHAR_CLASS) {
|
||||
final PsiBuilder.Marker m = builder.mark();
|
||||
builder.advanceLexer();
|
||||
m.done(RegExpElementTypes.SIMPLE_CLASS);
|
||||
}
|
||||
else if (token == RegExpTT.PROPERTY) {
|
||||
parseProperty(builder);
|
||||
}
|
||||
@@ -291,7 +297,7 @@ public class RegExpParser implements PsiParser {
|
||||
}
|
||||
|
||||
private void parseSimpleClassdef(PsiBuilder builder) {
|
||||
assert RegExpTT.CHARACTERS2.contains(builder.getTokenType());
|
||||
assert RegExpTT.CHARACTERS.contains(builder.getTokenType());
|
||||
|
||||
final PsiBuilder.Marker marker = builder.mark();
|
||||
makeChar(builder);
|
||||
@@ -301,7 +307,7 @@ public class RegExpParser implements PsiParser {
|
||||
builder.advanceLexer();
|
||||
|
||||
final IElementType t = builder.getTokenType();
|
||||
if (RegExpTT.CHARACTERS2.contains(t)) {
|
||||
if (RegExpTT.CHARACTERS.contains(t) || t == RegExpTT.CHAR_CLASS) {
|
||||
m.drop();
|
||||
makeChar(builder);
|
||||
marker.done(RegExpElementTypes.CHAR_RANGE);
|
||||
@@ -449,7 +455,7 @@ public class RegExpParser implements PsiParser {
|
||||
marker.drop();
|
||||
parseNamedCharacter(builder);
|
||||
}
|
||||
else if (RegExpTT.SIMPLE_CLASSES.contains(type)) {
|
||||
else if (type == RegExpTT.DOT || type == RegExpTT.CHAR_CLASS) {
|
||||
builder.advanceLexer();
|
||||
marker.done(RegExpElementTypes.SIMPLE_CLASS);
|
||||
}
|
||||
|
||||
@@ -135,22 +135,17 @@ public interface RegExpTT {
|
||||
IElementType RUBY_QUOTED_NAMED_GROUP_CALL = new RegExpElementType("RUBY_QUOTED_NAMED_GROUP_CALL");
|
||||
|
||||
TokenSet CHARACTERS = TokenSet.create(CHARACTER,
|
||||
ESC_CTRL_CHARACTER,
|
||||
ESC_CHARACTER,
|
||||
CTRL_CHARACTER,
|
||||
CTRL,
|
||||
UNICODE_CHAR,
|
||||
HEX_CHAR, BAD_HEX_VALUE,
|
||||
OCT_CHAR, BAD_OCT_VALUE,
|
||||
REDUNDANT_ESCAPE,
|
||||
MINUS,
|
||||
StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN,
|
||||
StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
|
||||
|
||||
TokenSet SIMPLE_CLASSES = TokenSet.create(DOT, CHAR_CLASS);
|
||||
|
||||
// caret is just a character in classes after the first position: [a^] matches "a" or "^"
|
||||
TokenSet CHARACTERS2 = TokenSet.orSet(CHARACTERS, SIMPLE_CLASSES);
|
||||
ESC_CTRL_CHARACTER,
|
||||
ESC_CHARACTER,
|
||||
CTRL_CHARACTER,
|
||||
CTRL,
|
||||
UNICODE_CHAR,
|
||||
HEX_CHAR, BAD_HEX_VALUE,
|
||||
OCT_CHAR, BAD_OCT_VALUE,
|
||||
REDUNDANT_ESCAPE,
|
||||
MINUS,
|
||||
StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN,
|
||||
StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
|
||||
|
||||
TokenSet QUANTIFIERS = TokenSet.create(QUEST, PLUS, STAR, LBRACE);
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ RBRACKET="]"
|
||||
|
||||
ESCAPE="\\"
|
||||
NAME=[:letter:]([:letter:]|_|-|" "|"("|")"|[:digit:])*
|
||||
GROUP_NAME=[:letter:]([:letter:]|_|-|" "|[:digit:])*
|
||||
ANY=[^]
|
||||
|
||||
META1 = {ESCAPE} | {LBRACKET} | "^"
|
||||
@@ -340,25 +341,25 @@ HEX_CHAR=[0-9a-fA-F]
|
||||
}
|
||||
|
||||
<NAMED_GROUP> {
|
||||
{NAME} { return RegExpTT.NAME; }
|
||||
{GROUP_NAME} { return RegExpTT.NAME; }
|
||||
">" { yybegin(YYINITIAL); return RegExpTT.GT; }
|
||||
{ANY} { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; }
|
||||
}
|
||||
|
||||
<QUOTED_NAMED_GROUP> {
|
||||
{NAME} { return RegExpTT.NAME; }
|
||||
{GROUP_NAME} { return RegExpTT.NAME; }
|
||||
"'" { yybegin(YYINITIAL); return RegExpTT.QUOTE; }
|
||||
{ANY} { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; }
|
||||
}
|
||||
|
||||
<PY_NAMED_GROUP_REF> {
|
||||
{NAME} { return RegExpTT.NAME; }
|
||||
{GROUP_NAME} { return RegExpTT.NAME; }
|
||||
")" { yybegin(YYINITIAL); return RegExpTT.GROUP_END; }
|
||||
{ANY} { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; }
|
||||
}
|
||||
|
||||
<PY_COND_REF> {
|
||||
{NAME} { return RegExpTT.NAME; }
|
||||
{GROUP_NAME} { return RegExpTT.NAME; }
|
||||
[:digit:]+ { return RegExpTT.NUMBER; }
|
||||
")" { yybegin(YYINITIAL); return RegExpTT.GROUP_END; }
|
||||
{ANY} { yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER; }
|
||||
|
||||
@@ -84,9 +84,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
|
||||
public void visitRegExpCharRange(RegExpCharRange range) {
|
||||
final RegExpCharRange.Endpoint from = range.getFrom();
|
||||
final RegExpCharRange.Endpoint to = range.getTo();
|
||||
final boolean a = from instanceof RegExpChar;
|
||||
final boolean b = to instanceof RegExpChar;
|
||||
if (a && b) {
|
||||
if (from instanceof RegExpChar && to instanceof RegExpChar) {
|
||||
final Character t = ((RegExpChar)to).getValue();
|
||||
final Character f = ((RegExpChar)from).getValue();
|
||||
if (t != null && f != null) {
|
||||
@@ -99,8 +97,8 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (a != b) {
|
||||
myHolder.createErrorAnnotation(range, "Character class (e.g. '\\\\w') may not be used inside character range");
|
||||
else if (to instanceof RegExpSimpleClass) {
|
||||
myHolder.createErrorAnnotation(to, "Character class not allowed inside character range");
|
||||
}
|
||||
else if (from.getText().equals(to.getText())) {
|
||||
myHolder.createWarningAnnotation(range, "Redundant character range");
|
||||
@@ -151,12 +149,20 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForDuplicates(RegExpClassElement element, Set<Character> seen) {
|
||||
private void checkForDuplicates(RegExpClassElement element, Set<Object> seen) {
|
||||
if (element instanceof RegExpChar) {
|
||||
final RegExpChar regExpChar = (RegExpChar)element;
|
||||
final Character value = regExpChar.getValue();
|
||||
if (value != null && !seen.add(value)) {
|
||||
myHolder.createWarningAnnotation(regExpChar, "Duplicate character '" + regExpChar.getText() + "' in character class");
|
||||
myHolder.createWarningAnnotation(regExpChar, "Duplicate character '" + regExpChar.getText() + "' inside character class");
|
||||
}
|
||||
}
|
||||
else if (element instanceof RegExpSimpleClass) {
|
||||
final RegExpSimpleClass regExpSimpleClass = (RegExpSimpleClass)element;
|
||||
final RegExpSimpleClass.Kind kind = regExpSimpleClass.getKind();
|
||||
if (!seen.add(kind)) {
|
||||
myHolder.createWarningAnnotation(regExpSimpleClass, "Duplicate predefined character class '" + regExpSimpleClass.getText() +
|
||||
"' inside character class");
|
||||
}
|
||||
}
|
||||
else if (element instanceof RegExpClass) {
|
||||
|
||||
@@ -184,6 +184,10 @@ public class RegExpParsingTest extends ParsingTestCase {
|
||||
public void testGroups33() throws IOException { doCodeTest("(?<asdf>[a-c])\\1"); }
|
||||
public void testGroups34() throws IOException { doCodeTest("(?<asdf>[a-c])\\k<asdf>"); }
|
||||
public void testGroups35() throws IOException { doCodeTest("\\k<adsf>"); }
|
||||
public void testGroups36() throws IOException { doCodeTest("(?P<name>{"); }
|
||||
public void testGroups37() throws IOException { doCodeTest("(?P=name)"); }
|
||||
public void testGroups38() throws IOException { doCodeTest("\\g'name'"); }
|
||||
public void testGroups39() throws IOException { doCodeTest("(?(name)yes-pattern|no-pattern)"); }
|
||||
|
||||
public void testEscapes1() throws IOException { doCodeTest("\\q"); }
|
||||
public void testEscapes2() throws IOException { doCodeTest("\\#"); }
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
</quantifiers>
|
||||
<charclasses>
|
||||
<test verify="false">
|
||||
<pattern><![CDATA[[<warning descr="Redundant character range">\w-\w</warning>]]]></pattern>
|
||||
<pattern><![CDATA[[\w-<warning descr="Duplicate predefined character class '\w' inside character class">\w</warning>]]]></pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test>
|
||||
<pattern>[\w-a]</pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test host="com.intellij.psi.impl.JavaRegExpHost">
|
||||
@@ -106,7 +110,7 @@
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test>
|
||||
<pattern><![CDATA[[\Qabc?*+.)<warning descr="Duplicate character ')' in character class">)</warning>]<warning descr="Duplicate character ']' in character class">]</warning>[<warning descr="Duplicate character ']' in character class">]</warning>\E]]]></pattern>
|
||||
<pattern><![CDATA[[\Qabc?*+.)<warning descr="Duplicate character ')' inside character class">)</warning>]<warning descr="Duplicate character ']' inside character class">]</warning>[<warning descr="Duplicate character ']' inside character class">]</warning>\E]]]></pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test host="com.intellij.psi.impl.JavaRegExpHost">
|
||||
@@ -133,7 +137,7 @@
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
<test>
|
||||
<pattern><![CDATA[[:xdig<warning descr="Duplicate character 'i' in character class">i</warning>t<warning descr="Duplicate character ':' in character class">:</warning>]+]]></pattern>
|
||||
<pattern><![CDATA[[:xdig<warning descr="Duplicate character 'i' inside character class">i</warning>t<warning descr="Duplicate character ':' inside character class">:</warning>]+]]></pattern>
|
||||
<expected>OK</expected>
|
||||
</test>
|
||||
</namedchars>
|
||||
|
||||
@@ -3,10 +3,11 @@ REGEXP_FILE
|
||||
RegExpBranchImpl: <[\w-\w]>
|
||||
RegExpClassImpl: <[\w-\w]>
|
||||
PsiElement(CLASS_BEGIN)('[')
|
||||
RegExpCharRangeImpl: <\w-\w>
|
||||
RegExpUnionImpl: <\w-\w>
|
||||
RegExpSimpleClassImpl: <\w>
|
||||
PsiElement(CHAR_CLASS)('\w')
|
||||
PsiElement(MINUS)('-')
|
||||
RegExpCharImpl: <->
|
||||
PsiElement(MINUS)('-')
|
||||
RegExpSimpleClassImpl: <\w>
|
||||
PsiElement(CHAR_CLASS)('\w')
|
||||
PsiElement(CLASS_END)(']')
|
||||
@@ -0,0 +1,14 @@
|
||||
REGEXP_FILE
|
||||
RegExpPatternImpl: <(?P<name>{>
|
||||
RegExpBranchImpl: <(?P<name>{>
|
||||
RegExpClosureImpl: <(?P<name>{>
|
||||
RegExpGroupImpl: <(?P<name>>
|
||||
PsiElement(PYTHON_NAMED_GROUP)('(?P<')
|
||||
PsiElement(NAME)('name')
|
||||
PsiElement(GT)('>')
|
||||
PsiErrorElement:Dangling metacharacter
|
||||
<empty list>
|
||||
RegExpQuantifierImpl: <{>
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiErrorElement:Number expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,7 @@
|
||||
REGEXP_FILE
|
||||
RegExpPatternImpl: <(?P=name)>
|
||||
RegExpBranchImpl: <(?P=name)>
|
||||
RegExpNamedGroupRefImpl: <(?P=name)>
|
||||
PsiElement(PYTHON_NAMED_GROUP_REF)('(?P=')
|
||||
PsiElement(NAME)('name')
|
||||
PsiElement(GROUP_END)(')')
|
||||
@@ -0,0 +1,7 @@
|
||||
REGEXP_FILE
|
||||
RegExpPatternImpl: <\g'name'>
|
||||
RegExpBranchImpl: <\g'name'>
|
||||
RegExpNamedGroupRefImpl: <\g'name'>
|
||||
PsiElement(RUBY_QUOTED_NAMED_GROUP_CALL)('\g'')
|
||||
PsiElement(NAME)('name')
|
||||
PsiElement(QUOTE)(''')
|
||||
@@ -0,0 +1,53 @@
|
||||
REGEXP_FILE
|
||||
RegExpPatternImpl: <(?(name)yes-pattern|no-pattern)>
|
||||
RegExpBranchImpl: <(?(name)yes-pattern|no-pattern)>
|
||||
RegExpPyCondRefImpl: <(?(name)yes-pattern|no-pattern)>
|
||||
PsiElement(PYTHON_COND_REF)('(?(')
|
||||
PsiElement(NAME)('name')
|
||||
PsiElement(GROUP_END)(')')
|
||||
RegExpBranchImpl: <yes-pattern>
|
||||
RegExpCharImpl: <y>
|
||||
PsiElement(CHARACTER)('y')
|
||||
RegExpCharImpl: <e>
|
||||
PsiElement(CHARACTER)('e')
|
||||
RegExpCharImpl: <s>
|
||||
PsiElement(CHARACTER)('s')
|
||||
RegExpCharImpl: <->
|
||||
PsiElement(MINUS)('-')
|
||||
RegExpCharImpl: <p>
|
||||
PsiElement(CHARACTER)('p')
|
||||
RegExpCharImpl: <a>
|
||||
PsiElement(CHARACTER)('a')
|
||||
RegExpCharImpl: <t>
|
||||
PsiElement(CHARACTER)('t')
|
||||
RegExpCharImpl: <t>
|
||||
PsiElement(CHARACTER)('t')
|
||||
RegExpCharImpl: <e>
|
||||
PsiElement(CHARACTER)('e')
|
||||
RegExpCharImpl: <r>
|
||||
PsiElement(CHARACTER)('r')
|
||||
RegExpCharImpl: <n>
|
||||
PsiElement(CHARACTER)('n')
|
||||
PsiElement(UNION)('|')
|
||||
RegExpBranchImpl: <no-pattern>
|
||||
RegExpCharImpl: <n>
|
||||
PsiElement(CHARACTER)('n')
|
||||
RegExpCharImpl: <o>
|
||||
PsiElement(CHARACTER)('o')
|
||||
RegExpCharImpl: <->
|
||||
PsiElement(MINUS)('-')
|
||||
RegExpCharImpl: <p>
|
||||
PsiElement(CHARACTER)('p')
|
||||
RegExpCharImpl: <a>
|
||||
PsiElement(CHARACTER)('a')
|
||||
RegExpCharImpl: <t>
|
||||
PsiElement(CHARACTER)('t')
|
||||
RegExpCharImpl: <t>
|
||||
PsiElement(CHARACTER)('t')
|
||||
RegExpCharImpl: <e>
|
||||
PsiElement(CHARACTER)('e')
|
||||
RegExpCharImpl: <r>
|
||||
PsiElement(CHARACTER)('r')
|
||||
RegExpCharImpl: <n>
|
||||
PsiElement(CHARACTER)('n')
|
||||
PsiElement(GROUP_END)(')')
|
||||
@@ -26,7 +26,7 @@ import java.util.*;
|
||||
|
||||
public class BackwardReferenceIndexUtil {
|
||||
static void registerFile(String filePath,
|
||||
Set<? extends JavacRef> refs,
|
||||
Collection<? extends JavacRef> refs,
|
||||
List<JavacDef> defs,
|
||||
final BackwardReferenceIndexWriter writer) {
|
||||
final int fileId = writer.enumeratePath(filePath);
|
||||
|
||||
@@ -19,16 +19,20 @@ import org.jetbrains.jps.javac.ast.api.JavacDef;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacRef;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar {
|
||||
private BackwardReferenceIndexWriter myWriter;
|
||||
private volatile BackwardReferenceIndexWriter myWriter;
|
||||
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
public void initialize() {
|
||||
myWriter = BackwardReferenceIndexWriter.getInstance();
|
||||
return myWriter != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return BackwardReferenceIndexWriter.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -37,7 +41,7 @@ public class BackwardReferenceRegistrar implements JavacFileReferencesRegistrar
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerFile(String filePath, Set<? extends JavacRef> refs, List<JavacDef> defs) {
|
||||
public void registerFile(String filePath, Collection<JavacRef> refs, List<JavacDef> defs) {
|
||||
BackwardReferenceIndexUtil.registerFile(filePath, refs, defs, myWriter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1042,6 +1042,10 @@ public class JavaBuilder extends ModuleLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
for (JavaCompilerToolExtension extension : JavaCompilerToolExtension.getExtensions()) {
|
||||
vmOptions.addAll(extension.getExternalBuildProcessOptions(compilingTool));
|
||||
}
|
||||
|
||||
compilingTool.processCompilerOptions(context, options);
|
||||
|
||||
JAVAC_OPTIONS.set(context, options);
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.jetbrains.jps.service.JpsServiceManager;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -51,6 +53,10 @@ public abstract class JavaCompilerToolExtension {
|
||||
public void processData(String dataName, byte[] content) {
|
||||
}
|
||||
|
||||
public List<String> getExternalBuildProcessOptions(@NotNull JavaCompilingTool compilingTool) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public static Iterable<JavaCompilerToolExtension> getExtensions() {
|
||||
return JpsServiceManager.getInstance().getExtensions(JavaCompilerToolExtension.class);
|
||||
}
|
||||
|
||||
+58
-60
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.source.util.TaskEvent;
|
||||
@@ -27,7 +28,7 @@ import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacDef;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileData;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacRef;
|
||||
|
||||
import javax.lang.model.element.ElementKind;
|
||||
@@ -35,14 +36,11 @@ import javax.lang.model.element.TypeElement;
|
||||
import javax.tools.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
final class JavacReferenceCollectorListener implements TaskListener {
|
||||
private final JavacFileReferencesRegistrar[] myFullASTListeners;
|
||||
private final JavacFileReferencesRegistrar[] myOnlyImportsListeners;
|
||||
private final boolean myDivideImportRefs;
|
||||
private final Consumer<JavacFileData> myDataConsumer;
|
||||
private final JavacTreeRefScanner myAstScanner;
|
||||
|
||||
private Name myAsterisk;
|
||||
@@ -50,11 +48,11 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
private final Map<String, IncompletelyProcessedFile> myIncompletelyProcessedFiles = new THashMap<String, IncompletelyProcessedFile>(10);
|
||||
|
||||
static void installOn(JavaCompiler.CompilationTask task,
|
||||
JavacFileReferencesRegistrar[] fullASTListenerArray,
|
||||
JavacFileReferencesRegistrar[] onlyImportsListenerArray) {
|
||||
boolean divideImportRefs,
|
||||
Consumer<JavacFileData> dataConsumer) {
|
||||
JavacTask javacTask = (JavacTask)task;
|
||||
Method addTaskMethod = ReflectionUtil.getMethod(JavacTask.class, "addTaskListener", TaskListener.class); // jdk >= 8
|
||||
final JavacReferenceCollectorListener taskListener = new JavacReferenceCollectorListener(fullASTListenerArray, onlyImportsListenerArray);
|
||||
final JavacReferenceCollectorListener taskListener = new JavacReferenceCollectorListener(divideImportRefs, dataConsumer);
|
||||
if (addTaskMethod != null) {
|
||||
try {
|
||||
addTaskMethod.invoke(task, taskListener);
|
||||
@@ -71,9 +69,9 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
}
|
||||
}
|
||||
|
||||
private JavacReferenceCollectorListener(JavacFileReferencesRegistrar[] fullASTListenerArray, JavacFileReferencesRegistrar[] importsListenerArray) {
|
||||
myFullASTListeners = fullASTListenerArray;
|
||||
myOnlyImportsListeners = importsListenerArray;
|
||||
private JavacReferenceCollectorListener(boolean divideImportRefs, Consumer<JavacFileData> dataConsumer) {
|
||||
myDivideImportRefs = divideImportRefs;
|
||||
myDataConsumer = dataConsumer;
|
||||
myAstScanner = JavacTreeRefScanner.createASTScanner();
|
||||
}
|
||||
|
||||
@@ -93,37 +91,32 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
final int size = declarations.size();
|
||||
|
||||
boolean isFileDataComplete = true;
|
||||
boolean submitImportsOnlyData = true;
|
||||
boolean collectImportsData = true;
|
||||
JCTree declarationToProcess = null;
|
||||
final Set<JavacRef.JavacSymbolRefBase> collectedReferences;
|
||||
final List<JavacDef> collectedDefinitions;
|
||||
final TypeElement analyzedElement = e.getTypeElement();
|
||||
|
||||
IncompletelyProcessedFile incompletelyProcessedFile;
|
||||
switch (size) {
|
||||
case 0:
|
||||
collectedReferences = IncompletelyProcessedFile.createReferenceHolder();
|
||||
collectedDefinitions = IncompletelyProcessedFile.createDefinitionHolder();
|
||||
incompletelyProcessedFile = new IncompletelyProcessedFile(0, fileName);
|
||||
break;
|
||||
case 1:
|
||||
collectedReferences = IncompletelyProcessedFile.createReferenceHolder();
|
||||
collectedDefinitions = IncompletelyProcessedFile.createDefinitionHolder();
|
||||
incompletelyProcessedFile = new IncompletelyProcessedFile(0, fileName);
|
||||
declarationToProcess = declarations.get(0);
|
||||
break;
|
||||
default:
|
||||
IncompletelyProcessedFile incompletelyProcessedFile = myIncompletelyProcessedFiles.get(fileName);
|
||||
incompletelyProcessedFile = myIncompletelyProcessedFiles.get(fileName);
|
||||
if (incompletelyProcessedFile == null) {
|
||||
myIncompletelyProcessedFiles.put(fileName, incompletelyProcessedFile = new IncompletelyProcessedFile(size));
|
||||
myIncompletelyProcessedFiles.put(fileName, incompletelyProcessedFile = new IncompletelyProcessedFile(size, fileName));
|
||||
} else {
|
||||
submitImportsOnlyData = false;
|
||||
collectImportsData = false;
|
||||
}
|
||||
|
||||
if (--incompletelyProcessedFile.remainDeclarations == 0) {
|
||||
if (incompletelyProcessedFile.decrementRemainDeclarationsAndGet() == 0) {
|
||||
myIncompletelyProcessedFiles.remove(fileName);
|
||||
} else {
|
||||
isFileDataComplete = false;
|
||||
}
|
||||
collectedReferences = incompletelyProcessedFile.collectedReferences;
|
||||
collectedDefinitions = incompletelyProcessedFile.collectedDefinitions;
|
||||
|
||||
for (JCTree declaration : declarations) {
|
||||
if (declaration.type != null && declaration.type.tsym == analyzedElement) {
|
||||
@@ -135,22 +128,22 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
if (declarationToProcess == null) throw new IllegalStateException("Can't find tree for " + analyzedElement.getQualifiedName());
|
||||
}
|
||||
|
||||
if (submitImportsOnlyData) {
|
||||
scanImports(unit, collectedReferences);
|
||||
for (JavacFileReferencesRegistrar r : myOnlyImportsListeners) {
|
||||
r.registerFile(fileName, collectedReferences, collectedDefinitions);
|
||||
if (collectImportsData) {
|
||||
scanImports(unit, incompletelyProcessedFile.myFileData.getRefs());
|
||||
if (myDivideImportRefs) {
|
||||
scanImports(unit, incompletelyProcessedFile.myFileData.getImportRefs());
|
||||
}
|
||||
}
|
||||
if (myFullASTListeners.length == 0) return;
|
||||
final IncompletelyProcessedFile finalIncompletelyProcessedFile = incompletelyProcessedFile;
|
||||
JavacTreeScannerSink sink = new JavacTreeScannerSink() {
|
||||
@Override
|
||||
public void sinkReference(JavacRef.JavacSymbolRefBase ref) {
|
||||
collectedReferences.add(ref);
|
||||
finalIncompletelyProcessedFile.myFileData.getRefs().add(ref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sinkDeclaration(JavacDef def) {
|
||||
collectedDefinitions.add(def);
|
||||
finalIncompletelyProcessedFile.myFileData.getDefs().add(def);
|
||||
}
|
||||
};
|
||||
myAstScanner.scan(declarationToProcess, sink);
|
||||
@@ -160,9 +153,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
myAstScanner.scan(annotation, sink);
|
||||
}
|
||||
|
||||
for (JavacFileReferencesRegistrar r : myFullASTListeners) {
|
||||
r.registerFile(e.getSourceFile().getName(), collectedReferences, collectedDefinitions);
|
||||
}
|
||||
myDataConsumer.consume(incompletelyProcessedFile.myFileData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +169,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
return myAsterisk;
|
||||
}
|
||||
|
||||
private void scanImports(JCTree.JCCompilationUnit compilationUnit, Set<JavacRef.JavacSymbolRefBase> symbols) {
|
||||
private void scanImports(JCTree.JCCompilationUnit compilationUnit, Collection<JavacRef> symbols) {
|
||||
for (JCTree.JCImport anImport : compilationUnit.getImports()) {
|
||||
final JCTree.JCFieldAccess id = (JCTree.JCFieldAccess)anImport.getQualifiedIdentifier();
|
||||
final Symbol sym = id.sym;
|
||||
@@ -205,7 +196,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectClassImports(Symbol baseImport, Set<JavacRef.JavacSymbolRefBase> collector) {
|
||||
private static void collectClassImports(Symbol baseImport, Collection<JavacRef> collector) {
|
||||
for (Symbol symbol = baseImport;
|
||||
symbol != null && symbol.getKind() != ElementKind.PACKAGE;
|
||||
symbol = symbol.owner) {
|
||||
@@ -213,31 +204,38 @@ final class JavacReferenceCollectorListener implements TaskListener {
|
||||
}
|
||||
}
|
||||
|
||||
private static class IncompletelyProcessedFile {
|
||||
private final Set<JavacRef.JavacSymbolRefBase> collectedReferences = createReferenceHolder();
|
||||
private final List<JavacDef> collectedDefinitions = createDefinitionHolder();
|
||||
private int remainDeclarations;
|
||||
private class IncompletelyProcessedFile {
|
||||
private final JavacFileData myFileData;
|
||||
private int myRemainDeclarations;
|
||||
|
||||
private IncompletelyProcessedFile(int remainDeclarations) {
|
||||
this.remainDeclarations = remainDeclarations;
|
||||
private IncompletelyProcessedFile(int remainDeclarations, String filePath) {
|
||||
myRemainDeclarations = remainDeclarations;
|
||||
myFileData = new JavacFileData(filePath,
|
||||
createReferenceHolder(),
|
||||
myDivideImportRefs ? createReferenceHolder() : Collections.<JavacRef>emptyList(),
|
||||
createDefinitionHolder());
|
||||
}
|
||||
|
||||
private static Set<JavacRef.JavacSymbolRefBase> createReferenceHolder() {
|
||||
return new THashSet<JavacRef.JavacSymbolRefBase>(new TObjectHashingStrategy<JavacRef.JavacSymbolRefBase>() {
|
||||
@Override
|
||||
public int computeHashCode(JavacRef.JavacSymbolRefBase ref) {
|
||||
return ref.getOriginalElement().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(JavacRef.JavacSymbolRefBase r1, JavacRef.JavacSymbolRefBase r2) {
|
||||
return r1.getOriginalElement() == r2.getOriginalElement();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static List<JavacDef> createDefinitionHolder() {
|
||||
return new ArrayList<JavacDef>();
|
||||
private int decrementRemainDeclarationsAndGet() {
|
||||
return --myRemainDeclarations;
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<JavacRef> createReferenceHolder() {
|
||||
return new THashSet<JavacRef>(new TObjectHashingStrategy<JavacRef>() {
|
||||
@Override
|
||||
public int computeHashCode(JavacRef ref) {
|
||||
return ((JavacRef.JavacSymbolRefBase) ref).getOriginalElement().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(JavacRef r1, JavacRef r2) {
|
||||
return ((JavacRef.JavacSymbolRefBase) r1).getOriginalElement() == ((JavacRef.JavacSymbolRefBase) r2).getOriginalElement();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static List<JavacDef> createDefinitionHolder() {
|
||||
return new ArrayList<JavacDef>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,34 +15,19 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
|
||||
import org.jetbrains.jps.service.JpsServiceManager;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileData;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Code here should not depend on any javac private API located in tools.jar if no JavacFileReferencesRegistrar-s will be run.
|
||||
* A workaround to allow run standalone jps with improperly configured classloader without NoClassDefFoundError (e.g: IDEA-162877)
|
||||
*/
|
||||
public class JavacReferencesCollector {
|
||||
public static void installOn(JavaCompiler.CompilationTask task) {
|
||||
List<JavacFileReferencesRegistrar> fullASTListeners = new SmartList<JavacFileReferencesRegistrar>();
|
||||
List<JavacFileReferencesRegistrar> onlyImportsListeners = new SmartList<JavacFileReferencesRegistrar>();
|
||||
for (JavacFileReferencesRegistrar listener : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) {
|
||||
if (!listener.initialize()) {
|
||||
continue;
|
||||
}
|
||||
(listener.onlyImports() ? onlyImportsListeners : fullASTListeners).add(listener);
|
||||
}
|
||||
|
||||
final JavacFileReferencesRegistrar[] fullASTListenerArray = fullASTListeners.toArray(new JavacFileReferencesRegistrar[fullASTListeners.size()]);
|
||||
final JavacFileReferencesRegistrar[] onlyImportsListenerArray = onlyImportsListeners.toArray(new JavacFileReferencesRegistrar[onlyImportsListeners.size()]);
|
||||
if (fullASTListenerArray.length == 0 && onlyImportsListenerArray.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavacReferenceCollectorListener.installOn(task, fullASTListenerArray, onlyImportsListenerArray);
|
||||
public static void installOn(JavaCompiler.CompilationTask task,
|
||||
boolean divideImportRefs,
|
||||
Consumer<JavacFileData> fileDataConsumer) {
|
||||
JavacReferenceCollectorListener.installOn(task, divideImportRefs, fileDataConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
+111
-5
@@ -15,14 +15,23 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast;
|
||||
|
||||
import com.intellij.openapi.util.AtomicClearableLazyValue;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.jps.builders.java.JavaCompilingTool;
|
||||
import org.jetbrains.jps.javac.DiagnosticOutputConsumer;
|
||||
import org.jetbrains.jps.javac.JavaCompilerToolExtension;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileData;
|
||||
import org.jetbrains.jps.javac.ast.api.JavacFileReferencesRegistrar;
|
||||
import org.jetbrains.jps.model.java.compiler.JavaCompilers;
|
||||
import org.jetbrains.jps.service.JpsServiceManager;
|
||||
|
||||
import javax.tools.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
@@ -31,6 +40,24 @@ import java.util.Collection;
|
||||
public class RefCollectorCompilerToolExtension extends JavaCompilerToolExtension{
|
||||
public static final String ID = "ASTReferenceCollector";
|
||||
|
||||
private static final String ENABLED_PARAM = "jps.ref.collector.enabled";
|
||||
private static final String DIVIDE_IMPORTS_PARAM = "jps.divide.imports";
|
||||
|
||||
private final AtomicClearableLazyValue<List<JavacFileReferencesRegistrar>> myRegistrars = new AtomicClearableLazyValue<List<JavacFileReferencesRegistrar>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<JavacFileReferencesRegistrar> compute() {
|
||||
List<JavacFileReferencesRegistrar> result = new ArrayList<JavacFileReferencesRegistrar>();
|
||||
for (JavacFileReferencesRegistrar registrar : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) {
|
||||
if (registrar.isEnabled()) {
|
||||
registrar.initialize();
|
||||
result.add(registrar);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
@@ -41,15 +68,94 @@ public class RefCollectorCompilerToolExtension extends JavaCompilerToolExtension
|
||||
public void beforeCompileTaskExecution(@NotNull JavaCompilingTool compilingTool,
|
||||
@NotNull JavaCompiler.CompilationTask task,
|
||||
@NotNull Collection<String> options,
|
||||
@NotNull DiagnosticOutputConsumer diagnosticConsumer) {
|
||||
// todo: transfer collected data via DiagnosticOutputConsumer.customOutputData()
|
||||
if (JavaCompilers.JAVAC_ID.equals(compilingTool.getId())) {
|
||||
JavacReferencesCollector.installOn(task);
|
||||
@NotNull final DiagnosticOutputConsumer diagnosticConsumer) {
|
||||
if (isJavac(compilingTool)) {
|
||||
final String isEnabledProperty = System.getProperty(ENABLED_PARAM);
|
||||
|
||||
Consumer<JavacFileData> fileDataConsumer;
|
||||
boolean divideImportsRefs;
|
||||
if (isEnabledProperty == null) {
|
||||
//in-process
|
||||
final RefCollectorOptions refCollectorOptions = new RefCollectorOptions();
|
||||
fileDataConsumer = refCollectorOptions.enabled ? new Consumer<JavacFileData>() {
|
||||
@Override
|
||||
public void consume(JavacFileData data) {
|
||||
submitFileData(data);
|
||||
}
|
||||
} : null;
|
||||
divideImportsRefs = refCollectorOptions.divideImportRefs;
|
||||
} else if (isEnabledProperty.equals("true")) {
|
||||
//external
|
||||
fileDataConsumer = new Consumer<JavacFileData>() {
|
||||
@Override
|
||||
public void consume(JavacFileData data) {
|
||||
diagnosticConsumer.customOutputData(ID, "javac-refs", data.asBytes());
|
||||
}
|
||||
};
|
||||
divideImportsRefs = SystemProperties.getBooleanProperty(DIVIDE_IMPORTS_PARAM, false);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fileDataConsumer != null) {
|
||||
JavacReferencesCollector.installOn(task, divideImportsRefs, fileDataConsumer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExternalBuildProcessOptions(@NotNull JavaCompilingTool compilingTool) {
|
||||
List<String> options = new ArrayList<String>(2);
|
||||
if (isJavac(compilingTool)) {
|
||||
final RefCollectorOptions refCollectorOptions = new RefCollectorOptions();
|
||||
options.add("-D" + ENABLED_PARAM + "=" + refCollectorOptions.enabled);
|
||||
if (refCollectorOptions.enabled && refCollectorOptions.divideImportRefs) {
|
||||
options.add("-D" + DIVIDE_IMPORTS_PARAM + "=true");
|
||||
}
|
||||
} else {
|
||||
options.add("-D" + ENABLED_PARAM + "=false");
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processData(String dataName, byte[] content) {
|
||||
// todo!
|
||||
submitFileData(JavacFileData.fromBytes(content));
|
||||
}
|
||||
|
||||
private void submitFileData(@NotNull JavacFileData data) {
|
||||
for (JavacFileReferencesRegistrar registrar : myRegistrars.getValue()) {
|
||||
registrar.registerFile(data.getFilePath(), registrar.onlyImports() ? data.getImportRefs() : data.getRefs(), data.getDefs());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isJavac(@NotNull JavaCompilingTool compilingTool) {
|
||||
return JavaCompilers.JAVAC_ID.equals(compilingTool.getId());
|
||||
}
|
||||
|
||||
private static class RefCollectorOptions {
|
||||
private final boolean enabled;
|
||||
private final boolean divideImportRefs;
|
||||
|
||||
private RefCollectorOptions() {
|
||||
boolean enabled = false;
|
||||
boolean divideImportRefs = false;
|
||||
for (JavacFileReferencesRegistrar listener : JpsServiceManager.getInstance().getExtensions(JavacFileReferencesRegistrar.class)) {
|
||||
if (listener.isEnabled()) {
|
||||
enabled = true;
|
||||
if (listener.onlyImports()) {
|
||||
divideImportRefs = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.enabled = enabled;
|
||||
this.divideImportRefs = divideImportRefs;
|
||||
}
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void clearRegistrars() {
|
||||
myRegistrars.drop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast.api;
|
||||
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.util.ThrowableConsumer;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class JavacFileData {
|
||||
private final String myFilePath;
|
||||
private final Collection<JavacRef> myRefs;
|
||||
private final Collection<JavacRef> myImportRefs;
|
||||
private final List<JavacDef> myDefs;
|
||||
|
||||
public JavacFileData(@NotNull String path,
|
||||
@NotNull Collection<JavacRef> refs,
|
||||
@NotNull Collection<JavacRef> importRefs,
|
||||
@NotNull List<JavacDef> defs) {
|
||||
myFilePath = path;
|
||||
myRefs = refs;
|
||||
myImportRefs = importRefs;
|
||||
myDefs = defs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFilePath() {
|
||||
return myFilePath;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<JavacRef> getRefs() {
|
||||
return myRefs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<JavacRef> getImportRefs() {
|
||||
return myImportRefs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JavacDef> getDefs() {
|
||||
return myDefs;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public byte[] asBytes() {
|
||||
final BufferExposingByteArrayOutputStream os = new BufferExposingByteArrayOutputStream();
|
||||
DataOutputStream stream = new DataOutputStream(os);
|
||||
try {
|
||||
EXTERNALIZER.save(stream, this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JavacFileData fromBytes(byte[] bytes) {
|
||||
final UnsyncByteArrayInputStream is = new UnsyncByteArrayInputStream(bytes);
|
||||
try {
|
||||
return EXTERNALIZER.read(new DataInputStream(is));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final DataExternalizer<JavacFileData> EXTERNALIZER = new DataExternalizer<JavacFileData>() {
|
||||
DataExternalizer<JavacRef> myRefSeqExternalizer = createRefExternalizer();
|
||||
DataExternalizer<JavacDef> myDefSeqExternalizer = createDefExternalizer();
|
||||
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, JavacFileData data) throws IOException {
|
||||
EnumeratorStringDescriptor.INSTANCE.save(out, data.getFilePath());
|
||||
saveRefs(out, data.getRefs());
|
||||
saveRefs(out, data.getImportRefs());
|
||||
saveDefs(out, data.getDefs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavacFileData read(@NotNull DataInput in) throws IOException {
|
||||
return new JavacFileData(EnumeratorStringDescriptor.INSTANCE.read(in),
|
||||
readRefs(in),
|
||||
readRefs(in),
|
||||
readDefs(in));
|
||||
}
|
||||
|
||||
|
||||
private void saveRefs(final DataOutput out, Collection<JavacRef> refs) throws IOException {
|
||||
DataInputOutputUtil.writeSeq(out, refs, new ThrowableConsumer<JavacRef, IOException>() {
|
||||
@Override
|
||||
public void consume(JavacRef ref) throws IOException {
|
||||
myRefSeqExternalizer.save(out, ref);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Collection<JavacRef> readRefs(final DataInput in) throws IOException {
|
||||
return DataInputOutputUtil.readSeq(in, new ThrowableComputable<JavacRef, IOException>() {
|
||||
@Override
|
||||
public JavacRef compute() throws IOException {
|
||||
return myRefSeqExternalizer.read(in);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveDefs(final DataOutput out, List<JavacDef> defs) throws IOException {
|
||||
DataInputOutputUtil.writeSeq(out, defs, new ThrowableConsumer<JavacDef, IOException>() {
|
||||
@Override
|
||||
public void consume(JavacDef def) throws IOException {
|
||||
myDefSeqExternalizer.save(out, def);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<JavacDef> readDefs(final DataInput in) throws IOException {
|
||||
return DataInputOutputUtil.readSeq(in, new ThrowableComputable<JavacDef, IOException>() {
|
||||
@Override
|
||||
public JavacDef compute() throws IOException {
|
||||
return myDefSeqExternalizer.read(in);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static DataExternalizer<JavacDef> createDefExternalizer() {
|
||||
return new DataExternalizer<JavacDef>() {
|
||||
private static final byte CLASS_MARKER = 0;
|
||||
private static final byte FUN_EXPR_MARKER = 1;
|
||||
|
||||
DataExternalizer<JavacRef> refExternalizer = createRefExternalizer();
|
||||
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, JavacDef def) throws IOException {
|
||||
if (def instanceof JavacDef.JavacClassDef) {
|
||||
out.writeByte(CLASS_MARKER);
|
||||
final JavacRef[] superClasses = ((JavacDef.JavacClassDef)def).getSuperClasses();
|
||||
out.writeInt(superClasses.length);
|
||||
for (JavacRef aClass : superClasses) {
|
||||
refExternalizer.save(out, aClass);
|
||||
}
|
||||
}
|
||||
else if (def instanceof JavacDef.JavacFunExprDef) {
|
||||
out.writeByte(FUN_EXPR_MARKER);
|
||||
} else {
|
||||
throw new IllegalStateException("unknown type: " + def.getClass());
|
||||
}
|
||||
refExternalizer.save(out, def.getDefinedElement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavacDef read(@NotNull DataInput in) throws IOException {
|
||||
final byte marker = in.readByte();
|
||||
switch (marker) {
|
||||
case CLASS_MARKER:
|
||||
final int supersSize = in.readInt();
|
||||
JavacRef[] superClasses = new JavacRef[supersSize];
|
||||
for (int i = 0; i < supersSize; i++) {
|
||||
superClasses[i] = refExternalizer.read(in);
|
||||
}
|
||||
return new JavacDef.JavacClassDef(refExternalizer.read(in), superClasses);
|
||||
case FUN_EXPR_MARKER:
|
||||
return new JavacDef.JavacFunExprDef(refExternalizer.read(in));
|
||||
default: throw new IllegalStateException("unknown marker " + marker);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static DataExternalizer<JavacRef> createRefExternalizer() {
|
||||
return new DataExternalizer<JavacRef>() {
|
||||
private static final byte CLASS_MARKER = 0;
|
||||
private static final byte METHOD_MARKER = 1;
|
||||
private static final byte FIELD_MARKER = 2;
|
||||
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, JavacRef ref) throws IOException {
|
||||
if (ref instanceof JavacRef.JavacClass) {
|
||||
out.writeByte(CLASS_MARKER);
|
||||
out.writeBoolean(((JavacRef.JavacClass)ref).isAnonymous());
|
||||
}
|
||||
else if (ref instanceof JavacRef.JavacField) {
|
||||
out.writeByte(FIELD_MARKER);
|
||||
writeBytes(out, ref.getOwnerName());
|
||||
}
|
||||
else if (ref instanceof JavacRef.JavacMethod) {
|
||||
out.writeByte(METHOD_MARKER);
|
||||
writeBytes(out, ref.getOwnerName());
|
||||
out.write(((JavacRef.JavacMethod)ref).getParamCount());
|
||||
} else {
|
||||
throw new IllegalStateException("unknown type: " + ref.getClass());
|
||||
}
|
||||
out.writeLong(ref.getFlags());
|
||||
writeBytes(out, ref.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavacRef read(@NotNull DataInput in) throws IOException {
|
||||
final byte marker = in.readByte();
|
||||
switch (marker) {
|
||||
case CLASS_MARKER:
|
||||
return new JavacRef.JavacClassImpl(in.readBoolean(), in.readLong(), readBytes(in));
|
||||
case METHOD_MARKER:
|
||||
return new JavacRef.JavacMethodImpl(readBytes(in), in.readByte(), in.readLong(), readBytes(in));
|
||||
case FIELD_MARKER:
|
||||
return new JavacRef.JavacFieldImpl(readBytes(in), in.readLong(), readBytes(in));
|
||||
default:
|
||||
throw new IllegalStateException("unknown marker " + marker);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBytes(DataOutput out, byte[] bytes) throws IOException {
|
||||
out.writeInt(bytes.length);
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
private byte[] readBytes(DataInput in) throws IOException {
|
||||
final int len = in.readInt();
|
||||
final byte[] buf = new byte[len];
|
||||
in.readFully(buf);
|
||||
return buf;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -15,14 +15,15 @@
|
||||
*/
|
||||
package org.jetbrains.jps.javac.ast.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface JavacFileReferencesRegistrar {
|
||||
void initialize();
|
||||
|
||||
boolean initialize();
|
||||
boolean isEnabled();
|
||||
|
||||
boolean onlyImports();
|
||||
|
||||
void registerFile(String filePath, Set<? extends JavacRef> refs, List<JavacDef> defs);
|
||||
void registerFile(String filePath, Collection<JavacRef> refs, List<JavacDef> defs);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.jetbrains.jps.javac.ast.api;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol;
|
||||
import com.sun.tools.javac.util.Convert;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface JavacRef {
|
||||
@@ -64,7 +65,7 @@ public interface JavacRef {
|
||||
class JavacClassImpl extends JavacRefBase implements JavacClass {
|
||||
private boolean myAnonymous;
|
||||
|
||||
public JavacClassImpl(byte[] name, long flags, boolean anonymous) {
|
||||
public JavacClassImpl(boolean anonymous, long flags, byte[] name) {
|
||||
super(name, flags);
|
||||
myAnonymous = anonymous;
|
||||
}
|
||||
@@ -78,13 +79,18 @@ public interface JavacRef {
|
||||
public boolean isAnonymous() {
|
||||
return myAnonymous;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Convert.utf2string(getName());
|
||||
}
|
||||
}
|
||||
|
||||
class JavacMethodImpl extends JavacRefBase implements JavacMethod {
|
||||
private final byte[] myOwnerName;
|
||||
private final byte myParamCount;
|
||||
|
||||
public JavacMethodImpl(byte[] name, byte[] ownerName, byte paramCount, long flags) {
|
||||
public JavacMethodImpl(byte[] ownerName, byte paramCount, long flags, byte[] name) {
|
||||
super(name, flags);
|
||||
myOwnerName = ownerName;
|
||||
myParamCount = paramCount;
|
||||
@@ -99,12 +105,17 @@ public interface JavacRef {
|
||||
public byte[] getOwnerName() {
|
||||
return myOwnerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Convert.utf2string(getOwnerName()) + "." + Convert.utf2string(getName()) + "(" + myParamCount + ")";
|
||||
}
|
||||
}
|
||||
|
||||
class JavacFieldImpl extends JavacRefBase implements JavacField {
|
||||
private final byte[] myOwnerName;
|
||||
|
||||
public JavacFieldImpl(byte[] name, byte[] ownerName, long flags) {
|
||||
public JavacFieldImpl(byte[] ownerName, long flags, byte[] name) {
|
||||
super(name, flags);
|
||||
myOwnerName = ownerName;
|
||||
}
|
||||
@@ -114,6 +125,11 @@ public interface JavacRef {
|
||||
public byte[] getOwnerName() {
|
||||
return myOwnerName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Convert.utf2string(getOwnerName()) + "." + Convert.utf2string(getName());
|
||||
}
|
||||
}
|
||||
|
||||
abstract class JavacSymbolRefBase implements JavacRef {
|
||||
|
||||
@@ -29,9 +29,12 @@ import org.jetbrains.jps.backwardRefs.CompilerBackwardReferenceIndex
|
||||
import org.jetbrains.jps.backwardRefs.LightRef
|
||||
import org.jetbrains.jps.backwardRefs.index.CompiledFileData
|
||||
import org.jetbrains.jps.backwardRefs.index.CompilerIndices
|
||||
import org.jetbrains.jps.builders.BuildResult
|
||||
import org.jetbrains.jps.builders.JpsBuildTestCase
|
||||
import org.jetbrains.jps.builders.TestProjectBuilderLogger
|
||||
import org.jetbrains.jps.builders.logging.BuildLoggingManager
|
||||
import org.jetbrains.jps.javac.JavaCompilerToolExtension
|
||||
import org.jetbrains.jps.javac.ast.RefCollectorCompilerToolExtension
|
||||
import java.io.File
|
||||
|
||||
abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
|
||||
@@ -58,6 +61,22 @@ abstract class ReferenceIndexTestBase : JpsBuildTestCase() {
|
||||
assertIndexEquals("initialIndex.txt")
|
||||
}
|
||||
|
||||
override fun rebuildAllModules() {
|
||||
try {
|
||||
super.rebuildAllModules()
|
||||
} finally {
|
||||
(JavaCompilerToolExtension.getExtension(RefCollectorCompilerToolExtension.ID) as RefCollectorCompilerToolExtension).clearRegistrars()
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildAllModules(): BuildResult {
|
||||
try {
|
||||
return super.buildAllModules()
|
||||
} finally {
|
||||
(JavaCompilerToolExtension.getExtension(RefCollectorCompilerToolExtension.ID) as RefCollectorCompilerToolExtension).clearRegistrars()
|
||||
}
|
||||
}
|
||||
|
||||
protected fun renameFile(fileToRename: String, newName: String) {
|
||||
rename(orCreateProjectDir.path + "/m/" + fileToRename, newName)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.openapi.editor;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
|
||||
@@ -25,7 +26,7 @@ public abstract class CustomFileDropHandler {
|
||||
public static final ExtensionPointName<CustomFileDropHandler> CUSTOM_DROP_HANDLER_EP =
|
||||
ExtensionPointName.create("com.intellij.customFileDropHandler");
|
||||
|
||||
public abstract boolean canHandle(@NotNull Transferable t, Editor editor);
|
||||
public abstract boolean canHandle(@NotNull Transferable t, @Nullable Editor editor);
|
||||
|
||||
public abstract boolean handleDrop(@NotNull Transferable t, Editor editor, final Project project);
|
||||
public abstract boolean handleDrop(@NotNull Transferable t, @Nullable Editor editor, final Project project);
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -23,6 +23,7 @@ import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -57,12 +58,49 @@ public class SystemInfo extends SystemInfoRt {
|
||||
}
|
||||
|
||||
// version numbers from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724832.aspx
|
||||
public static final boolean isWin10OrNewer = isWindows && isOsVersionAtLeast("10.0");
|
||||
public static final boolean isWin2kOrNewer = isWindows && isOsVersionAtLeast("5.0");
|
||||
public static final boolean isWinXpOrNewer = isWindows && isOsVersionAtLeast("5.1");
|
||||
public static final boolean isWinVistaOrNewer = isWindows && isOsVersionAtLeast("6.0");
|
||||
public static final boolean isWin7OrNewer = isWindows && isOsVersionAtLeast("6.1");
|
||||
public static final boolean isWin8OrNewer = isWindows && isOsVersionAtLeast("6.2");
|
||||
|
||||
/**
|
||||
* https://msdn.microsoft.com/en-us/commandline/wsl/about
|
||||
*/
|
||||
private static final AtomicNullableLazyValue<File> ourWSLBashFile = new AtomicNullableLazyValue<File>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected File compute() {
|
||||
if (!isWin10OrNewer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String windir = System.getenv().get("windir");
|
||||
if (StringUtil.isEmpty(windir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new File(windir + "\\System32\\bash.exe");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @return WSL bash file or null if unavailable
|
||||
*/
|
||||
@Nullable
|
||||
public static File getWSLBashFile() {
|
||||
File bashFile = ourWSLBashFile.getValue();
|
||||
return bashFile == null || !bashFile.exists() ? null : bashFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we are on Windows 10+ and have WSL installed
|
||||
*/
|
||||
public static boolean hasWSL() {
|
||||
return getWSLBashFile() != null;
|
||||
}
|
||||
|
||||
public static final boolean isXWindow = isUnix && !isMac;
|
||||
// https://userbase.kde.org/KDE_System_Administration/Environment_Variables#KDE_FULL_SESSION
|
||||
public static final boolean isKDE = !StringUtil.isEmpty(System.getenv("KDE_FULL_SESSION"));
|
||||
|
||||
+3
-2
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.CustomFileDropHandler;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.io.File;
|
||||
@@ -28,14 +29,14 @@ import java.util.List;
|
||||
public class PatchFileDropHandler extends CustomFileDropHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(@NotNull Transferable t, Editor editor) {
|
||||
public boolean canHandle(@NotNull Transferable t, @Nullable Editor editor) {
|
||||
List<File> list = FileCopyPasteUtil.getFileList(t);
|
||||
if (list == null || list.size() != 1) return false;
|
||||
return PatchFileType.isPatchFile(list.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleDrop(@NotNull Transferable t, Editor editor, @NotNull final Project project) {
|
||||
public boolean handleDrop(@NotNull Transferable t, @Nullable Editor editor, @NotNull final Project project) {
|
||||
List<File> list = FileCopyPasteUtil.getFileList(t);
|
||||
if (list == null || list.size() != 1) return false;
|
||||
return ApplyPatchAction.showAndGetApplyPatch(project, list.get(0));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -43,7 +43,7 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
|
||||
protected final SmartPsiElementPointer<PsiClass> myPointer;
|
||||
protected static final Logger LOG = Logger.getInstance(AbstractRegisterFix.class);
|
||||
|
||||
public AbstractRegisterFix(@NotNull SmartPsiElementPointer<PsiClass> klass) {
|
||||
protected AbstractRegisterFix(@NotNull SmartPsiElementPointer<PsiClass> klass) {
|
||||
myPointer = klass;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,11 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
|
||||
return DevKitBundle.message("inspections.component.not.registered.quickfix.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return DevKitBundle.message("inspections.component.not.registered.quickfix.name", getType());
|
||||
@@ -76,7 +81,7 @@ abstract class AbstractRegisterFix implements LocalQuickFix, DescriptorUtil.Patc
|
||||
return;
|
||||
}
|
||||
LOG.assertTrue(psiFile != null);
|
||||
final Module module = ModuleUtil.findModuleForFile(psiFile.getVirtualFile(), project);
|
||||
final Module module = ModuleUtilCore.findModuleForFile(psiFile.getVirtualFile(), project);
|
||||
assert module != null;
|
||||
|
||||
Runnable command = () -> {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.util;
|
||||
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -23,6 +24,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.xml.XmlFile;
|
||||
import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.xml.DomFileElement;
|
||||
import com.intellij.util.xml.DomManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -67,9 +69,11 @@ public class DescriptorUtil {
|
||||
throw new IncorrectOperationException(DevKitBundle.message("error.plugin.xml.readonly"));
|
||||
}
|
||||
|
||||
for (XmlFile pluginXml : pluginXmls) {
|
||||
patcher.patchPluginXml(pluginXml, klass);
|
||||
}
|
||||
WriteAction.run((ThrowableRunnable<IncorrectOperationException>)() -> {
|
||||
for (XmlFile pluginXml : pluginXmls) {
|
||||
patcher.patchPluginXml(pluginXml, klass);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+5
-22
@@ -5,31 +5,11 @@ import com.jetbrains.edu.learning.settings.StudyOptionsProvider;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class CCOptions implements StudyOptionsProvider {
|
||||
private JRadioButton myHtmlRadioButton;
|
||||
private JRadioButton myMarkdownRadioButton;
|
||||
private JPanel myPanel;
|
||||
private boolean myIsModified = false;
|
||||
|
||||
|
||||
public CCOptions() {
|
||||
myHtmlRadioButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myIsModified = true;
|
||||
}
|
||||
});
|
||||
|
||||
myMarkdownRadioButton.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
myIsModified = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -47,12 +27,15 @@ public class CCOptions implements StudyOptionsProvider {
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
return myIsModified;
|
||||
final boolean htmlAsDefaultTaskFormat = CCSettings.getInstance().useHtmlAsDefaultTaskFormat();
|
||||
return myHtmlRadioButton.isSelected() != htmlAsDefaultTaskFormat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() throws ConfigurationException {
|
||||
CCSettings.getInstance().setUseHtmlAsDefaultTaskFormat(myHtmlRadioButton.isSelected());
|
||||
if (isModified()) {
|
||||
CCSettings.getInstance().setUseHtmlAsDefaultTaskFormat(myHtmlRadioButton.isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+31
-25
@@ -476,23 +476,26 @@ public class StudySerializationUtils {
|
||||
}
|
||||
|
||||
private static JsonObject convertSubtaskInfosToMap(JsonObject stepOptionsJson) {
|
||||
for (JsonElement taskFileElement : stepOptionsJson.getAsJsonArray(FILES)) {
|
||||
JsonObject taskFileObject = taskFileElement.getAsJsonObject();
|
||||
JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS);
|
||||
for (JsonElement placeholder : placeholders) {
|
||||
JsonObject placeholderObject = placeholder.getAsJsonObject();
|
||||
JsonArray infos = placeholderObject.getAsJsonArray(SUBTASK_INFOS);
|
||||
Map<Integer, JsonObject> objectsToInsert = new HashMap<>();
|
||||
for (JsonElement info : infos) {
|
||||
JsonObject object = info.getAsJsonObject();
|
||||
int index = object.getAsJsonPrimitive(INDEX).getAsInt();
|
||||
objectsToInsert.put(index, object);
|
||||
}
|
||||
placeholderObject.remove(SUBTASK_INFOS);
|
||||
JsonObject newInfos = new JsonObject();
|
||||
placeholderObject.add(SUBTASK_INFOS, newInfos);
|
||||
for (Map.Entry<Integer, JsonObject> entry : objectsToInsert.entrySet()) {
|
||||
newInfos.add(entry.getKey().toString(), entry.getValue());
|
||||
final JsonArray files = stepOptionsJson.getAsJsonArray(FILES);
|
||||
if (files != null) {
|
||||
for (JsonElement taskFileElement : files) {
|
||||
JsonObject taskFileObject = taskFileElement.getAsJsonObject();
|
||||
JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS);
|
||||
for (JsonElement placeholder : placeholders) {
|
||||
JsonObject placeholderObject = placeholder.getAsJsonObject();
|
||||
JsonArray infos = placeholderObject.getAsJsonArray(SUBTASK_INFOS);
|
||||
Map<Integer, JsonObject> objectsToInsert = new HashMap<>();
|
||||
for (JsonElement info : infos) {
|
||||
JsonObject object = info.getAsJsonObject();
|
||||
int index = object.getAsJsonPrimitive(INDEX).getAsInt();
|
||||
objectsToInsert.put(index, object);
|
||||
}
|
||||
placeholderObject.remove(SUBTASK_INFOS);
|
||||
JsonObject newInfos = new JsonObject();
|
||||
placeholderObject.add(SUBTASK_INFOS, newInfos);
|
||||
for (Map.Entry<Integer, JsonObject> entry : objectsToInsert.entrySet()) {
|
||||
newInfos.add(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -501,14 +504,17 @@ public class StudySerializationUtils {
|
||||
|
||||
private static JsonObject convertToSecondVersion(JsonObject stepOptionsJson) {
|
||||
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
|
||||
for (JsonElement taskFileElement : stepOptionsJson.getAsJsonArray(FILES)) {
|
||||
JsonObject taskFileObject = taskFileElement.getAsJsonObject();
|
||||
JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS);
|
||||
for (JsonElement placeholder : placeholders) {
|
||||
JsonObject placeholderObject = placeholder.getAsJsonObject();
|
||||
convertToAbsoluteOffset(taskFileObject, placeholderObject);
|
||||
convertMultipleHints(gson, placeholderObject);
|
||||
convertToSubtaskInfo(placeholderObject);
|
||||
final JsonArray files = stepOptionsJson.getAsJsonArray(FILES);
|
||||
if (files != null) {
|
||||
for (JsonElement taskFileElement : files) {
|
||||
JsonObject taskFileObject = taskFileElement.getAsJsonObject();
|
||||
JsonArray placeholders = taskFileObject.getAsJsonArray(PLACEHOLDERS);
|
||||
for (JsonElement placeholder : placeholders) {
|
||||
JsonObject placeholderObject = placeholder.getAsJsonObject();
|
||||
convertToAbsoluteOffset(taskFileObject, placeholderObject);
|
||||
convertMultipleHints(gson, placeholderObject);
|
||||
convertToSubtaskInfo(placeholderObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
return stepOptionsJson;
|
||||
|
||||
+1
@@ -182,6 +182,7 @@ public class EduStepicAuthorizedClient {
|
||||
return stepicUser[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static StepicUser login(@NotNull final String email, @NotNull final String password) {
|
||||
final List<NameValuePair> parameters = new ArrayList<>();
|
||||
if (password.isEmpty()) return null;
|
||||
|
||||
+48
-69
@@ -16,6 +16,8 @@
|
||||
package com.jetbrains.edu.learning.stepic;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
@@ -27,68 +29,28 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.PlainDocument;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
|
||||
public class StepicStudyOptions implements StudyOptionsProvider {
|
||||
private static final String DEFAULT_PASSWORD_TEXT = "************";
|
||||
private static final Logger LOG = Logger.getInstance(StepicStudyOptions.class);
|
||||
private JTextField myLoginTextField;
|
||||
private JPasswordField myPasswordField;
|
||||
private JPanel myPane;
|
||||
private JBCheckBox myEnableTestingFromSamples;
|
||||
|
||||
private boolean myCredentialsModified;
|
||||
|
||||
public StepicStudyOptions() {
|
||||
myPasswordField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
myLoginTextField.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
myCredentialsModified = true;
|
||||
erasePassword();
|
||||
}
|
||||
});
|
||||
|
||||
DocumentListener passwordEraser = new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
if (!myCredentialsModified) {
|
||||
erasePassword();
|
||||
}
|
||||
}
|
||||
};
|
||||
myLoginTextField.getDocument().addDocumentListener(passwordEraser);
|
||||
|
||||
myPasswordField.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (!myCredentialsModified && !getPassword().isEmpty()) {
|
||||
erasePassword();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
}
|
||||
});
|
||||
|
||||
myEnableTestingFromSamples.addChangeListener(new ChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
myCredentialsModified = true;
|
||||
}
|
||||
});
|
||||
reset();
|
||||
}
|
||||
|
||||
private void erasePassword() {
|
||||
setPassword("");
|
||||
myCredentialsModified = true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -107,12 +69,15 @@ public class StepicStudyOptions implements StudyOptionsProvider {
|
||||
|
||||
@NotNull
|
||||
private String getPassword() {
|
||||
final String passwordText = String.valueOf(myPasswordField.getPassword());
|
||||
return passwordText.equals(DEFAULT_PASSWORD_TEXT) ? "" : passwordText;
|
||||
return String.valueOf(myPasswordField.getPassword());
|
||||
}
|
||||
|
||||
private void setPassword(@NotNull final String password) {
|
||||
myPasswordField.setText(StringUtil.isEmpty(password) ? null : password);
|
||||
myPasswordField.setText(password);
|
||||
}
|
||||
|
||||
private boolean isTestingFromSamplesEnabled() {
|
||||
return myEnableTestingFromSamples.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,9 +87,8 @@ public class StepicStudyOptions implements StudyOptionsProvider {
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
final StepicUser user = taskManager.getUser();
|
||||
setLogin(user.getEmail());
|
||||
setPassword(DEFAULT_PASSWORD_TEXT);
|
||||
setPassword(user.getPassword());
|
||||
myEnableTestingFromSamples.setSelected(taskManager.isEnableTestingFromSamples());
|
||||
resetCredentialsModification();
|
||||
}
|
||||
else {
|
||||
LOG.warn("No study object is opened");
|
||||
@@ -137,31 +101,42 @@ public class StepicStudyOptions implements StudyOptionsProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
if (myCredentialsModified) {
|
||||
final Project project = StudyUtils.getStudyProject();
|
||||
if (project != null) {
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
taskManager.setEnableTestingFromSamples(myEnableTestingFromSamples.isSelected());
|
||||
public void apply() throws ConfigurationException {
|
||||
final Project project = StudyUtils.getStudyProject();
|
||||
if (project != null) {
|
||||
StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
|
||||
if (isTestingFromSamplesEnabled() != taskManager.isEnableTestingFromSamples()){
|
||||
taskManager.setEnableTestingFromSamples(isTestingFromSamplesEnabled());
|
||||
}
|
||||
|
||||
final StepicUser user = taskManager.getUser();
|
||||
final boolean isCredentialsModified = !getLogin().equals(user.getEmail()) || !getPassword().equals(user.getPassword());
|
||||
if (isCredentialsModified) {
|
||||
final String login = getLogin();
|
||||
final String password = getPassword();
|
||||
if (!StringUtil.isEmptyOrSpaces(login) && !StringUtil.isEmptyOrSpaces(password)) {
|
||||
final StepicUser user = taskManager.getUser();
|
||||
user.setEmail(login);
|
||||
user.setPassword(password);
|
||||
|
||||
// login to post credentials
|
||||
final StepicUser stepicUser = EduStepicAuthorizedClient.login(login, password);
|
||||
if (stepicUser != null) {
|
||||
taskManager.setUser(stepicUser);
|
||||
final StepicUser[] stepicUser = new StepicUser[1];
|
||||
ProgressManager.getInstance().runProcessWithProgressSynchronously(
|
||||
() -> {
|
||||
ProgressManager.getInstance().getProgressIndicator().setIndeterminate(true);
|
||||
stepicUser[0] = StudyUtils.execCancelable(() -> EduStepicAuthorizedClient.login(login, password));
|
||||
}, "Logging In", true,
|
||||
project);
|
||||
|
||||
if (stepicUser[0] != null && stepicUser[0].getAccessToken() != null) {
|
||||
taskManager.setUser(stepicUser[0]);
|
||||
}
|
||||
else {
|
||||
throw new ConfigurationException("Unable to login");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG.warn("No study object is opened");
|
||||
}
|
||||
}
|
||||
resetCredentialsModification();
|
||||
else {
|
||||
LOG.warn("No study object is opened");
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -171,11 +146,15 @@ public class StepicStudyOptions implements StudyOptionsProvider {
|
||||
}
|
||||
|
||||
public boolean isModified() {
|
||||
return myCredentialsModified;
|
||||
}
|
||||
|
||||
public void resetCredentialsModification() {
|
||||
myCredentialsModified = false;
|
||||
final Project project = StudyUtils.getStudyProject();
|
||||
if (project == null) return false;
|
||||
|
||||
final StudyTaskManager taskManager = StudyTaskManager.getInstance(project);
|
||||
final StepicUser user = taskManager.getUser();
|
||||
|
||||
return !getLogin().equals(user.getEmail())
|
||||
|| !getPassword().equals(user.getPassword())
|
||||
|| !isTestingFromSamplesEnabled() == taskManager.isEnableTestingFromSamples();
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
|
||||
Reference in New Issue
Block a user