Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2014-10-24 17:11:20 +02:00
397 changed files with 5207 additions and 2757 deletions
@@ -1,22 +1,22 @@
/* The following code was generated by JFlex 1.4.3 on 4/29/14 2:27 PM */
/* The following code was generated by JFlex 1.4.3 on 10/24/14 4:28 PM */
/* It's an automatically generated code. Do not modify it. */
package org.intellij.lang.regexp;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import java.util.LinkedList;
import java.util.EnumSet;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.tree.IElementType;
// IDEADEV-11055
@SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" })
import java.util.ArrayList;
import java.util.EnumSet;
@SuppressWarnings("ALL")
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 4/29/14 2:27 PM from the specification file
* <tt>C:/idea_src/ultimate/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
* on 10/24/14 4:28 PM from the specification file
* <tt>/Users/bas/Projects/IntelliJ IDEA Ultimate/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
*/
class _RegExLexer implements FlexLexer {
/** initial size of the lookahead buffer */
@@ -52,73 +52,94 @@ class _RegExLexer implements FlexLexer {
* Translates characters to character classes
*/
private static final String ZZ_CMAP_PACKED =
"\10\0\2\53\1\13\1\0\1\53\1\63\22\0\1\46\1\57\1\0"+
"\1\61\1\15\1\0\1\52\1\62\1\4\1\5\1\17\1\20\1\51"+
"\1\43\1\3\1\0\1\2\7\42\2\1\1\54\1\0\1\60\1\56"+
"\1\55\1\16\1\0\1\24\1\24\1\30\1\27\1\37\1\35\1\25"+
"\1\44\1\32\6\45\1\34\1\36\1\45\1\26\3\45\1\26\1\26"+
"\1\45\1\25\1\10\1\12\1\11\1\14\1\47\1\0\1\23\1\24"+
"\1\31\1\27\1\23\1\23\1\45\1\44\1\32\4\45\1\22\1\45"+
"\1\33\1\45\1\22\1\26\1\22\1\41\1\45\1\26\1\40\1\45"+
"\1\25\1\6\1\21\1\7\54\0\1\45\12\0\1\45\4\0\1\45"+
"\5\0\27\45\1\0\37\45\1\0\u013f\45\31\0\162\45\4\0\14\45"+
"\16\0\5\45\11\0\1\45\213\0\1\45\13\0\1\45\1\0\3\45"+
"\1\0\1\45\1\0\24\45\1\0\54\45\1\0\46\45\1\0\5\45"+
"\4\0\202\45\10\0\105\45\1\0\46\45\2\0\2\45\6\0\20\45"+
"\41\0\46\45\2\0\1\45\7\0\47\45\110\0\33\45\5\0\3\45"+
"\56\0\32\45\5\0\13\45\25\0\12\50\4\0\2\45\1\0\143\45"+
"\1\0\1\45\17\0\2\45\7\0\2\45\12\50\3\45\2\0\1\45"+
"\20\0\1\45\1\0\36\45\35\0\3\45\60\0\46\45\13\0\1\45"+
"\u0152\0\66\45\3\0\1\45\22\0\1\45\7\0\12\45\4\0\12\50"+
"\25\0\10\45\2\0\2\45\2\0\26\45\1\0\7\45\1\0\1\45"+
"\3\0\4\45\3\0\1\45\36\0\2\45\1\0\3\45\4\0\12\50"+
"\2\45\23\0\6\45\4\0\2\45\2\0\26\45\1\0\7\45\1\0"+
"\2\45\1\0\2\45\1\0\2\45\37\0\4\45\1\0\1\45\7\0"+
"\12\50\2\0\3\45\20\0\11\45\1\0\3\45\1\0\26\45\1\0"+
"\7\45\1\0\2\45\1\0\5\45\3\0\1\45\22\0\1\45\17\0"+
"\2\45\4\0\12\50\25\0\10\45\2\0\2\45\2\0\26\45\1\0"+
"\7\45\1\0\2\45\1\0\5\45\3\0\1\45\36\0\2\45\1\0"+
"\3\45\4\0\12\50\1\0\1\45\21\0\1\45\1\0\6\45\3\0"+
"\3\45\1\0\4\45\3\0\2\45\1\0\1\45\1\0\2\45\3\0"+
"\2\45\3\0\3\45\3\0\10\45\1\0\3\45\55\0\11\50\25\0"+
"\10\45\1\0\3\45\1\0\27\45\1\0\12\45\1\0\5\45\46\0"+
"\2\45\4\0\12\50\25\0\10\45\1\0\3\45\1\0\27\45\1\0"+
"\12\45\1\0\5\45\3\0\1\45\40\0\1\45\1\0\2\45\4\0"+
"\12\50\25\0\10\45\1\0\3\45\1\0\27\45\1\0\20\45\46\0"+
"\2\45\4\0\12\50\25\0\22\45\3\0\30\45\1\0\11\45\1\0"+
"\1\45\2\0\7\45\72\0\60\45\1\0\2\45\14\0\7\45\11\0"+
"\12\50\47\0\2\45\1\0\1\45\2\0\2\45\1\0\1\45\2\0"+
"\1\45\6\0\4\45\1\0\7\45\1\0\3\45\1\0\1\45\1\0"+
"\1\45\2\0\2\45\1\0\4\45\1\0\2\45\11\0\1\45\2\0"+
"\5\45\1\0\1\45\11\0\12\50\2\0\2\45\42\0\1\45\37\0"+
"\12\50\26\0\10\45\1\0\42\45\35\0\4\45\164\0\42\45\1\0"+
"\5\45\1\0\2\45\25\0\12\50\6\0\6\45\112\0\46\45\12\0"+
"\51\45\7\0\132\45\5\0\104\45\5\0\122\45\6\0\7\45\1\0"+
"\77\45\1\0\1\45\1\0\4\45\2\0\7\45\1\0\1\45\1\0"+
"\4\45\2\0\47\45\1\0\1\45\1\0\4\45\2\0\37\45\1\0"+
"\1\45\1\0\4\45\2\0\7\45\1\0\1\45\1\0\4\45\2\0"+
"\7\45\1\0\7\45\1\0\27\45\1\0\37\45\1\0\1\45\1\0"+
"\4\45\2\0\7\45\1\0\47\45\1\0\23\45\16\0\11\50\56\0"+
"\125\45\14\0\u026c\45\2\0\10\45\12\0\32\45\5\0\113\45\25\0"+
"\15\45\1\0\4\45\16\0\22\45\16\0\22\45\16\0\15\45\1\0"+
"\3\45\17\0\64\45\43\0\1\45\4\0\1\45\3\0\12\50\46\0"+
"\12\50\6\0\130\45\10\0\51\45\127\0\35\45\51\0\12\50\36\45"+
"\2\0\5\45\u038b\0\154\45\224\0\234\45\4\0\132\45\6\0\26\45"+
"\2\0\6\45\2\0\46\45\2\0\6\45\2\0\10\45\1\0\1\45"+
"\1\0\1\45\1\0\1\45\1\0\37\45\2\0\65\45\1\0\7\45"+
"\1\0\1\45\3\0\3\45\1\0\7\45\3\0\4\45\2\0\6\45"+
"\4\0\15\45\5\0\3\45\1\0\7\45\164\0\1\45\15\0\1\45"+
"\202\0\1\45\4\0\1\45\2\0\12\45\1\0\1\45\3\0\5\45"+
"\6\0\1\45\1\0\1\45\1\0\1\45\1\0\4\45\1\0\3\45"+
"\1\0\7\45\3\0\3\45\5\0\5\45\u0ebb\0\2\45\52\0\5\45"+
"\5\0\2\45\4\0\126\45\6\0\3\45\1\0\132\45\1\0\4\45"+
"\5\0\50\45\4\0\136\45\21\0\30\45\70\0\20\45\u0200\0\u19b6\45"+
"\112\0\u51a6\45\132\0\u048d\45\u0773\0\u2ba4\45\u215c\0\u012e\45\2\0\73\45"+
"\225\0\7\45\14\0\5\45\5\0\1\45\1\0\12\45\1\0\15\45"+
"\1\0\5\45\1\0\1\45\1\0\2\45\1\0\2\45\1\0\154\45"+
"\41\0\u016b\45\22\0\100\45\2\0\66\45\50\0\14\45\164\0\5\45"+
"\1\0\207\45\23\0\12\50\7\0\32\45\6\0\32\45\13\0\131\45"+
"\3\0\6\45\2\0\6\45\2\0\6\45\2\0\3\45\43\0";
"\10\0\2\56\1\13\1\0\1\56\1\66\22\0\1\50\1\62\1\0"+
"\1\64\1\15\1\0\1\55\1\65\1\4\1\5\1\17\1\20\1\54"+
"\1\45\1\3\1\0\1\2\7\44\2\1\1\57\1\0\1\63\1\61"+
"\1\60\1\16\1\0\1\24\1\24\1\32\1\31\1\41\1\37\1\25"+
"\1\46\1\34\2\47\1\51\1\51\1\51\1\47\1\36\1\40\1\47"+
"\1\30\2\47\1\27\1\27\1\27\1\47\1\26\1\10\1\12\1\11"+
"\1\14\1\52\1\0\1\23\1\24\1\33\1\31\1\23\1\23\1\47"+
"\1\46\1\34\4\47\1\22\1\47\1\35\1\47\1\22\1\27\1\22"+
"\1\43\1\27\1\27\1\42\1\47\1\25\1\6\1\21\1\7\54\0"+
"\1\47\12\0\1\47\4\0\1\47\5\0\27\47\1\0\37\47\1\0"+
"\u01ca\47\4\0\14\47\16\0\5\47\7\0\1\47\1\0\1\47\201\0"+
"\5\47\1\0\2\47\2\0\4\47\10\0\1\47\1\0\3\47\1\0"+
"\1\47\1\0\24\47\1\0\123\47\1\0\213\47\10\0\236\47\11\0"+
"\46\47\2\0\1\47\7\0\47\47\110\0\33\47\5\0\3\47\55\0"+
"\53\47\25\0\12\53\4\0\2\47\1\0\143\47\1\0\1\47\17\0"+
"\2\47\7\0\2\47\12\53\3\47\2\0\1\47\20\0\1\47\1\0"+
"\36\47\35\0\131\47\13\0\1\47\16\0\12\53\41\47\11\0\2\47"+
"\4\0\1\47\5\0\26\47\4\0\1\47\11\0\1\47\3\0\1\47"+
"\27\0\31\47\107\0\1\47\1\0\13\47\127\0\66\47\3\0\1\47"+
"\22\0\1\47\7\0\12\47\4\0\12\53\1\0\7\47\1\0\7\47"+
"\5\0\10\47\2\0\2\47\2\0\26\47\1\0\7\47\1\0\1\47"+
"\3\0\4\47\3\0\1\47\20\0\1\47\15\0\2\47\1\0\3\47"+
"\4\0\12\53\2\47\23\0\6\47\4\0\2\47\2\0\26\47\1\0"+
"\7\47\1\0\2\47\1\0\2\47\1\0\2\47\37\0\4\47\1\0"+
"\1\47\7\0\12\53\2\0\3\47\20\0\11\47\1\0\3\47\1\0"+
"\26\47\1\0\7\47\1\0\2\47\1\0\5\47\3\0\1\47\22\0"+
"\1\47\17\0\2\47\4\0\12\53\25\0\10\47\2\0\2\47\2\0"+
"\26\47\1\0\7\47\1\0\2\47\1\0\5\47\3\0\1\47\36\0"+
"\2\47\1\0\3\47\4\0\12\53\1\0\1\47\21\0\1\47\1\0"+
"\6\47\3\0\3\47\1\0\4\47\3\0\2\47\1\0\1\47\1\0"+
"\2\47\3\0\2\47\3\0\3\47\3\0\14\47\26\0\1\47\25\0"+
"\12\53\25\0\10\47\1\0\3\47\1\0\27\47\1\0\12\47\1\0"+
"\5\47\3\0\1\47\32\0\2\47\6\0\2\47\4\0\12\53\25\0"+
"\10\47\1\0\3\47\1\0\27\47\1\0\12\47\1\0\5\47\3\0"+
"\1\47\40\0\1\47\1\0\2\47\4\0\12\53\1\0\2\47\22\0"+
"\10\47\1\0\3\47\1\0\51\47\2\0\1\47\20\0\1\47\21\0"+
"\2\47\4\0\12\53\12\0\6\47\5\0\22\47\3\0\30\47\1\0"+
"\11\47\1\0\1\47\2\0\7\47\72\0\60\47\1\0\2\47\14\0"+
"\7\47\11\0\12\53\47\0\2\47\1\0\1\47\2\0\2\47\1\0"+
"\1\47\2\0\1\47\6\0\4\47\1\0\7\47\1\0\3\47\1\0"+
"\1\47\1\0\1\47\2\0\2\47\1\0\4\47\1\0\2\47\11\0"+
"\1\47\2\0\5\47\1\0\1\47\11\0\12\53\2\0\4\47\40\0"+
"\1\47\37\0\12\53\26\0\10\47\1\0\44\47\33\0\5\47\163\0"+
"\53\47\24\0\1\47\12\53\6\0\6\47\4\0\4\47\3\0\1\47"+
"\3\0\2\47\7\0\3\47\4\0\15\47\14\0\1\47\1\0\12\53"+
"\6\0\46\47\1\0\1\47\5\0\1\47\2\0\53\47\1\0\u014d\47"+
"\1\0\4\47\2\0\7\47\1\0\1\47\1\0\4\47\2\0\51\47"+
"\1\0\4\47\2\0\41\47\1\0\4\47\2\0\7\47\1\0\1\47"+
"\1\0\4\47\2\0\17\47\1\0\71\47\1\0\4\47\2\0\103\47"+
"\45\0\20\47\20\0\125\47\14\0\u026c\47\2\0\21\47\1\0\32\47"+
"\5\0\113\47\25\0\15\47\1\0\4\47\16\0\22\47\16\0\22\47"+
"\16\0\15\47\1\0\3\47\17\0\64\47\43\0\1\47\4\0\1\47"+
"\3\0\12\53\46\0\12\53\6\0\130\47\10\0\51\47\1\0\1\47"+
"\5\0\106\47\12\0\35\47\51\0\12\53\36\47\2\0\5\47\13\0"+
"\54\47\25\0\7\47\10\0\12\53\46\0\27\47\11\0\65\47\53\0"+
"\12\53\6\0\12\53\15\0\1\47\135\0\57\47\21\0\7\47\4\0"+
"\12\53\51\0\36\47\15\0\2\47\12\53\54\47\32\0\44\47\34\0"+
"\12\53\3\0\3\47\12\53\44\47\153\0\4\47\1\0\4\47\3\0"+
"\2\47\11\0\300\47\100\0\u0116\47\2\0\6\47\2\0\46\47\2\0"+
"\6\47\2\0\10\47\1\0\1\47\1\0\1\47\1\0\1\47\1\0"+
"\37\47\2\0\65\47\1\0\7\47\1\0\1\47\3\0\3\47\1\0"+
"\7\47\3\0\4\47\2\0\6\47\4\0\15\47\5\0\3\47\1\0"+
"\7\47\164\0\1\47\15\0\1\47\20\0\15\47\145\0\1\47\4\0"+
"\1\47\2\0\12\47\1\0\1\47\3\0\5\47\6\0\1\47\1\0"+
"\1\47\1\0\1\47\1\0\4\47\1\0\13\47\2\0\4\47\5\0"+
"\5\47\4\0\1\47\64\0\2\47\u0a7b\0\57\47\1\0\57\47\1\0"+
"\205\47\6\0\4\47\3\0\2\47\14\0\46\47\1\0\1\47\5\0"+
"\1\47\2\0\70\47\7\0\1\47\20\0\27\47\11\0\7\47\1\0"+
"\7\47\1\0\7\47\1\0\7\47\1\0\7\47\1\0\7\47\1\0"+
"\7\47\1\0\7\47\120\0\1\47\u01d5\0\2\47\52\0\5\47\5\0"+
"\2\47\4\0\126\47\6\0\3\47\1\0\132\47\1\0\4\47\5\0"+
"\51\47\3\0\136\47\21\0\33\47\65\0\20\47\u0200\0\u19b6\47\112\0"+
"\u51cd\47\63\0\u048d\47\103\0\56\47\2\0\u010d\47\3\0\20\47\12\53"+
"\2\47\24\0\57\47\20\0\31\47\10\0\106\47\61\0\11\47\2\0"+
"\147\47\2\0\4\47\1\0\4\47\14\0\13\47\115\0\12\47\1\0"+
"\3\47\1\0\4\47\1\0\27\47\35\0\64\47\16\0\62\47\34\0"+
"\12\53\30\0\6\47\3\0\1\47\4\0\12\53\34\47\12\0\27\47"+
"\31\0\35\47\7\0\57\47\34\0\1\47\12\53\46\0\51\47\27\0"+
"\3\47\1\0\10\47\4\0\12\53\6\0\27\47\3\0\1\47\5\0"+
"\60\47\1\0\1\47\3\0\2\47\2\0\5\47\2\0\1\47\1\0"+
"\1\47\30\0\3\47\2\0\13\47\7\0\3\47\14\0\6\47\2\0"+
"\6\47\2\0\6\47\11\0\7\47\1\0\7\47\221\0\43\47\15\0"+
"\12\53\6\0\u2ba4\47\14\0\27\47\4\0\61\47\u2104\0\u016e\47\2\0"+
"\152\47\46\0\7\47\14\0\5\47\5\0\1\47\1\0\12\47\1\0"+
"\15\47\1\0\5\47\1\0\1\47\1\0\2\47\1\0\2\47\1\0"+
"\154\47\41\0\u016b\47\22\0\100\47\2\0\66\47\50\0\14\47\164\0"+
"\5\47\1\0\207\47\23\0\12\53\7\0\32\47\6\0\32\47\13\0"+
"\131\47\3\0\6\47\2\0\6\47\2\0\6\47\2\0\3\47\43\0";
/**
* Translates characters to character classes
@@ -136,17 +157,17 @@ class _RegExLexer implements FlexLexer {
"\1\17\1\20\1\21\1\22\1\23\1\3\1\24\1\25"+
"\1\26\1\27\1\30\1\31\1\32\1\33\1\34\1\35"+
"\1\11\1\36\1\3\1\37\1\40\1\37\1\41\1\42"+
"\1\1\1\43\1\44\1\2\1\45\1\46\1\47\1\50"+
"\1\0\1\51\1\52\1\53\1\54\1\55\1\56\1\57"+
"\1\60\2\61\1\62\1\11\1\63\1\64\1\65\1\52"+
"\1\66\1\67\1\70\1\71\1\72\1\73\1\0\1\74"+
"\1\75\1\76\1\77\1\0\1\100\1\101\1\102\1\103"+
"\2\64\2\65\1\52\1\104\1\105\1\106\1\107\1\0"+
"\1\102\1\64\1\110\2\65\1\111\1\112\1\102\3\65"+
"\1\113";
"\1\43\1\1\1\44\1\45\1\2\1\46\1\47\1\50"+
"\1\51\1\0\1\52\1\53\1\54\1\55\1\56\1\57"+
"\1\60\1\61\2\62\1\63\1\11\1\64\1\65\1\66"+
"\1\53\1\67\1\70\1\71\1\72\1\73\1\74\1\0"+
"\1\75\1\76\1\77\1\100\1\0\1\101\1\102\1\103"+
"\1\104\2\65\1\66\1\53\1\105\1\106\1\107\1\110"+
"\1\0\1\103\1\111\2\65\1\66\1\112\1\113\1\103"+
"\1\65\1\66\1\65\1\114\4\65";
private static int [] zzUnpackAction() {
int [] result = new int[112];
int [] result = new int[116];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -171,23 +192,24 @@ class _RegExLexer implements FlexLexer {
private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\64\0\150\0\234\0\320\0\u0104\0\u0138\0\u016c"+
"\0\u01a0\0\u01d4\0\u0208\0\u023c\0\u0270\0\u02a4\0\u02a4\0\u02d8"+
"\0\u02a4\0\u02a4\0\u030c\0\u0340\0\u02a4\0\u02a4\0\u02a4\0\u02a4"+
"\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u0374\0\u02a4"+
"\0\u03a8\0\u02a4\0\u03dc\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u0410"+
"\0\u02a4\0\u0444\0\u02a4\0\u0478\0\u02a4\0\u02a4\0\u030c\0\u02a4"+
"\0\u02a4\0\u04ac\0\u04e0\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u0514"+
"\0\u02a4\0\u0548\0\u02a4\0\u057c\0\u05b0\0\u02a4\0\u02a4\0\u02a4"+
"\0\u02a4\0\u02a4\0\u02a4\0\u05e4\0\u02a4\0\u02a4\0\u02a4\0\u0618"+
"\0\u064c\0\u0680\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u02a4\0\u02a4"+
"\0\u06b4\0\u02a4\0\u02a4\0\u02a4\0\u06e8\0\u071c\0\u02a4\0\u02a4"+
"\0\u0750\0\u02a4\0\u0784\0\u07b8\0\u07ec\0\u0820\0\u0854\0\u02a4"+
"\0\u02a4\0\u02a4\0\u02a4\0\u0888\0\u08bc\0\u02a4\0\u02a4\0\u08f0"+
"\0\u0924\0\u057c\0\u02a4\0\u02a4\0\u0958\0\u098c\0\u02a4\0\u02a4";
"\0\0\0\67\0\156\0\245\0\334\0\u0113\0\u014a\0\u0181"+
"\0\u01b8\0\u01ef\0\u0226\0\u025d\0\u0294\0\u02cb\0\u02cb\0\u0302"+
"\0\u02cb\0\u02cb\0\u0339\0\u0370\0\u02cb\0\u02cb\0\u02cb\0\u02cb"+
"\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u03a7\0\u02cb"+
"\0\u03de\0\u02cb\0\u0415\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u044c"+
"\0\u02cb\0\u0483\0\u02cb\0\u04ba\0\u02cb\0\u02cb\0\u0339\0\u02cb"+
"\0\u02cb\0\u02cb\0\u04f1\0\u0528\0\u02cb\0\u02cb\0\u02cb\0\u02cb"+
"\0\u055f\0\u02cb\0\u0596\0\u02cb\0\u05cd\0\u0604\0\u02cb\0\u02cb"+
"\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u063b\0\u02cb\0\u02cb\0\u02cb"+
"\0\u0672\0\u06a9\0\u06e0\0\u02cb\0\u02cb\0\u02cb\0\u02cb\0\u02cb"+
"\0\u02cb\0\u0717\0\u02cb\0\u02cb\0\u02cb\0\u074e\0\u0785\0\u02cb"+
"\0\u02cb\0\u07bc\0\u02cb\0\u07f3\0\u082a\0\u0861\0\u0898\0\u02cb"+
"\0\u02cb\0\u02cb\0\u02cb\0\u08cf\0\u0906\0\u02cb\0\u093d\0\u02cb"+
"\0\u0974\0\u05cd\0\u02cb\0\u02cb\0\u09ab\0\u09e2\0\u0a19\0\u02cb"+
"\0\u0a50\0\u0a87\0\u0abe\0\u0af5";
private static int [] zzUnpackRowMap() {
int [] result = new int[112];
int [] result = new int[116];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -212,51 +234,68 @@ class _RegExLexer implements FlexLexer {
private static final String ZZ_TRANS_PACKED_0 =
"\3\16\1\17\1\20\1\21\1\22\1\16\1\23\1\16"+
"\1\24\1\25\1\26\1\27\1\30\1\31\1\32\1\33"+
"\21\16\1\34\2\16\1\35\4\16\1\25\5\16\1\36"+
"\1\16\1\25\12\16\1\37\51\16\1\40\2\41\4\40"+
"\1\42\12\40\20\43\1\41\1\40\2\43\2\40\1\41"+
"\1\44\12\40\11\45\1\46\1\45\1\0\63\45\1\0"+
"\1\47\47\45\6\16\1\22\1\16\1\50\1\51\1\52"+
"\1\53\1\26\26\16\1\34\6\16\1\54\1\53\7\16"+
"\1\53\6\55\1\56\1\55\1\57\1\55\1\24\51\55"+
"\5\60\1\61\14\60\20\62\1\60\1\63\2\62\6\60"+
"\1\64\7\60\13\11\1\65\47\11\1\65\22\60\20\43"+
"\2\60\2\43\7\60\1\66\30\60\20\43\2\60\2\43"+
"\14\60\1\67\6\60\1\61\14\60\20\43\2\60\2\43"+
"\17\60\2\41\2\60\1\61\14\60\20\43\1\41\1\60"+
"\2\43\2\60\1\41\13\60\102\0\1\70\56\0\1\71"+
"\2\0\1\72\47\0\1\73\1\74\1\75\4\76\1\73"+
"\1\76\1\73\1\76\1\77\6\76\2\100\2\101\2\102"+
"\1\103\1\104\1\103\2\105\1\106\1\107\1\106\1\110"+
"\1\111\1\112\1\76\1\113\1\106\1\77\4\73\1\77"+
"\7\73\1\77\37\0\1\114\25\0\2\41\37\0\1\41"+
"\5\0\1\41\14\0\2\43\17\0\21\43\1\0\2\43"+
"\1\0\2\43\24\0\1\115\2\0\1\72\47\0\1\73"+
"\1\74\1\75\4\76\1\73\1\76\1\116\1\76\1\77"+
"\6\76\2\100\2\101\2\102\1\103\1\104\1\103\2\105"+
"\1\106\1\107\1\106\1\110\1\111\1\112\1\76\1\113"+
"\1\106\1\77\4\73\1\77\7\73\1\77\52\0\1\117"+
"\33\0\20\62\2\0\2\62\40\0\20\63\2\0\2\63"+
"\22\0\1\120\27\0\1\121\17\0\2\122\1\123\1\124"+
"\1\125\1\126\1\127\12\0\1\130\53\0\2\74\37\0"+
"\1\74\23\0\1\131\37\0\1\131\21\0\64\132\1\133"+
"\2\134\20\133\2\134\2\133\3\134\3\133\1\134\1\133"+
"\1\134\2\133\1\134\21\133\1\135\2\136\20\135\2\136"+
"\2\135\3\136\3\135\1\136\1\135\1\136\2\135\1\136"+
"\21\135\1\0\1\74\1\137\37\0\1\137\77\0\1\140"+
"\1\0\1\141\61\0\1\142\1\143\4\0\5\144\1\0"+
"\56\144\2\0\1\145\37\0\1\145\21\0\65\146\2\147"+
"\20\146\2\147\2\146\3\147\3\146\1\147\1\146\1\147"+
"\2\146\1\147\21\146\65\150\2\151\20\150\2\151\2\150"+
"\3\151\3\150\1\151\1\150\1\151\2\150\1\151\21\150"+
"\1\0\1\74\1\152\37\0\1\152\21\0\5\144\1\153"+
"\56\144\2\0\1\154\37\0\1\154\21\0\65\155\2\156"+
"\20\155\2\156\2\155\3\156\3\155\1\156\1\155\1\156"+
"\2\155\1\156\21\155\65\157\2\160\20\157\2\160\2\157"+
"\3\160\3\157\1\160\1\157\1\160\2\157\1\160\21\157";
"\23\16\1\34\2\16\1\35\5\16\1\25\5\16\1\36"+
"\1\16\1\25\12\16\1\37\54\16\1\40\2\41\4\40"+
"\1\42\12\40\22\43\1\41\1\40\2\43\1\40\1\43"+
"\1\40\1\41\1\44\12\40\11\45\1\46\1\45\1\0"+
"\66\45\1\0\1\47\52\45\6\16\1\22\1\16\1\50"+
"\1\51\1\52\1\53\1\26\30\16\1\34\7\16\1\54"+
"\1\53\7\16\1\53\6\55\1\56\1\55\1\57\1\55"+
"\1\24\13\55\1\60\1\55\1\60\1\55\1\60\3\55"+
"\1\60\12\55\1\60\15\55\5\61\1\62\14\61\22\63"+
"\1\61\1\64\2\63\1\61\1\63\5\61\1\65\7\61"+
"\13\11\1\66\52\11\1\66\22\61\22\43\2\61\2\43"+
"\1\61\1\43\6\61\1\67\30\61\22\43\2\61\2\43"+
"\1\61\1\43\13\61\1\70\6\61\1\62\14\61\22\43"+
"\2\61\2\43\1\61\1\43\16\61\2\41\2\61\1\62"+
"\14\61\22\43\1\41\1\61\2\43\1\61\1\43\1\61"+
"\1\41\13\61\105\0\1\71\61\0\1\72\2\0\1\73"+
"\52\0\1\74\1\75\1\76\4\77\1\74\1\77\1\74"+
"\1\77\1\100\6\77\2\101\3\102\3\103\1\104\1\105"+
"\1\104\2\106\1\107\1\110\1\107\1\111\1\112\1\113"+
"\1\77\1\114\1\107\1\100\1\107\4\74\1\100\7\74"+
"\1\100\41\0\1\115\26\0\2\41\41\0\1\41\6\0"+
"\1\41\14\0\2\43\17\0\23\43\1\0\2\43\1\0"+
"\3\43\24\0\1\116\2\0\1\73\52\0\1\74\1\75"+
"\1\76\4\77\1\74\1\77\1\117\1\77\1\100\6\77"+
"\2\101\3\102\3\103\1\104\1\105\1\104\2\106\1\107"+
"\1\110\1\107\1\111\1\112\1\113\1\77\1\114\1\107"+
"\1\100\1\107\4\74\1\100\7\74\1\100\55\0\1\120"+
"\33\0\22\63\2\0\2\63\1\0\1\63\37\0\22\64"+
"\2\0\2\64\1\0\1\64\21\0\1\121\31\0\1\122"+
"\20\0\2\123\1\124\1\125\1\126\1\127\1\130\12\0"+
"\1\131\56\0\2\75\41\0\1\75\24\0\1\132\41\0"+
"\1\132\22\0\67\133\1\0\2\134\3\0\1\135\14\0"+
"\2\134\4\0\3\134\3\0\1\134\1\0\1\134\2\0"+
"\1\134\23\0\2\136\20\0\2\136\4\0\3\136\3\0"+
"\1\136\1\0\1\136\2\0\1\136\23\0\1\75\1\137"+
"\41\0\1\137\103\0\1\140\1\0\1\141\64\0\1\142"+
"\1\143\4\0\5\144\1\0\61\144\2\0\1\145\41\0"+
"\1\145\23\0\2\146\20\0\2\146\4\0\3\146\3\0"+
"\1\146\1\0\1\146\2\0\1\146\23\0\2\147\4\0"+
"\1\150\13\0\2\147\4\0\3\147\3\0\1\147\1\0"+
"\1\147\2\0\1\147\23\0\2\151\20\0\2\151\4\0"+
"\3\151\3\0\1\151\1\0\1\151\2\0\1\151\23\0"+
"\1\75\1\152\41\0\1\152\22\0\5\144\1\153\61\144"+
"\2\0\1\154\41\0\1\154\23\0\2\155\4\0\1\146"+
"\13\0\2\155\4\0\3\155\3\0\1\155\1\0\1\155"+
"\2\0\1\155\23\0\2\156\20\0\2\156\4\0\3\156"+
"\3\0\1\156\1\0\1\156\2\0\1\156\23\0\2\157"+
"\4\0\1\146\13\0\2\157\4\0\3\157\3\0\1\157"+
"\1\0\1\157\2\0\1\157\23\0\2\160\20\0\2\160"+
"\4\0\3\160\3\0\1\160\1\0\1\160\2\0\1\160"+
"\23\0\2\161\4\0\1\146\13\0\2\161\4\0\3\161"+
"\3\0\1\161\1\0\1\161\2\0\1\161\23\0\2\162"+
"\4\0\1\146\13\0\2\162\4\0\3\162\3\0\1\162"+
"\1\0\1\162\2\0\1\162\23\0\2\163\4\0\1\146"+
"\13\0\2\163\4\0\3\163\3\0\1\163\1\0\1\163"+
"\2\0\1\163\23\0\2\164\4\0\1\146\13\0\2\164"+
"\4\0\3\164\3\0\1\164\1\0\1\164\2\0\1\164"+
"\23\0\2\164\4\0\1\150\13\0\2\164\4\0\3\164"+
"\3\0\1\164\1\0\1\164\2\0\1\164\22\0";
private static int [] zzUnpackTrans() {
int [] result = new int[2496];
int [] result = new int[2860];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -299,14 +338,14 @@ class _RegExLexer implements FlexLexer {
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\7\0\2\1\4\0\2\11\1\1\2\11\2\1\12\11"+
"\1\1\1\11\1\1\1\11\1\1\4\11\1\1\1\11"+
"\1\1\1\11\1\1\2\11\1\1\2\11\2\1\4\11"+
"\1\1\1\11\1\1\2\11\1\1\3\11\2\1\4\11"+
"\1\1\1\11\1\0\1\11\2\1\6\11\1\1\3\11"+
"\3\1\6\11\1\0\3\11\1\1\1\0\2\11\1\1"+
"\1\11\5\1\4\11\1\0\1\1\2\11\3\1\2\11"+
"\2\1\2\11";
"\1\11\4\1\4\11\1\0\1\1\1\11\1\1\1\11"+
"\2\1\2\11\3\1\1\11\4\1";
private static int [] zzUnpackAttribute() {
int [] result = new int[112];
int [] result = new int[116];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -366,18 +405,21 @@ class _RegExLexer implements FlexLexer {
/* user code: */
// This adds support for nested states. I'm no JFlex pro, so maybe this is overkill, but it works quite well.
private final LinkedList<Integer> states = new LinkedList();
private final ArrayList<Integer> states = new ArrayList();
// This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax)
// as well, but is currently unfinished as it requires to tweak more places than just the lexer.
private boolean xmlSchemaMode;
private int capturingGroupCount = 0;
private boolean allowDanglingMetacharacters;
private boolean allowNestedCharacterClasses;
private boolean allowOctalNoLeadingZero;
private boolean allowHexDigitClass;
private boolean allowEmptyCharacterClass;
private boolean allowHorizontalWhitespaceClass;
private boolean allowCategoryShorthand;
_RegExLexer(EnumSet<RegExpCapability> capabilities) {
this((java.io.Reader)null);
@@ -387,15 +429,18 @@ class _RegExLexer implements FlexLexer {
this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO);
this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE);
this.allowHexDigitClass = capabilities.contains(RegExpCapability.ALLOW_HEX_DIGIT_CLASS);
this.allowHorizontalWhitespaceClass = capabilities.contains(RegExpCapability.ALLOW_HORIZONTAL_WHITESPACE_CLASS);
this.allowEmptyCharacterClass = capabilities.contains(RegExpCapability.ALLOW_EMPTY_CHARACTER_CLASS);
this.allowCategoryShorthand = capabilities.contains(RegExpCapability.UNICODE_CATEGORY_SHORTHAND);
}
private void yypushstate(int state) {
states.addFirst(yystate());
states.add(yystate());
yybegin(state);
}
private void yypopstate() {
final int state = states.removeFirst();
final int state = states.remove(states.size() - 1);
yybegin(state);
}
@@ -435,7 +480,7 @@ class _RegExLexer implements FlexLexer {
char [] map = new char[0x10000];
int i = 0; /* index in packed string */
int j = 0; /* index in unpacked array */
while (i < 1338) {
while (i < 1760) {
int count = packed.charAt(i++);
char value = packed.charAt(i++);
do map[j++] = value; while (--count > 0);
@@ -657,59 +702,55 @@ class _RegExLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 75:
case 76:
{ return RegExpTT.UNICODE_CHAR;
}
case 76: break;
case 77: break;
case 7:
{ if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE;
}
case 77: break;
case 78: break;
case 24:
{ return RegExpTT.COMMA;
}
case 78: break;
case 61:
case 79: break;
case 62:
{ return RegExpTT.POS_LOOKAHEAD;
}
case 79: break;
case 74:
case 80: break;
case 75:
{ return RegExpTT.COMMENT;
}
case 80: break;
case 69:
case 81: break;
case 70:
{ yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP;
}
case 81: break;
case 82: break;
case 14:
{ return RegExpTT.STAR;
}
case 82: break;
case 59:
case 83: break;
case 60:
{ yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF;
}
case 83: break;
case 48:
case 84: break;
case 49:
{ return RegExpTT.CHAR_CLASS;
}
case 84: break;
case 35:
case 85: break;
case 36:
{ handleOptions(); return RegExpTT.OPTIONS_OFF;
}
case 85: break;
case 55:
case 86: break;
case 56:
{ yypopstate(); return RegExpTT.QUOTE_END;
}
case 86: break;
case 34:
case 87: break;
case 35:
{ yybegin(YYINITIAL); return RegExpTT.GROUP_END;
}
case 87: break;
case 5:
{ return RegExpTT.GROUP_BEGIN;
}
case 88: break;
case 36:
case 37:
{ yybegin(YYINITIAL); return RegExpTT.COLON;
}
case 89: break;
@@ -725,7 +766,7 @@ class _RegExLexer implements FlexLexer {
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
}
case 92: break;
case 45:
case 46:
{ return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE;
}
case 93: break;
@@ -733,47 +774,46 @@ class _RegExLexer implements FlexLexer {
{ return RegExpTT.NAME;
}
case 94: break;
case 73:
{ if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR;
return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
}
case 95: break;
case 29:
{ yypopstate(); return RegExpTT.CLASS_END;
}
case 96: break;
case 33:
case 95: break;
case 34:
{ yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
}
case 97: break;
case 51:
case 96: break;
case 52:
{ yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
}
case 98: break;
case 97: break;
case 21:
{ return RegExpTT.NUMBER;
}
case 99: break;
case 98: break;
case 4:
{ return RegExpTT.DOT;
}
case 100: break;
case 71:
case 99: break;
case 72:
{ return RegExpTT.NEG_LOOKBEHIND;
}
case 100: break;
case 33:
{ yypopstate(); if (allowCategoryShorthand) return RegExpTT.CATEGORY_SHORT_HAND; else yypushback(1);
}
case 101: break;
case 43:
case 44:
{ return (allowOctalNoLeadingZero ? RegExpTT.OCT_CHAR : RegExpTT.BAD_OCT_VALUE);
}
case 102: break;
case 40:
case 41:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ yypushstate(CLASS1);
return RegExpTT.CLASS_BEGIN;
}
case 103: break;
case 62:
case 63:
{ return RegExpTT.NEG_LOOKAHEAD;
}
case 104: break;
@@ -781,15 +821,15 @@ class _RegExLexer implements FlexLexer {
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER;
}
case 105: break;
case 60:
case 61:
{ return RegExpTT.NON_CAPT_GROUP;
}
case 106: break;
case 64:
case 65:
{ yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP;
}
case 107: break;
case 65:
case 66:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ if (allowEmptyCharacterClass) {
@@ -813,7 +853,7 @@ class _RegExLexer implements FlexLexer {
{ if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER;
}
case 110: break;
case 50:
case 51:
{ yypushstate(PROP); return RegExpTT.PROPERTY;
}
case 111: break;
@@ -822,23 +862,27 @@ class _RegExLexer implements FlexLexer {
return RegExpTT.CLASS_BEGIN;
}
case 112: break;
case 70:
case 71:
{ return RegExpTT.POS_LOOKBEHIND;
}
case 113: break;
case 42:
{ return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
}
case 114: break;
case 72:
case 73:
{ return RegExpTT.HEX_CHAR;
}
case 115: break;
case 114: break;
case 1:
{ handleOptions(); return RegExpTT.OPTIONS_ON;
}
case 115: break;
case 43:
{ if (yystate() == CLASS2) return RegExpTT.ESC_CHARACTER;
while (yylength() > 2 && Integer.parseInt(yytext().toString().substring(1)) > capturingGroupCount) {
yypushback(1);
}
return RegExpTT.BACKREF;
}
case 116: break;
case 58:
case 59:
{ return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER;
}
case 117: break;
@@ -850,7 +894,7 @@ class _RegExLexer implements FlexLexer {
{ return RegExpTT.MINUS;
}
case 119: break;
case 46:
case 47:
{ return RegExpTT.ESC_CTRL_CHARACTER;
}
case 120: break;
@@ -862,19 +906,19 @@ class _RegExLexer implements FlexLexer {
{ return RegExpTT.QUEST;
}
case 122: break;
case 54:
{ return (allowHexDigitClass ? RegExpTT.CHAR_CLASS : StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
case 5:
{ capturingGroupCount++; return RegExpTT.GROUP_BEGIN;
}
case 123: break;
case 15:
{ return RegExpTT.PLUS;
}
case 124: break;
case 66:
case 67:
{ return RegExpTT.OCT_CHAR;
}
case 125: break;
case 38:
case 39:
{ yybegin(YYINITIAL); return RegExpTT.QUOTE;
}
case 126: break;
@@ -894,7 +938,7 @@ class _RegExLexer implements FlexLexer {
{ yybegin(CLASS1); return RegExpTT.CARET;
}
case 129: break;
case 56:
case 57:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ if (allowNestedCharacterClasses) {
@@ -904,16 +948,16 @@ class _RegExLexer implements FlexLexer {
return RegExpTT.CHARACTER;
}
case 130: break;
case 57:
case 58:
{ if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER;
return RegExpTT.REDUNDANT_ESCAPE;
}
case 131: break;
case 37:
case 38:
{ yybegin(YYINITIAL); return RegExpTT.GT;
}
case 132: break;
case 68:
case 69:
{ yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF;
}
case 133: break;
@@ -925,11 +969,11 @@ class _RegExLexer implements FlexLexer {
{ return RegExpTT.CHARACTER;
}
case 135: break;
case 63:
case 64:
{ yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP;
}
case 136: break;
case 39:
case 40:
{ yybegin(OPTIONS); return RegExpTT.SET_OPTIONS;
}
case 137: break;
@@ -937,7 +981,7 @@ class _RegExLexer implements FlexLexer {
{ yybegin(CLASS2); return RegExpTT.CHARACTER;
}
case 138: break;
case 67:
case 68:
{ if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL;
}
case 139: break;
@@ -949,42 +993,55 @@ class _RegExLexer implements FlexLexer {
{ return RegExpTT.DOLLAR;
}
case 141: break;
case 49:
case 50:
{ if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
case 142: break;
case 41:
case 42:
{ return RegExpTT.REDUNDANT_ESCAPE;
}
case 143: break;
case 47:
{ return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
case 55:
{ return (allowHexDigitClass || allowHorizontalWhitespaceClass ? RegExpTT.CHAR_CLASS : StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
}
case 144: break;
case 48:
{ return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
}
case 145: break;
case 22:
{ yypopstate(); return RegExpTT.RBRACE;
}
case 145: break;
case 53:
case 146: break;
case 54:
{ return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
}
case 146: break;
case 52:
case 147: break;
case 53:
{ return RegExpTT.BAD_HEX_VALUE;
}
case 147: break;
case 148: break;
case 9:
{ return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
case 148: break;
case 149: break;
case 11:
{ return RegExpTT.CARET;
}
case 149: break;
case 44:
case 150: break;
case 45:
{ return RegExpTT.ESC_CHARACTER;
}
case 150: break;
case 151: break;
case 74:
{ if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR;
if (yystate() == CLASS2) return RegExpTT.ESC_CHARACTER;
while (yylength() > 2 && Integer.parseInt(yytext().toString().substring(1)) > capturingGroupCount) {
yypushback(1);
}
return RegExpTT.BACKREF;
}
case 152: break;
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
@@ -89,8 +89,12 @@ public final class DefaultRegExpPropertiesProvider {
private final String[][] myCharacterClasses = {
{"d", "digit: [0-9]"},
{"D", "nondigit: [^0-9]"},
{"h", "horizontal whitespace character: [ \\t\\xA0\\u1680\\u180e\\u2000-\\u200a\\u202f\\u205f\\u3000]"},
{"H", "non-horizontal whitespace character: [^\\h]"},
{"s", "whitespace [ \\t\\n\\x0B\\f\\r]"},
{"S", "non-whitespace [^\\s]"},
{"v", "vertical whitespace character: [\\n\\x0B\\f\\r\\x85\\u2028\\u2029]"},
{"V", "non-vertical whitespace character: [^\\v]"},
{"w", "word character [a-zA-Z_0-9]"},
{"W", "nonword character [^\\w]"},
{"b", "word boundary"},
@@ -30,6 +30,8 @@ public class RegExpBraceMatcher implements PairedBraceMatcher {
new BracePair(RegExpTT.POS_LOOKBEHIND, RegExpTT.GROUP_END, true), new BracePair(RegExpTT.NEG_LOOKBEHIND, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.PYTHON_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.PYTHON_NAMED_GROUP_REF, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.RUBY_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.RUBY_QUOTED_NAMED_GROUP, RegExpTT.GROUP_END, true),
new BracePair(RegExpTT.CLASS_BEGIN, RegExpTT.CLASS_END, false), new BracePair(RegExpTT.LBRACE, RegExpTT.RBRACE, false),
new BracePair(RegExpTT.QUOTE_BEGIN, RegExpTT.QUOTE_END, false),};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -27,4 +27,6 @@ public enum RegExpCapability {
COMMENT_MODE,
ALLOW_HEX_DIGIT_CLASS,
ALLOW_EMPTY_CHARACTER_CLASS,
ALLOW_HORIZONTAL_WHITESPACE_CLASS,
UNICODE_CATEGORY_SHORTHAND
}
@@ -114,12 +114,23 @@ public class RegExpHighlighter extends SyntaxHighlighterBase {
keys1.put(RegExpTT.BOUNDARY, ESC_CHARACTER);
keys1.put(RegExpTT.CTRL, ESC_CHARACTER);
keys1.put(RegExpTT.ESC_CTRL_CHARACTER, ESC_CHARACTER);
keys1.put(RegExpTT.CATEGORY_SHORT_HAND, ESC_CHARACTER);
keys1.put(RegExpTT.REDUNDANT_ESCAPE, REDUNDANT_ESCAPE);
keys1.put(RegExpTT.QUOTE_BEGIN, QUOTE_CHARACTER);
keys1.put(RegExpTT.QUOTE_END, QUOTE_CHARACTER);
keys1.put(RegExpTT.NON_CAPT_GROUP, PARENTHS);
keys1.put(RegExpTT.POS_LOOKBEHIND, PARENTHS);
keys1.put(RegExpTT.NEG_LOOKBEHIND, PARENTHS);
keys1.put(RegExpTT.POS_LOOKAHEAD, PARENTHS);
keys1.put(RegExpTT.NEG_LOOKAHEAD, PARENTHS);
keys1.put(RegExpTT.SET_OPTIONS, PARENTHS);
keys1.put(RegExpTT.PYTHON_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.PYTHON_NAMED_GROUP_REF, PARENTHS);
keys1.put(RegExpTT.RUBY_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.RUBY_QUOTED_NAMED_GROUP, PARENTHS);
keys1.put(RegExpTT.GROUP_BEGIN, PARENTHS);
keys1.put(RegExpTT.GROUP_END, PARENTHS);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -15,6 +15,7 @@
*/
package org.intellij.lang.regexp;
import org.intellij.lang.regexp.psi.RegExpChar;
import org.intellij.lang.regexp.psi.RegExpGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,6 +29,7 @@ public interface RegExpLanguageHost {
boolean supportsPossessiveQuantifiers();
boolean supportsPythonConditionalRefs();
boolean supportsNamedGroupSyntax(RegExpGroup group);
boolean supportsExtendedHexCharacter(RegExpChar regExpChar);
boolean isValidCategory(@NotNull String category);
@NotNull
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -16,6 +16,7 @@
package org.intellij.lang.regexp;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ClassExtension;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
@@ -73,6 +74,14 @@ public final class RegExpLanguageHosts extends ClassExtension<RegExpLanguageHost
}
}
public boolean supportsExtendedHexCharacter(@Nullable RegExpChar regExpChar) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return true;
}
final RegExpLanguageHost host = findRegExpHost(regExpChar);
return host != null && host.supportsExtendedHexCharacter(regExpChar);
}
public boolean supportsNamedGroupSyntax(@Nullable final RegExpGroup group) {
final RegExpLanguageHost host = findRegExpHost(group);
return host != null && host.supportsNamedGroupSyntax(group);
@@ -447,6 +447,10 @@ public class RegExpParser implements PsiParser {
private static void parseProperty(PsiBuilder builder) {
checkMatches(builder, RegExpTT.PROPERTY, "'\\p' expected");
if (builder.getTokenType() == RegExpTT.CATEGORY_SHORT_HAND) {
builder.advanceLexer();
return;
}
checkMatches(builder, RegExpTT.LBRACE, "Character category expected");
if (builder.getTokenType() == RegExpTT.NAME) {
builder.advanceLexer();
@@ -38,7 +38,9 @@ public class RegExpParserDefinition implements ParserDefinition {
@NotNull
public Lexer createLexer(Project project) {
return new RegExpLexer(EnumSet.of(RegExpCapability.NESTED_CHARACTER_CLASSES));
return new RegExpLexer(EnumSet.of(RegExpCapability.NESTED_CHARACTER_CLASSES,
RegExpCapability.ALLOW_HORIZONTAL_WHITESPACE_CLASS,
RegExpCapability.UNICODE_CATEGORY_SHORTHAND));
}
public PsiParser createParser(Project project) {
@@ -75,7 +75,7 @@ public interface RegExpTT {
IElementType ESC_CTRL_CHARACTER = new RegExpElementType("ESC_CTRL_CHARACTER");
// "\\" ("." | "|" | "$" | "^" | "?" | "*" | "+" | "[" | "{" | "(" | ")")
IElementType ESC_CHARACTER = new RegExpElementType("ESC_CHARACTER");
// "\\" ("w" | "W" | "s" | "S" | "d" | "D")
// "\\" ("w" | "W" | "s" | "S" | "d" | "D" | "v" | "V" | "h" | "H")
IElementType CHAR_CLASS = new RegExpElementType("CHAR_CLASS");
// "\\u" XXXX
IElementType UNICODE_CHAR = new RegExpElementType("UNICODE_CHAR");
@@ -87,6 +87,8 @@ public interface RegExpTT {
IElementType CTRL = new RegExpElementType("CTRL");
// "\\p" | "\\P"
IElementType PROPERTY = new RegExpElementType("PROPERTY");
// "L" | "M" | "Z" | "S" | "N" | "P" | "C" after a property escape
IElementType CATEGORY_SHORT_HAND = new RegExpElementType("CATEGORY_SHORT_HAND");
// e.g. "\\#" but also "\\q" which is not a valid escape actually
IElementType REDUNDANT_ESCAPE = new RegExpElementType("REDUNDANT_ESCAPE");
@@ -29,6 +29,8 @@ public interface RegExpGroup extends RegExpAtom {
boolean isRubyNamedGroup();
boolean isNamedGroup();
@Nullable
String getGroupName();
}
@@ -30,7 +30,7 @@ import org.intellij.lang.regexp.psi.RegExpElementVisitor;
public class RegExpCharImpl extends RegExpElementImpl implements RegExpChar {
private static final TokenSet OCT_CHARS = TokenSet.create(RegExpTT.OCT_CHAR, RegExpTT.BAD_OCT_VALUE);
private static final TokenSet HEX_CHARS = TokenSet.create(RegExpTT.HEX_CHAR, RegExpTT.BAD_HEX_VALUE);
private static final TokenSet UNICODE_CHARS = TokenSet.create(RegExpTT.HEX_CHAR, StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN);
private static final TokenSet UNICODE_CHARS = TokenSet.create(RegExpTT.UNICODE_CHAR, StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN);
public RegExpCharImpl(ASTNode astNode) {
super(astNode);
@@ -117,7 +117,12 @@ public class RegExpCharImpl extends RegExpElementImpl implements RegExpChar {
case'c':
return (char)(ch ^ 64);
case'x':
return parseNumber(idx, s, 16, 2, true);
if (s.length() <= idx + 1) return null;
if (s.charAt(idx + 1) == '{') {
final char c = s.charAt(s.length() - 1);
return (c != '}') ? null : parseNumber(idx + 1, s, 16, s.length() - 4, true);
}
return s.length() == 4 ? parseNumber(idx, s, 16, 2, true) : null;
case'u':
return parseNumber(idx, s, 16, 4, true);
case'0':
@@ -145,6 +150,9 @@ public class RegExpCharImpl extends RegExpElementImpl implements RegExpChar {
sum += Integer.valueOf(s.substring(i, i + 1), radix);
}
if (i-start == 0) return null;
if (sum < Character.MIN_CODE_POINT || sum > Character.MAX_CODE_POINT) {
return null;
}
return i-start < len && strict ? null : (char)sum;
} catch (NumberFormatException e1) {
return null;
@@ -56,6 +56,10 @@ public class RegExpGroupImpl extends RegExpElementImpl implements RegExpGroup {
getNode().findChildByType(RegExpTT.RUBY_QUOTED_NAMED_GROUP) != null;
}
public boolean isNamedGroup() {
return getNode().findChildByType(RegExpTT.RUBY_NAMED_GROUP) != null;
}
public String getGroupName() {
if (!isPythonNamedGroup()) {
return null;
@@ -2,13 +2,13 @@
package org.intellij.lang.regexp;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import java.util.LinkedList;
import java.util.EnumSet;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.tree.IElementType;
// IDEADEV-11055
@SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" })
import java.util.ArrayList;
import java.util.EnumSet;
@SuppressWarnings("ALL")
%%
%class _RegExLexer
@@ -21,18 +21,21 @@ import com.intellij.psi.StringEscapesTokenTypes;
%{
// This adds support for nested states. I'm no JFlex pro, so maybe this is overkill, but it works quite well.
private final LinkedList<Integer> states = new LinkedList();
private final ArrayList<Integer> states = new ArrayList();
// This was an idea to use the regex implementation for XML schema regexes (which use a slightly different syntax)
// as well, but is currently unfinished as it requires to tweak more places than just the lexer.
private boolean xmlSchemaMode;
private int capturingGroupCount = 0;
private boolean allowDanglingMetacharacters;
private boolean allowNestedCharacterClasses;
private boolean allowOctalNoLeadingZero;
private boolean allowHexDigitClass;
private boolean allowEmptyCharacterClass;
private boolean allowHorizontalWhitespaceClass;
private boolean allowCategoryShorthand;
_RegExLexer(EnumSet<RegExpCapability> capabilities) {
this((java.io.Reader)null);
@@ -42,15 +45,18 @@ import com.intellij.psi.StringEscapesTokenTypes;
this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO);
this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE);
this.allowHexDigitClass = capabilities.contains(RegExpCapability.ALLOW_HEX_DIGIT_CLASS);
this.allowHorizontalWhitespaceClass = capabilities.contains(RegExpCapability.ALLOW_HORIZONTAL_WHITESPACE_CLASS);
this.allowEmptyCharacterClass = capabilities.contains(RegExpCapability.ALLOW_EMPTY_CHARACTER_CLASS);
this.allowCategoryShorthand = capabilities.contains(RegExpCapability.UNICODE_CATEGORY_SHORTHAND);
}
private void yypushstate(int state) {
states.addFirst(yystate());
states.add(yystate());
yybegin(state);
}
private void yypopstate() {
final int state = states.removeFirst();
final int state = states.remove(states.size() - 1);
yybegin(state);
}
@@ -99,7 +105,7 @@ META={ESCAPE} | {DOT} |
CONTROL="t" | "n" | "r" | "f" | "a" | "e"
BOUNDARY="b" | "B" | "A" | "z" | "Z" | "G"
CLASS="w" | "W" | "s" | "S" | "d" | "D" | "X" | "C"
CLASS="w" | "W" | "s" | "S" | "d" | "D" | "v" | "V" | "X" | "C"
XML_CLASS="c" | "C" | "i" | "I"
PROP="p" | "P"
@@ -118,12 +124,12 @@ HEX_CHAR=[0-9a-fA-F]
{ESCAPE} {ESCAPE} { return RegExpTT.ESC_CHARACTER; }
/* hex escapes */
{ESCAPE} "x" {HEX_CHAR}{2} { return RegExpTT.HEX_CHAR; }
{ESCAPE} "x" {ANY}{0,2} { return RegExpTT.BAD_HEX_VALUE; }
{ESCAPE} "x" ({HEX_CHAR}{2}|{LBRACE}{HEX_CHAR}{1,6}{RBRACE}) { return RegExpTT.HEX_CHAR; }
{ESCAPE} "x" ({HEX_CHAR}?|{LBRACE}{HEX_CHAR}*{RBRACE}?) { return RegExpTT.BAD_HEX_VALUE; }
/* unicode escapes */
{ESCAPE} "u" {HEX_CHAR}{4} { return RegExpTT.UNICODE_CHAR; }
{ESCAPE} "u" {ANY}{0,4} { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; }
{ESCAPE} "u" {HEX_CHAR}{0,3} { return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN; }
/* octal escapes */
{ESCAPE} "0" [0-7]{1,3} { return RegExpTT.OCT_CHAR; }
@@ -141,15 +147,21 @@ HEX_CHAR=[0-9a-fA-F]
subexpressions exist at that point in the regular expression, otherwise the
parser will drop digits until the number is smaller or equal to the existing
number of groups or it is one digit."
So, for 100% compatibility, backrefs > 9 should be resolved by the parser, but
I'm not sure if it's worth the effort - at least not atm.
*/
{ESCAPE} [0-7]{3} { if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR;
return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
if (yystate() == CLASS2) return RegExpTT.ESC_CHARACTER;
while (yylength() > 2 && Integer.parseInt(yytext().toString().substring(1)) > capturingGroupCount) {
yypushback(1);
}
return RegExpTT.BACKREF;
}
{ESCAPE} {DIGITS} { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; }
{ESCAPE} {DIGITS} { if (yystate() == CLASS2) return RegExpTT.ESC_CHARACTER;
while (yylength() > 2 && Integer.parseInt(yytext().toString().substring(1)) > capturingGroupCount) {
yypushback(1);
}
return RegExpTT.BACKREF;
}
{ESCAPE} "-" { return RegExpTT.ESC_CHARACTER; }
{ESCAPE} {META} { return RegExpTT.ESC_CHARACTER; }
@@ -159,7 +171,7 @@ HEX_CHAR=[0-9a-fA-F]
{ESCAPE} {BOUNDARY} { return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER; }
{ESCAPE} {CONTROL} { return RegExpTT.ESC_CTRL_CHARACTER; }
{ESCAPE} [hH] { return (allowHexDigitClass ? RegExpTT.CHAR_CLASS : StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN); }
{ESCAPE} [hH] { return (allowHexDigitClass || allowHorizontalWhitespaceClass ? RegExpTT.CHAR_CLASS : StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN); }
{ESCAPE} [:letter:] { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; }
{ESCAPE} [\n\b\t\r\f ] { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; }
@@ -175,6 +187,7 @@ HEX_CHAR=[0-9a-fA-F]
<PROP> {
{LBRACE} { yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE; }
"L"|"M"|"Z"|"S"|"N"|"P"|"C" { yypopstate(); if (allowCategoryShorthand) return RegExpTT.CATEGORY_SHORT_HAND; else yypushback(1); }
{ANY} { yypopstate(); yypushback(1); }
}
@@ -252,7 +265,7 @@ HEX_CHAR=[0-9a-fA-F]
<YYINITIAL> {
{LPAREN} { return RegExpTT.GROUP_BEGIN; }
{LPAREN} { capturingGroupCount++; return RegExpTT.GROUP_BEGIN; }
{RPAREN} { return RegExpTT.GROUP_END; }
"|" { return RegExpTT.UNION; }
@@ -104,6 +104,13 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
registerFix(a, new RemoveRedundantEscapeAction(ch));
}
}
if (ch.getType() == RegExpChar.Type.HEX) {
if (text.charAt(text.length() - 1) == '}') {
if (!myLanguageHosts.supportsExtendedHexCharacter(ch)) {
myHolder.createErrorAnnotation(ch, "This hex character syntax is not supported");
}
}
}
}
}
@@ -124,14 +131,14 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
public void visitRegExpBackref(final RegExpBackref backref) {
final RegExpGroup group = backref.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved backreference");
final Annotation a = myHolder.createErrorAnnotation(backref, "Unresolved back reference");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
}
else if (PsiTreeUtil.isAncestor(group, backref, true)) {
myHolder.createWarningAnnotation(backref, "Backreference is nested into the capturing group it refers to");
myHolder.createWarningAnnotation(backref, "Back reference is nested into the capturing group it refers to");
}
}
@@ -173,7 +180,7 @@ public final class RegExpAnnotator extends RegExpElementVisitor implements Annot
*/
final RegExpGroup group = groupRef.resolve();
if (group == null) {
final Annotation a = myHolder.createErrorAnnotation(groupRef, "Unresolved backreference");
final Annotation a = myHolder.createErrorAnnotation(groupRef, "Unresolved back reference");
if (a != null) {
// IDEA-9381
a.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
@@ -58,7 +58,7 @@ public class RegExpCompletionTest extends CodeInsightFixtureTestCase {
private void doBackSlashVariantsTest() throws Throwable {
java.util.List<String> nameList = new ArrayList<String>(Arrays.asList("d", "D", "s", "S", "w", "W", "b", "B", "A", "G", "Z", "z", "Q", "E",
"t", "n", "r", "f", "a", "e"));
"t", "n", "r", "f", "a", "e", "h", "H", "v", "V"));
for (String[] stringArray : DefaultRegExpPropertiesProvider.getInstance().getAllKnownProperties()) {
nameList.add("p{" + stringArray[0] + "}");
}
+48 -1
View File
@@ -364,6 +364,18 @@
<pattern>[\p{L}&amp;&amp;[^\p{Lu}]]</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>\pL\pM\pZ\pS\pN\pP\pC\PL\PM\PZ\PS\PN\PP\PC</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>\pA</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>\pl</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>a\p</pattern>
<expected>ERR</expected>
@@ -571,6 +583,14 @@
<pattern>\x4a</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>\x{0}</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>\x{2011F}</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>[\x4a-\x4b]</pattern>
<expected>OK</expected>
@@ -710,6 +730,14 @@
<pattern>([ab]+)=\1</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)\105</pattern>
<expected>OK</expected>
</test>
<test>
<pattern>(.)\11</pattern>
<expected>OK</expected>
</test>
<test verify="false">
<pattern>([ab]+)=\2</pattern>
<expected>ERR</expected>
@@ -719,7 +747,7 @@
<expected>ERR</expected>
</test>
<test verify="false">
<pattern><![CDATA[([ab]+=<warning descr="Backreference is nested into the capturing group it refers to">\1</warning>)]]></pattern>
<pattern><![CDATA[([ab]+=<warning descr="Back reference is nested into the capturing group it refers to">\1</warning>)]]></pattern>
<expected>OK</expected>
</test>
</backrefs>
@@ -771,6 +799,18 @@
<pattern>abc\x1</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>abc\x{</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>abc\x{}</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>abc\x{0</pattern>
<expected>ERR</expected>
</test>
<test>
<pattern>abc\u</pattern>
<expected>ERR</expected>
@@ -1001,4 +1041,11 @@
<expected>OK</expected>
</test>
</bug>
<bug id="IDEA-131542">
<test>
<pattern>\h \H \v \V</pattern>
<expected>OK</expected>
</test>
</bug>
</tests>
Binary file not shown.
+1
View File
@@ -31,6 +31,7 @@
<jvmarg line="&quot;-Dmodules.output=${modules.output}&quot;"/>
<jvmarg line="&quot;-Dgant.script=@{script}&quot;"/>
<jvmarg line="&quot;-Dgant.target=@{target}&quot;"/>
<jvmarg line="-DmaySkipAndroidPlugin=true"/>
<classpath>
<fileset dir="${project.home}/lib/ant/lib">
+2 -2
View File
@@ -12,7 +12,7 @@
<option name="EDITOR_FONT_SIZE" value="12" linux="14"/>
<option name="EDITOR_FONT_NAME" value="Menlo" linux="Source Code Pro"/>
<colors>
<option name="ADDED_LINES_COLOR" value="295622" />
<option name="ADDED_LINES_COLOR" value="384C38" />
<option name="ANNOTATIONS_COLOR" value="8b999f" />
<option name="CARET_COLOR" value="bbbbbb" />
<option name="CARET_ROW_COLOR" value="323232" />
@@ -38,7 +38,7 @@
<option name="INDENT_GUIDE" value="373737" />
<option name="LINE_NUMBERS_COLOR" value="888888" />
<option name="METHOD_SEPARATORS_COLOR" value="4d4d4d" />
<option name="MODIFIED_LINES_COLOR" value="415f69" />
<option name="MODIFIED_LINES_COLOR" value="374752" />
<option name="NOTIFICATION_BACKGROUND" value="5c5c42" />
<option name="READONLY_FRAGMENT_BACKGROUND" value="" />
<option name="RECURSIVE_CALL_ATTRIBUTES" value="574300" />
@@ -19,6 +19,7 @@ import com.intellij.debugger.SourcePosition;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -80,8 +81,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
//noinspection unchecked
final List<SmartStepTarget> targets = new OrderedSet<SmartStepTarget>();
TextRange textRange = element.getTextRange();
final Range<Integer> lines = new Range<Integer>(doc.getLineNumber(textRange.getStartOffset()), doc.getLineNumber(textRange.getEndOffset()));
final Ref<TextRange> textRange = new Ref<TextRange>(lineRange);
final PsiElementVisitor methodCollector = new JavaRecursiveElementVisitor() {
final Stack<PsiMethod> myContextStack = new Stack<PsiMethod>();
@@ -96,12 +96,12 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
@Override
public void visitAnonymousClass(PsiAnonymousClass aClass) {
for (PsiMethod psiMethod : aClass.getMethods()) {
targets.add(new MethodSmartStepTarget(psiMethod, getCurrentParamName(), psiMethod.getBody(), true, lines));
targets.add(new MethodSmartStepTarget(psiMethod, getCurrentParamName(), psiMethod.getBody(), true, null));
}
}
public void visitLambdaExpression(PsiLambdaExpression expression) {
targets.add(new LambdaSmartStepTarget(expression, getCurrentParamName(), expression.getBody(), myNextLambdaExpressionOrdinal++, lines));
targets.add(new LambdaSmartStepTarget(expression, getCurrentParamName(), expression.getBody(), myNextLambdaExpressionOrdinal++, null));
}
@Override
@@ -111,6 +111,15 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
}
}
@Override
public void visitExpression(PsiExpression expression) {
TextRange range = expression.getTextRange();
if (lineRange.intersects(range)) {
textRange.set(textRange.get().union(range));
}
super.visitExpression(expression);
}
public void visitExpressionList(PsiExpressionList expressionList) {
final PsiMethod psiMethod = myContextStack.isEmpty()? null : myContextStack.peek();
if (psiMethod != null) {
@@ -146,7 +155,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
((PsiMethodCallExpression)expression).getMethodExpression().getReferenceNameElement()
: expression instanceof PsiNewExpression? ((PsiNewExpression)expression).getClassOrAnonymousClassReference() : expression,
false,
lines
null
));
}
try {
@@ -168,6 +177,11 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
}
sibling.accept(methodCollector);
}
Range<Integer> lines = new Range<Integer>(doc.getLineNumber(textRange.get().getStartOffset()), doc.getLineNumber(textRange.get().getEndOffset()));
for (SmartStepTarget target : targets) {
target.setCallingExpressionLines(lines);
}
return targets;
}
return Collections.emptyList();
@@ -27,7 +27,7 @@ public abstract class SmartStepTarget {
private final PsiElement myHighlightElement;
private final String myLabel;
private final boolean myNeedBreakpointRequest;
private final Range<Integer> myExpressionLines;
private Range<Integer> myExpressionLines;
protected SmartStepTarget(@Nullable String label, @Nullable PsiElement highlightElement, boolean needBreakpointRequest, Range<Integer> expressionLines) {
myHighlightElement = highlightElement;
@@ -53,4 +53,8 @@ public abstract class SmartStepTarget {
public Range<Integer> getCallingExpressionLines() {
return myExpressionLines;
}
public void setCallingExpressionLines(Range<Integer> expressionLines) {
myExpressionLines = expressionLines;
}
}
@@ -22,6 +22,7 @@ import com.intellij.debugger.engine.evaluation.EvaluationContext;
import com.intellij.debugger.jdi.StackFrameProxyImpl;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThreeState;
import com.intellij.xdebugger.frame.XStackFrame;
import com.sun.jdi.InternalException;
@@ -101,9 +102,29 @@ public class CompoundPositionManager extends PositionManagerEx {
return Collections.emptyList();
}
private static int mapToOriginalLine(int line, int[] mapping) {
for (int i = 0; i < mapping.length; i += 2) {
if (mapping[i + 1] == line) {
return mapping[i];
}
}
return -1;
}
@Override
@NotNull
public List<Location> locationsOfLine(@NotNull ReferenceType type, @NotNull SourcePosition position) {
VirtualFile file = position.getFile().getVirtualFile();
if (file != null) {
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
if (data != null) {
int line = mapToOriginalLine(position.getLine() + 1, data);
if (line > -1) {
position = SourcePosition.createFromLine(position.getFile(), line - 1);
}
}
}
for (PositionManager positionManager : myPositionManagers) {
try {
return positionManager.locationsOfLine(type, position);
@@ -140,7 +140,7 @@ public class PositionManagerImpl implements PositionManager {
lineNumber = -1;
}
if (psiFile instanceof PsiCompiledElement && lineNumber > -1) {
if (lineNumber > -1) {
VirtualFile file = psiFile.getVirtualFile();
if (file != null) {
int[] data = file.getUserData(LINE_NUMBERS_MAPPING_KEY);
@@ -23,8 +23,8 @@ import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
import com.intellij.debugger.ui.tree.ValueDescriptor;
import com.intellij.debugger.ui.tree.render.CompoundReferenceRenderer;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
import com.intellij.icons.AllIcons;
import com.intellij.ui.components.JBLabel;
import com.intellij.util.IconUtil;
import com.intellij.xdebugger.frame.XFullValueEvaluator;
import org.jetbrains.annotations.NotNull;
@@ -52,11 +52,8 @@ class IconObjectRenderer extends CompoundReferenceRenderer implements FullValueE
@Override
public Icon calcValueIcon(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener listener)
throws EvaluateException {
ImageIcon icon = ImageObjectRenderer.getIcon(evaluationContext, descriptor.getValue(), "iconToBytes");
if (icon != null) {
return IconUtil.cropIcon(icon, 16, 16);
}
return null;
String getterName = AllIcons.Debugger.Value.getIconHeight() <= 16 ? "iconToBytesPreviewNormal" : "iconToBytesPreviewRetina";
return ImageObjectRenderer.getIcon(evaluationContext, descriptor.getValue(), getterName);
}
@NotNull
@@ -15,6 +15,7 @@
*/
package com.intellij.debugger.ui.breakpoints;
import com.intellij.debugger.PositionManager;
import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -81,8 +82,8 @@ public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointPropert
}
@Override
public final boolean canPutAt(@NotNull VirtualFile file, final int line, @NotNull Project project) {
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
public final boolean canPutAt(@NotNull final VirtualFile file, final int line, @NotNull Project project) {
final PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
// JSPX supports jvm debugging, but not in XHTML files
if (psiFile == null || psiFile.getVirtualFile().getFileType() == StdFileTypes.XHTML) {
return false;
@@ -128,6 +129,9 @@ public abstract class JavaLineBreakpointTypeBase<P extends JavaBreakpointPropert
result.set(JavaLineBreakpointType.class);
}
}
else if (file.getUserData(PositionManager.LINE_NUMBERS_MAPPING_KEY) != null) {
result.set(JavaLineBreakpointType.class);
}
}
if (result.isNull()) {
result.set(JavaMethodBreakpointType.class);
@@ -16,9 +16,8 @@
package com.intellij.ide.actions;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.impl.welcomeScreen.NewWelcomeScreen;
/**
* @author Dmitry Avdeev
@@ -34,7 +33,7 @@ public class ImportProjectAction extends ImportModuleAction {
@Override
public void update(AnActionEvent e) {
if (e.getPlace() == ActionPlaces.WELCOME_SCREEN && Registry.is("ide.new.welcome.screen")) {
if (NewWelcomeScreen.isNewWelcomeScreen(e)) {
e.getPresentation().setIcon(AllIcons.Welcome.ImportProject);
}
}
@@ -18,12 +18,11 @@ package com.intellij.ide.actions;
import com.intellij.icons.AllIcons;
import com.intellij.ide.impl.NewProjectUtil;
import com.intellij.ide.projectWizard.NewProjectWizard;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.impl.welcomeScreen.NewWelcomeScreen;
import org.jetbrains.annotations.NotNull;
public class NewProjectAction extends AnAction implements DumbAware {
@@ -34,7 +33,7 @@ public class NewProjectAction extends AnAction implements DumbAware {
@Override
public void update(@NotNull AnActionEvent e) {
if (e.getPlace() == ActionPlaces.WELCOME_SCREEN && Registry.is("ide.new.welcome.screen")) {
if (NewWelcomeScreen.isNewWelcomeScreen(e)) {
e.getPresentation().setIcon(AllIcons.Welcome.CreateNewProject);
}
}
@@ -21,19 +21,17 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
@@ -77,7 +75,7 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec
final PsiElement body = expression.getBody();
if (body instanceof PsiCodeBlock) {
PsiExpression psiExpression = getExpression((PsiCodeBlock)body);
if (psiExpression != null) {
if (psiExpression != null && !findCommentsOutsideExpression(body, psiExpression)) {
if (!expression.isVoidCompatible() && LambdaUtil.isExpressionStatementExpression(psiExpression)) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expression.getParent());
if (parent instanceof PsiExpressionList) {
@@ -110,6 +108,16 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaBatchLocalInspec
}
}
}
private boolean findCommentsOutsideExpression(PsiElement body, PsiExpression psiExpression) {
final Collection<PsiComment> comments = PsiTreeUtil.findChildrenOfType(body, PsiComment.class);
for (PsiComment comment : comments) {
if (!PsiTreeUtil.isAncestor(psiExpression, comment, true)) {
return true;
}
}
return false;
}
};
}
@@ -20,6 +20,7 @@ import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
@@ -100,7 +101,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
addInstruction(new ReturnInstruction(false, null));
new LiveVariablesAnalyzer(myCurrentFlow, myFactory).flushDeadVariablesOnStatementFinish();
if (Registry.is("idea.dfa.live.variables.analysis")) {
new LiveVariablesAnalyzer(myCurrentFlow, myFactory).flushDeadVariablesOnStatementFinish();
}
return myCurrentFlow;
}
@@ -222,24 +222,11 @@ public class DataFlowRunner {
protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
Instruction instruction = instructionState.getInstruction();
if (instruction instanceof MethodCallInstruction) {
PsiCallExpression anchor = ((MethodCallInstruction)instruction).getCallExpression();
if (anchor instanceof PsiNewExpression) {
PsiAnonymousClass anonymousClass = ((PsiNewExpression)anchor).getAnonymousClass();
if (anonymousClass != null) {
registerNestedClosures(instructionState, anonymousClass);
}
}
}
else if (instruction instanceof LambdaInstruction) {
PsiLambdaExpression lambdaExpression = ((LambdaInstruction)instruction).getLambdaExpression();
registerNestedClosures(instructionState, lambdaExpression);
}
else if (instruction instanceof EmptyInstruction) {
PsiElement anchor = ((EmptyInstruction)instruction).getAnchor();
if (anchor instanceof PsiClass) {
registerNestedClosures(instructionState, (PsiClass)anchor);
}
PsiElement closure = DfaUtil.getClosureInside(instruction);
if (closure instanceof PsiClass) {
registerNestedClosures(instructionState, (PsiClass)closure);
} else if (closure instanceof PsiLambdaExpression) {
registerNestedClosures(instructionState, (PsiLambdaExpression)closure);
}
return instruction.accept(this, instructionState.getMemoryState(), visitor);
@@ -15,9 +15,7 @@
*/
package com.intellij.codeInspection.dataFlow;
import com.intellij.codeInspection.dataFlow.instructions.AssignInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.util.MultiValuesMap;
@@ -113,6 +111,26 @@ public class DfaUtil {
return Collections.emptyList();
}
@Nullable
static PsiElement getClosureInside(Instruction instruction) {
if (instruction instanceof MethodCallInstruction) {
PsiCallExpression anchor = ((MethodCallInstruction)instruction).getCallExpression();
if (anchor instanceof PsiNewExpression) {
return ((PsiNewExpression)anchor).getAnonymousClass();
}
}
else if (instruction instanceof LambdaInstruction) {
return ((LambdaInstruction)instruction).getLambdaExpression();
}
else if (instruction instanceof EmptyInstruction) {
PsiElement anchor = ((EmptyInstruction)instruction).getAnchor();
if (anchor instanceof PsiClass) {
return anchor;
}
}
return null;
}
private static class ValuableInstructionVisitor extends StandardInstructionVisitor {
final Map<PsiElement, PlaceResult> myResults = ContainerUtil.newHashMap();
@@ -21,10 +21,11 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.util.PairFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FilteringIterator;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.*;
import com.intellij.util.containers.Queue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,6 +40,26 @@ public class LiveVariablesAnalyzer {
private final Instruction[] myInstructions;
private final MultiMap<Instruction, Instruction> myForwardMap;
private final MultiMap<Instruction, Instruction> myBackwardMap;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final FactoryMap<PsiElement, List<DfaVariableValue>> myClosureReads = new FactoryMap<PsiElement, List<DfaVariableValue>>() {
@Nullable
@Override
protected List<DfaVariableValue> create(PsiElement closure) {
final Set<DfaVariableValue> result = ContainerUtil.newLinkedHashSet();
closure.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PsiReferenceExpression) {
DfaValue value = myFactory.createValue((PsiReferenceExpression)element);
if (value instanceof DfaVariableValue) {
result.add((DfaVariableValue)value);
}
}
super.visitElement(element);
}
});
return ContainerUtil.newArrayList(result);
}
};
public LiveVariablesAnalyzer(ControlFlow flow, DfaValueFactory factory) {
myFactory = factory;
@@ -96,12 +117,36 @@ public class LiveVariablesAnalyzer {
return result;
}
@Nullable
private static DfaVariableValue getWrittenVariable(Instruction instruction) {
if (instruction instanceof AssignInstruction) {
DfaValue value = ((AssignInstruction)instruction).getAssignedValue();
return value instanceof DfaVariableValue ? (DfaVariableValue)value : null;
}
if (instruction instanceof FlushVariableInstruction) return ((FlushVariableInstruction)instruction).getVariable();
return null;
}
@NotNull
private List<DfaVariableValue> getReadVariables(Instruction instruction) {
if (instruction instanceof PushInstruction && !((PushInstruction)instruction).isReferenceWrite()) {
DfaValue value = ((PushInstruction)instruction).getValue();
if (value instanceof DfaVariableValue) {
return Collections.singletonList((DfaVariableValue)value);
}
} else {
PsiElement closure = DfaUtil.getClosureInside(instruction);
if (closure != null) {
return myClosureReads.get(closure);
}
}
return Collections.emptyList();
}
private boolean isInterestingInstruction(Instruction instruction) {
if (instruction == myInstructions[0]) return true;
if (instruction instanceof PushInstruction) return ((PushInstruction)instruction).getValue() instanceof DfaVariableValue;
if (instruction instanceof AssignInstruction) return ((AssignInstruction)instruction).getAssignedValue() != null;
if (!getReadVariables(instruction).isEmpty() || getWrittenVariable(instruction) != null) return true;
return instruction instanceof FinishElementInstruction ||
instruction instanceof FlushVariableInstruction ||
instruction instanceof GotoInstruction ||
instruction instanceof ConditionalGotoInstruction ||
instruction instanceof ReturnInstruction;
@@ -124,34 +169,24 @@ public class LiveVariablesAnalyzer {
}
}
if (instruction instanceof AssignInstruction) {
DfaValue value = ((AssignInstruction)instruction).getAssignedValue();
if (value instanceof DfaVariableValue) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(value.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy((DfaVariableValue)value)) {
liveVars.clear(var.getID());
}
DfaVariableValue written = getWrittenVariable(instruction);
if (written != null) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(written.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy(written)) {
liveVars.clear(var.getID());
}
}
if (instruction instanceof PushInstruction) {
DfaValue value = ((PushInstruction)instruction).getValue();
if (value instanceof DfaVariableValue) {
if (!((PushInstruction)instruction).isReferenceWrite() && !liveVars.get(value.getID())) {
liveVars = (BitSet)liveVars.clone();
} else {
boolean cloned = false;
for (DfaVariableValue value : getReadVariables(instruction)) {
if (!liveVars.get(value.getID())) {
if (!cloned) {
liveVars = (BitSet)liveVars.clone();
cloned = true;
}
liveVars.set(value.getID());
}
}
} else if (instruction instanceof FlushVariableInstruction) {
DfaVariableValue variable = ((FlushVariableInstruction)instruction).getVariable();
if (variable != null) {
liveVars = (BitSet)liveVars.clone();
liveVars.clear(variable.getID());
for (DfaVariableValue var : myFactory.getVarFactory().getAllQualifiedBy(variable)) {
liveVars.clear(var.getID());
}
}
}
return liveVars;
@@ -144,7 +144,9 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
}
for (PsiMethodMember member : elements) {
if (!addParameterToConstructor(project, file, editor, member.getElement(), new PsiField[] {getField()}, cleanupElements)) break;
if (!addParameterToConstructor(project, file, editor, member.getElement(), new PsiField[] {getField()}, cleanupElements)) {
break;
}
}
} else if (!constrs.isEmpty()) {
@@ -317,9 +319,9 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
assert constructor != null;
PsiParameter[] newParameters = constructor.getParameterList().getParameters();
if (newParameters == parameters) return false; //user must have canceled dialog
boolean created = false;
// do not introduce assignment in chanined constructor
if (JavaHighlightUtil.getChainedConstructors(constructor) == null) {
boolean created = false;
for (PsiField field : fields.keySet()) {
final String defaultParamName = fields.get(field);
PsiParameter parameter = findParamByName(defaultParamName, field.getType(), newParameters, parameterInfos);
@@ -334,8 +336,10 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction {
}
created = true;
}
return created;
} else {
return true;
}
return created;
}
private static void notNull(PsiField field, PsiParameter parameter) {
@@ -106,7 +106,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler
}
private PsiGenerationInfo<PsiMethod> generateDelegatePrototype(PsiMethodMember methodCandidate, PsiElement target) throws IncorrectOperationException {
PsiMethod method = GenerateMembersUtil.substituteGenericMethod(methodCandidate.getElement(), methodCandidate.getSubstitutor());
PsiMethod method = GenerateMembersUtil.substituteGenericMethod(methodCandidate.getElement(), methodCandidate.getSubstitutor(), target);
clearMethod(method);
clearModifiers(method);
@@ -475,7 +475,7 @@ public class GenerateMembersUtil {
if (method.isConstructor()) {
return factory.createConstructor(method.getName(), target);
}
return factory.createMethod(method.getName(), PsiType.VOID);
return factory.createMethod(method.getName(), PsiType.VOID, target);
}
private static void substituteReturnType(@NotNull PsiManager manager,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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,12 +21,16 @@ import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.psi.PsiElement;
import org.intellij.lang.regexp.DefaultRegExpPropertiesProvider;
import org.intellij.lang.regexp.RegExpLanguageHost;
import org.intellij.lang.regexp.psi.RegExpChar;
import org.intellij.lang.regexp.psi.RegExpGroup;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.regex.Pattern;
/**
* @author yole
*/
@@ -60,19 +64,31 @@ public class JavaRegExpHost implements RegExpLanguageHost {
@Override
public boolean supportsNamedGroupSyntax(RegExpGroup group) {
if (group.isRubyNamedGroup()) {
final Module module = ModuleUtilCore.findModuleForPsiElement(group);
if (module != null) {
final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
if (sdk != null && sdk.getSdkType() instanceof JavaSdk) {
final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk);
return version != null && version.isAtLeast(JavaSdkVersion.JDK_1_7);
}
}
if (group.isNamedGroup()) {
final JavaSdkVersion version = getJavaVersion(group);
return version != null && version.isAtLeast(JavaSdkVersion.JDK_1_7);
}
return false;
}
@Override
public boolean supportsExtendedHexCharacter(RegExpChar regExpChar) {
final JavaSdkVersion version = getJavaVersion(regExpChar);
return version != null && version.isAtLeast(JavaSdkVersion.JDK_1_7);
}
@Nullable
private static JavaSdkVersion getJavaVersion(PsiElement element) {
final Module module = ModuleUtilCore.findModuleForPsiElement(element);
if (module != null) {
final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
if (sdk != null && sdk.getSdkType() instanceof JavaSdk) {
return JavaSdk.getInstance().getVersion(sdk);
}
}
return null;
}
@Override
public boolean isValidCategory(@NotNull String category) {
return myPropertiesProvider.isValidCategory(category);
@@ -42,7 +42,8 @@ public class RenameFileAction extends AnAction implements DumbAware {
public void update(AnActionEvent e) {
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
Presentation presentation = e.getPresentation();
boolean enabled = file instanceof PsiClassOwner && e.getPlace() != ActionPlaces.EDITOR_POPUP && e.getData(CommonDataKeys.PROJECT) != null;
String place = e.getPlace();
boolean enabled = (file instanceof PsiClassOwner || ActionPlaces.EDITOR_TAB_POPUP.equals(place)) && place != ActionPlaces.EDITOR_POPUP && e.getData(CommonDataKeys.PROJECT) != null;
presentation.setEnabled(enabled);
presentation.setVisible(enabled);
if (enabled) {
@@ -16,6 +16,7 @@
package com.intellij.refactoring.invertBoolean;
import com.intellij.codeInsight.CodeInsightServicesUtil;
import com.intellij.codeInsight.daemon.impl.RecursiveCallLineMarkerProvider;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
@@ -139,7 +140,8 @@ public class InvertBooleanProcessor extends BaseRefactoringProcessor {
if (argumentList != null) {
final PsiExpression[] args = argumentList.getExpressions();
if (index < args.length) {
if (methodExpression == null || methodExpression.getQualifier() == null || !"super".equals(methodExpression.getQualifierExpression().getText())) {
if (methodExpression == null ||
canInvert(methodExpression, args[index] instanceof PsiReferenceExpression && ((PsiReferenceExpression)args[index]).resolve() == myElement)) {
toInvert.add(mySmartPointerManager.createSmartPsiElementPointer(args[index]));
}
}
@@ -181,6 +183,19 @@ public class InvertBooleanProcessor extends BaseRefactoringProcessor {
return result.toArray(new UsageInfo[result.size()]);
}
private static boolean canInvert(PsiReferenceExpression methodExpression, boolean checkRecursive) {
PsiExpression qualifierExpression = methodExpression.getQualifierExpression();
if (qualifierExpression == null || !"super".equals(qualifierExpression.getText())) {
PsiElement parent = methodExpression.getParent();
if (parent instanceof PsiMethodCallExpression) {
return !(checkRecursive && RecursiveCallLineMarkerProvider.isRecursiveMethodCall((PsiMethodCallExpression)parent));
} else {
return true;
}
}
return false;
}
private void addRefsToInvert(final List<SmartPsiElementPointer> toInvert, final PsiNamedElement namedElement) {
final Query<PsiReference> query = namedElement instanceof PsiMethod ?
MethodReferencesSearch.search((PsiMethod)namedElement) :
@@ -197,9 +212,9 @@ public class InvertBooleanProcessor extends BaseRefactoringProcessor {
}
else {
if (namedElement instanceof PsiParameter) { //filter usages in super method calls
if (refExpr.getParent().getParent() instanceof PsiMethodCallExpression) {
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)refExpr.getParent().getParent()).getMethodExpression();
if (methodExpression.getQualifier() != null && "super".equals(methodExpression.getQualifierExpression().getText())) {
PsiElement gParent = refExpr.getParent().getParent();
if (gParent instanceof PsiMethodCallExpression) {
if (!canInvert(((PsiMethodCallExpression)gParent).getMethodExpression(), true)) {
continue;
}
}
@@ -84,6 +84,9 @@ public interface JVMElementFactory {
@NotNull
PsiMethod createMethod(@NotNull @NonNls String name, PsiType returnType) throws IncorrectOperationException;
@NotNull
PsiMethod createMethod(@NotNull @NonNls String name, PsiType returnType, PsiElement context) throws IncorrectOperationException;
/**
* Creates an empty constructor.
*
@@ -247,6 +247,12 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps
return (PsiMethod)CodeStyleManager.getInstance(myManager.getProject()).reformat(method);
}
@NotNull
@Override
public PsiMethod createMethod(@NotNull @NonNls String name, PsiType returnType, PsiElement context) throws IncorrectOperationException {
return createMethodFromText("public " + returnType.getCanonicalText(true) + " " + name + "() {}", context);
}
@NotNull
@Override
public PsiMethod createConstructor() {
@@ -35,6 +35,21 @@ public class ImageSerializer {
return baos.toByteArray();
}
public static byte[] iconToBytesPreview(Icon icon, int maxSize) throws IOException {
if (icon.getIconHeight() <= maxSize && icon.getIconWidth() <= maxSize) {
return imageToBytes(toImage(icon));
}
return null;
}
public static byte[] iconToBytesPreviewNormal(Icon icon) throws IOException {
return iconToBytesPreview(icon, 16);
}
public static byte[] iconToBytesPreviewRetina(Icon icon) throws IOException {
return iconToBytesPreview(icon, 32);
}
public static byte[] iconToBytes(Icon icon) throws IOException {
return imageToBytes(toImage(icon));
}
@@ -0,0 +1,41 @@
import java.util.Optional;
import java.util.function.Function;
class Scratch
{
public static void main(String[] args) throws Exception
{
final Optional<Integer> i = foo();
System.out.println(i);
}
private static Optional<Integer> foo()
{
final Optional<String> s = returnsR(
"foo",
z -> {
if (z.isEmpty())
{
return Optional.empty();
}
else
{
return Optional.of("a string");
}
});
if (s.isPresent())
{
return Optional.of(1);
}
else
{
return Optional.of(2);
}
}
private static <R> R returnsR(String s, Function<String, R> f)
{
return f.apply(s);
}
}
@@ -0,0 +1,16 @@
// "Add constructor parameter" "true"
abstract class FooBar {
protected final String myFoo;
public FooBar(String myFoo) {
this.myFoo = myFoo;
}
public FooBar(Integer interestingType, String myFoo) {
this(myFoo);
}
public FooBar(int i, String myFoo) {
this(myFoo);
}
}
@@ -0,0 +1,15 @@
// "Add constructor parameter" "true"
abstract class FooBar {
protected final String my<caret>Foo;
public FooBar() {
}
public FooBar(Integer interestingType) {
this();
}
public FooBar(int i) {
this();
}
}
@@ -0,0 +1,7 @@
// "Replace with expression lambda" "true"
class Test {
{
Runnable r = () -> System.out.println(""//todo comment
);
}
}
@@ -0,0 +1,19 @@
// "Replace with expression lambda" "false"
class Test {
{
a(() -> {
//my comment here
ret<caret>urn new Object(){};
});
}
void a(Supplier<Object> s) {}
void a(AI<Object> s) {}
interface AI<K> {
void m();
}
interface Supplier<T> {
T get();
}
}
@@ -0,0 +1,9 @@
// "Replace with expression lambda" "true"
class Test {
{
Runnable r = () -> <caret>{
System.out.println(""//todo comment
);
};
}
}
@@ -0,0 +1,19 @@
import org.jetbrains.annotations.Nullable;
class Foo {
void foo(final @Nullable String s, String s2) {
if (s2 == null) return;
if (s == null) return;
System.out.println(s2);
new Runnable() {
@Override
public void run() {
s.hashCode();
}
}.run();
}
}
@@ -0,0 +1,11 @@
class InvertBooleanParameterTest {
void foo(boolean <caret>b) {
boolean c = !b;
foo(b);
foo(true);
}
{
foo(true);
}
}
@@ -0,0 +1,11 @@
class InvertBooleanParameterTest {
void foo(boolean bInverted) {
boolean c = bInverted;
foo(bInverted);
foo(false);
}
{
foo(false);
}
}
@@ -151,6 +151,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA131700() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}
@@ -21,7 +21,9 @@ import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder
import com.intellij.find.FindManager
import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.application.ex.PathManagerEx
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.FoldRegion
import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.ex.FoldingModelEx
import com.intellij.openapi.editor.impl.FoldingModelImpl
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
@@ -397,7 +399,7 @@ class Test {
public void testCustomFolding() {
myFixture.testFolding("$PathManagerEx.testDataPath/codeInsight/folding/${getTestName(false)}.java");
}
public void "test custom folding IDEA-122715 and IDEA-87312"() {
def text = """\
public class Test {
@@ -429,7 +431,7 @@ public class Test {
assert region.placeholderText == "Bar"
count ++;
}
}
}
assert count == 2 : "Not all custom regions are found";
}
@@ -452,7 +454,7 @@ class Foo {
assertEquals 1, foldRegionsCount
assertEquals "Some", foldingModel.allFoldRegions[0].placeholderText
}
public void "test custom folding collapsed by default"() {
def text = """\
class Test {
@@ -1054,6 +1056,37 @@ class Foo {
}
}
public void "test folding state is preserved for unchanged text in bulk mode"() {
def text = """
class Foo {
void m1() {
}
void m2() {
}
}
"""
configure text
assertEquals 2, foldRegionsCount
assertEquals 2, expandedFoldRegionsCount
myFixture.performEditorAction(IdeActions.ACTION_COLLAPSE_ALL_REGIONS)
assertEquals 0, expandedFoldRegionsCount
def document = (DocumentEx)myFixture.editor.document
WriteCommandAction.runWriteCommandAction myFixture.project, {
document.inBulkUpdate = true;
try {
document.insertString(document.getText().indexOf("}") + 1, "\n");
}
finally {
document.inBulkUpdate = false;
}
}
assertEquals 2, foldRegionsCount
assertEquals 0, expandedFoldRegionsCount
}
private int getFoldRegionsCount() {
return myFixture.editor.foldingModel.allFoldRegions.length
}
@@ -242,6 +242,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testManyContinuesNotComplex() { doTest(); }
public void testFinallyNotComplex() { doTest(); }
public void testFlushFurtherUnusedVariables() { doTest(); }
public void testDontFlushVariablesUsedInClosures() { doTest(); }
public void testVariablesDiverge() { doTest(); }
public void testMergeByNullability() { doTest(); }
@@ -15,19 +15,25 @@
*/
package com.intellij.index;
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.impl.CurrentEditorProvider;
import com.intellij.openapi.command.impl.UndoManagerImpl;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.SkipSlowTestLocally;
@@ -47,7 +53,7 @@ import java.util.*;
* Date: Dec 12, 2007
*/
@SkipSlowTestLocally
public class IndexTest extends IdeaTestCase {
public class IndexTest extends CodeInsightTestCase {
public void testUpdate() throws StorageException, IOException {
final File storageFile = FileUtil.createTempFile("indextest", "storage");
@@ -208,8 +214,7 @@ public class IndexTest extends IdeaTestCase {
VfsUtil.saveText(vFile, "class Foo {}");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
@@ -218,20 +223,20 @@ public class IndexTest extends IdeaTestCase {
Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.deleteString(0, document.getTextLength());
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope));
psiFile = null;
PlatformTestUtil.tryGcSoftlyReachableObjects();
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
PsiClass foo = facade.findClass("Foo", scope);
PsiClass foo = myJavaFacade.findClass("Foo", scope);
assertNotNull(foo);
assertTrue(foo.isValid());
assertEquals("class Foo {}", foo.getText());
assertTrue(foo.isValid());
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
}
});
}
@@ -244,8 +249,7 @@ public class IndexTest extends IdeaTestCase {
VfsUtil.saveText(vFile, "");
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
@@ -259,11 +263,11 @@ public class IndexTest extends IdeaTestCase {
FileDocumentManager.getInstance().saveDocument(document);
assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
assertNull(facade.findClass("Foo", scope));
assertNull(myJavaFacade.findClass("Foo", scope));
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNotNull(facade.findClass("Foo", scope));
assertNotNull(facade.findClass("Foo", scope).getText());
assertNotNull(myJavaFacade.findClass("Foo", scope));
assertNotNull(myJavaFacade.findClass("Foo", scope).getText());
// if Foo exists now, mod count should be different
assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
}
@@ -303,9 +307,45 @@ public class IndexTest extends IdeaTestCase {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertEquals(" Foo", file.getText());
assertOneElement(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
}
});
}
public void testUndoToFileContentForUnsavedCommittedDocument() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
final VirtualFile vFile = createChildData(dir, "Foo.java");
VfsUtil.saveText(vFile, "class Foo {}");
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
assertTrue(document != null && document.getModificationStamp() == 0);
final GlobalSearchScope scope = GlobalSearchScope.projectScope(myProject);
assertNotNull(myJavaFacade.findClass("Foo", scope));
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
@Override
public void run() {
document.insertString(0, "import Bar;\n");
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
assertNotNull(myJavaFacade.findClass("Foo", scope));
}
});
final UndoManager undoManager = UndoManager.getInstance(getProject());
final FileEditor selectedEditor = FileEditorManager.getInstance(myProject).openFile(vFile, false)[0];
((UndoManagerImpl)undoManager).setEditorProvider(new CurrentEditorProvider() {
@Override
public FileEditor getCurrentEditor() {
return selectedEditor;
}
});
assertTrue(undoManager.isUndoAvailable(selectedEditor));
FileDocumentManager.getInstance().saveDocument(document);
undoManager.undo(selectedEditor);
assertNotNull(myJavaFacade.findClass("Foo", scope));
}
}
@@ -132,11 +132,11 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
assertTree("-foldersOnTop\n" +
" a.java\n" +
" +b.java\n" +
" c.java\n" +
" a.txt\n" +
" c.txt\n" +
" +b.java\n" +
" +b.txt\n");
" +b.txt\n"+
" c.txt\n");
}
public void testSortByTypeBetweenFilesAndFolders() throws Exception {
@@ -156,11 +156,11 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
assertTree("-sortByTypeBetweenFilesAndFolders\n" +
" a.java\n" +
" b.java\n" +
" +a.java_folder\n" +
" +b.java_folder\n" +
" a.txt\n" +
" b.txt\n" +
" +a.java_folder\n" +
" +a_folder\n" +
" +b.java_folder\n" +
" +b_folder\n");
}
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.smartPointers;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightTestCase;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentEvent;
@@ -25,6 +26,7 @@ import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.event.EditorEventMulticaster;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -37,12 +39,14 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.FileContentUtil;
import gnu.trove.THashSet;
import org.junit.Assert;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.Set;
@@ -434,4 +438,35 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
}
}
}
public void testSmartPointersSurvivePsiFileUnload() throws IOException {
final VirtualFile vfile = myRoot.createChildData(this, "X.txt");
String xxx = "xxx";
String text = xxx + " " + xxx + " " + xxx;
VfsUtil.saveText(vfile, text);
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vfile);
assertTrue(String.valueOf(psiFile), psiFile instanceof PsiPlainTextFile);
SmartPointerManagerImpl manager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
TextRange range1 = TextRange.from(text.indexOf(xxx), xxx.length());
SmartPsiFileRange pointer1 = manager.createSmartPsiFileRangePointer(psiFile, range1);
TextRange range2 = TextRange.from(text.lastIndexOf(xxx), xxx.length());
SmartPsiFileRange pointer2 = manager.createSmartPsiFileRangePointer(psiFile, range2);
assertNotNull(FileDocumentManager.getInstance().getCachedDocument(vfile));
SoftReference<PsiFile> ref = new SoftReference<PsiFile>(psiFile);
psiFile = null;
while (ref.get() != null) {
PlatformTestUtil.tryGcSoftlyReachableObjects();
}
assertNull(FileDocumentManager.getInstance().getCachedDocument(vfile));
assertEquals(pointer1.getRange(), range1);
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@Override
public void run() {
FileDocumentManager.getInstance().getDocument(vfile).insertString(0, " ");
}
});
assertEquals(range1.shiftRight(1), pointer1.getRange());
assertEquals(range2.shiftRight(1), pointer2.getRange());
}
}
@@ -17,6 +17,7 @@ package org.jetbrains.jps.model.serialization;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsEncodingConfigurationService;
@@ -84,6 +85,11 @@ public class JpsEncodingModelSerializerExtension extends JpsModelSerializerExten
JpsEncodingConfigurationService.getInstance().setGlobalEncoding(global, StringUtil.nullize(encoding));
}
@Override
public void loadExtensionWithDefaultSettings(@NotNull JpsGlobal global) {
JpsEncodingConfigurationService.getInstance().setGlobalEncoding(global, CharsetToolkit.UTF8);
}
@Override
public void saveExtension(@NotNull JpsGlobal global, @NotNull Element componentTag) {
componentTag.setAttribute(ENCODING_ATTRIBUTE, JpsEncodingConfigurationService.getInstance().getGlobalEncoding(global));
@@ -1,9 +1,7 @@
package com.intellij.json.formatter;
import com.intellij.formatting.*;
import com.intellij.json.JsonElementTypes;
import com.intellij.json.JsonLanguage;
import com.intellij.json.JsonParserDefinition;
import com.intellij.json.psi.JsonArray;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonProperty;
@@ -23,18 +21,19 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.intellij.json.JsonParserDefinition.JSON_BRACES;
import static com.intellij.json.JsonParserDefinition.JSON_BRACKETS;
import static com.intellij.json.JsonElementTypes.*;
import static com.intellij.json.JsonParserDefinition.*;
import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_COLON;
import static com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_VALUE;
import static com.intellij.json.psi.JsonPsiUtil.hasElementType;
/**
* @author Mikhail Golubev
*/
public class JsonBlock implements ASTBlock {
private static final TokenSet OPEN_BRACES = TokenSet.create(JsonElementTypes.L_BRACKET, JsonElementTypes.L_CURLY);
private static final TokenSet CLOSE_BRACES = TokenSet.create(JsonElementTypes.R_BRACKET, JsonElementTypes.R_CURLY);
private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES);
private static final TokenSet JSON_OPEN_BRACES = TokenSet.create(L_BRACKET, L_CURLY);
private static final TokenSet JSON_CLOSE_BRACES = TokenSet.create(R_BRACKET, R_CURLY);
private static final TokenSet JSON_ALL_BRACES = TokenSet.orSet(JSON_OPEN_BRACES, JSON_CLOSE_BRACES);
private final JsonBlock myParent;
@@ -48,8 +47,6 @@ public class JsonBlock implements ASTBlock {
// lazy initialized on first call to #getSubBlocks()
private List<Block> mySubBlocks = null;
private final Alignment myChildAlignment = Alignment.createAlignment();
private final Alignment myPropertyValueAlignment;
private final Wrap myChildWrap;
@@ -111,28 +108,35 @@ public class JsonBlock implements ASTBlock {
}
private Block makeSubBlock(@NotNull ASTNode childNode) {
final IElementType childNodeType = childNode.getElementType();
Indent indent = Indent.getNoneIndent();
Alignment alignment = null;
Wrap wrap = null;
JsonCodeStyleSettings customSettings = getCustomSettings();
if (isContainer() && childNodeType != JsonElementTypes.COMMA && !BRACES.contains(childNodeType)) {
assert myChildWrap != null && myChildAlignment != null;
wrap = myChildWrap;
alignment = myChildAlignment;
indent = Indent.getNormalIndent();
final JsonCodeStyleSettings customSettings = getCustomSettings();
if (hasElementType(myNode, JSON_CONTAINERS)) {
if (!hasElementType(childNode, COMMA) && !hasElementType(childNode, JSON_ALL_BRACES)) {
assert myChildWrap != null;
wrap = myChildWrap;
indent = Indent.getNormalIndent();
}
else if (hasElementType(childNode, JSON_OPEN_BRACES)) {
if (JsonPsiUtil.isPropertyValue(myPsiElement) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) {
// WEB-13587 Align compound values on opening brace/bracket, not the whole block
assert myParent != null && myParent.myParent != null && myParent.myParent.myPropertyValueAlignment != null;
alignment = myParent.myParent.myPropertyValueAlignment;
}
}
}
// Handle properties alignment
else if (myNode.getElementType() == JsonElementTypes.PROPERTY) {
assert myParent.myNode.getElementType() == JsonElementTypes.OBJECT;
assert myParent.myPropertyValueAlignment != null;
if (childNode.getElementType() == JsonElementTypes.COLON && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) {
else if (hasElementType(myNode, PROPERTY) ) {
assert myParent != null && myParent.myPropertyValueAlignment != null;
if (hasElementType(childNode, COLON) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_COLON) {
alignment = myParent.myPropertyValueAlignment;
}
else if (JsonPsiUtil.isPropertyValue(childNode.getPsi()) && customSettings.PROPERTY_ALIGNMENT == ALIGN_ON_VALUE) {
alignment = myParent.myPropertyValueAlignment;
if (!hasElementType(childNode, JSON_CONTAINERS)) {
alignment = myParent.myPropertyValueAlignment;
}
}
}
return new JsonBlock(this, childNode, mySettings, alignment, indent, wrap);
@@ -160,17 +164,17 @@ public class JsonBlock implements ASTBlock {
@Override
public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) {
final CommonCodeStyleSettings commonSettings = getCommonSettings();
final IElementType leftChildType = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode.getElementType() : null;
final IElementType rightChildType = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode.getElementType() : null;
final ASTNode leftChild = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode : null;
final ASTNode rightChild = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode : null;
// This causes braces/brackets to be on their own lines if whole object/array spans several lines.
if (leftChildType != null && rightChildType != null) {
if (JSON_BRACES.contains(leftChildType) ^ JSON_BRACES.contains(rightChildType)) {
if (leftChild != null && rightChild != null) {
if (hasElementType(leftChild, JSON_BRACES) ^ hasElementType(rightChild, JSON_BRACES)) {
final int numSpaces = commonSettings.SPACE_WITHIN_BRACES ? 1 : 0;
return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(),
commonSettings.KEEP_LINE_BREAKS,
commonSettings.KEEP_BLANK_LINES_IN_CODE);
}
else if (JSON_BRACKETS.contains(leftChildType) ^ JSON_BRACKETS.contains(rightChildType)) {
else if (hasElementType(leftChild, JSON_BRACKETS) ^ hasElementType(rightChild, JSON_BRACKETS)) {
final int numSpaces = commonSettings.SPACE_WITHIN_BRACKETS ? 1 : 0;
return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(),
commonSettings.KEEP_LINE_BREAKS,
@@ -183,8 +187,11 @@ public class JsonBlock implements ASTBlock {
@NotNull
@Override
public ChildAttributes getChildAttributes(int newChildIndex) {
if (isContainer()) {
return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment);
if (hasElementType(myNode, JSON_CONTAINERS)) {
// WEB-13675: For some reason including alignment in child attributes causes
// indents to consist solely of spaces when both USE_TABS and SMART_TAB
// options are enabled.
return new ChildAttributes(Indent.getNormalIndent(), null);
}
// Will use continuation indent for cases like { "foo"<caret> }
return new ChildAttributes(null, null);
@@ -192,15 +199,14 @@ public class JsonBlock implements ASTBlock {
@Override
public boolean isIncomplete() {
IElementType nodeType = myNode.getElementType();
ASTNode lastChildNode = myNode.getLastChildNode();
if (nodeType == JsonElementTypes.OBJECT) {
return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_CURLY;
final ASTNode lastChildNode = myNode.getLastChildNode();
if (hasElementType(myNode, OBJECT)) {
return lastChildNode != null && lastChildNode.getElementType() != R_CURLY;
}
else if (nodeType == JsonElementTypes.ARRAY) {
return lastChildNode != null && lastChildNode.getElementType() != JsonElementTypes.R_BRACKET;
else if (hasElementType(myNode, ARRAY)) {
return lastChildNode != null && lastChildNode.getElementType() != R_BRACKET;
}
else if (myPsiElement instanceof JsonProperty) {
else if (hasElementType(myNode, PROPERTY)) {
return ((JsonProperty)myPsiElement).getValue() == null;
}
return false;
@@ -215,10 +221,6 @@ public class JsonBlock implements ASTBlock {
return node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0;
}
private boolean isContainer() {
return JsonParserDefinition.JSON_CONTAINERS.contains(myNode.getElementType());
}
private JsonCodeStyleSettings getCustomSettings() {
return mySettings.getCustomSettings(JsonCodeStyleSettings.class);
}
@@ -23,13 +23,16 @@ import java.awt.event.ItemListener;
* @author Mikhail Golubev
*/
public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
public static final String SAMPLE = "{\n" +
" \"longKeyName\": true,\n" +
" \"short\": false,\n" +
"\n" +
" \"group2-longKeyName\": null,\n" +
" \"group2-short\": 42\n" +
"}";
public static final String ALIGNMENT_SAMPLE = "{\n" +
" \"foo\": {\n" +
" \"bar\": true,\n" +
" \"baz\": false\n" +
" },\n" +
" \"quux\": [\n" +
" 1, 2.0, 3e0, 4.0e0\n" +
" ],\n" +
" \"longPropertyName\": null\n" +
"}";
private JComboBox myPropertiesAlignmentCombo;
private JPanel myPreviewPanel;
@@ -59,7 +62,6 @@ public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
}
}
});
}
@Override
@@ -82,7 +84,7 @@ public class JsonCodeStylePanel extends CodeStyleAbstractPanel {
@Nullable
@Override
protected String getPreviewText() {
return SAMPLE;
return ALIGNMENT_SAMPLE;
}
@Override
@@ -5,6 +5,7 @@ import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import static com.intellij.json.JsonParserDefinition.JSON_COMMENTARIES;
@@ -86,4 +87,35 @@ public class JsonPsiUtil {
}
return lastSeen.getPsi();
}
/**
* Check that element type of the given AST node belongs to the token set.
* <p/>
* It slightly less verbose than {@code set.contains(node.getElementType())} and overloaded methods with the same name
* allow check ASTNode/PsiElement against both concrete element types and token sets in uniform way.
*/
public static boolean hasElementType(@NotNull ASTNode node, @NotNull TokenSet set) {
return set.contains(node.getElementType());
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet)
*/
public static boolean hasElementType(@NotNull ASTNode node, IElementType... types) {
return hasElementType(node, TokenSet.create(types));
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet)
*/
public static boolean hasElementType(@NotNull PsiElement element, @NotNull TokenSet set) {
return element.getNode() != null && hasElementType(element.getNode(), set);
}
/**
* @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.IElementType...)
*/
public static boolean hasElementType(@NotNull PsiElement element, IElementType... types) {
return element.getNode() != null && hasElementType(element.getNode(), types);
}
}
@@ -0,0 +1,82 @@
package com.intellij.json.psi.impl;
import com.intellij.json.JsonLanguage;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.PsiModificationTrackerImpl;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.PsiTreeChangePreprocessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Mikhail Golubev
*/
public class JsonTreeChangePreprocessor implements PsiTreeChangePreprocessor {
/**
* @see com.intellij.psi.impl.PsiTreeChangePreprocessorBase#treeChanged(com.intellij.psi.impl.PsiTreeChangeEventImpl)
*/
@Override
public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
final PsiElement element = event.getParent();
if (element == null || !(element.getManager() instanceof PsiManagerImpl)) {
return;
}
final PsiModificationTrackerImpl modificationTracker = (PsiModificationTrackerImpl)element.getManager().getModificationTracker();
boolean changedInsideCodeBlock = false;
switch (event.getCode()) {
case BEFORE_CHILDREN_CHANGE:
if (event.getParent() instanceof PsiFile) {
changedInsideCodeBlock = true;
break;
}
case CHILDREN_CHANGED:
if (event.isGenericChange()) {
return;
}
changedInsideCodeBlock = isInsideCodeBlock(event.getParent());
break;
case BEFORE_CHILD_ADDITION:
case BEFORE_CHILD_REMOVAL:
case CHILD_ADDED:
case CHILD_REMOVED:
changedInsideCodeBlock = isInsideCodeBlock(event.getParent());
break;
case BEFORE_PROPERTY_CHANGE:
case PROPERTY_CHANGED:
changedInsideCodeBlock = false;
break;
case BEFORE_CHILD_REPLACEMENT:
case CHILD_REPLACED:
changedInsideCodeBlock = isInsideCodeBlock(event.getParent());
break;
case BEFORE_CHILD_MOVEMENT:
case CHILD_MOVED:
changedInsideCodeBlock = isInsideCodeBlock(event.getOldParent()) && isInsideCodeBlock(event.getNewParent());
break;
}
if (!changedInsideCodeBlock) {
modificationTracker.incOutOfCodeBlockModificationCounter();
}
}
private boolean isInsideCodeBlock(@Nullable PsiElement element) {
if (element instanceof PsiFileSystemItem) {
return false;
}
if (element == null || element.getParent() == null) {
return true;
}
// Consider all elements of JSON PSI as externally visible, i.e. they are out of code block
return !(element.getLanguage() instanceof JsonLanguage);
}
}
@@ -34,8 +34,7 @@ public class JsonStructureViewModel extends StructureViewModelBase implements St
@Override
public boolean isAutoExpand(@NotNull StructureViewTreeElement element) {
final Object value = element.getValue();
return value instanceof PsiFile || value instanceof JsonProperty || value instanceof JsonObject;
return true;
}
@Override
@@ -1,8 +1,10 @@
package com.intellij.json;
import com.intellij.json.formatter.JsonCodeStyleSettings;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
/**
@@ -37,4 +39,49 @@ public class JsonEditingTest extends JsonTestCase {
public void testNormalIndentAfterPropertyWithoutComma() {
doTest("\n");
}
// WEB-13675
public void testIndentWithTabsWhenSmartTabEnabled() {
CommonCodeStyleSettings.IndentOptions indentOptions = getIndentOptions();
CommonCodeStyleSettings.IndentOptions oldSettings = (CommonCodeStyleSettings.IndentOptions)indentOptions.clone();
indentOptions.TAB_SIZE = 4;
indentOptions.INDENT_SIZE = 4;
indentOptions.USE_TAB_CHARACTER = true;
indentOptions.SMART_TABS = true;
try {
doTest("\n\"baz\"");
}
finally {
indentOptions.copyFrom(oldSettings);
}
}
// Moved from JavaScript
// WEB-11600
public void testEnterWhenPropertiesAlignedOnValue() {
doEnterTestForWeb11600();
}
// WEB-11600
public void testEnterWhenPropertiesAlignedOnValue1() {
doEnterTestForWeb11600();
}
private void doEnterTestForWeb11600() {
final JsonCodeStyleSettings settings = getCustomCodeStyleSettings();
final CommonCodeStyleSettings.IndentOptions indentOptions = getIndentOptions();
JsonCodeStyleSettings.PropertyAlignment oldPropertyAlignment = settings.PROPERTY_ALIGNMENT;
int oldIndentSize = indentOptions.INDENT_SIZE;
settings.PROPERTY_ALIGNMENT = JsonCodeStyleSettings.PropertyAlignment.ALIGN_ON_VALUE;
indentOptions.INDENT_SIZE = 4;
try {
doTest("\n");
}
finally {
indentOptions.INDENT_SIZE = oldIndentSize;
settings.PROPERTY_ALIGNMENT = oldPropertyAlignment;
}
}
}
@@ -4,11 +4,13 @@ import com.intellij.formatting.WrapType;
import com.intellij.json.formatter.JsonCodeStyleSettings;
import com.intellij.json.formatter.JsonCodeStyleSettings.PropertyAlignment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.FormatterTestCase;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.TestLoggerFactory;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NotNull;
/**
@@ -59,8 +61,13 @@ public class JsonFormattingTest extends FormatterTestCase {
}
public void testWrapping() throws Exception {
getSettings().setRightMargin(JsonLanguage.INSTANCE, 20);
doTest();
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
getSettings().setRightMargin(JsonLanguage.INSTANCE, 20);
doTest();
}
});
}
// WEB-13587
@@ -73,88 +80,87 @@ public class JsonFormattingTest extends FormatterTestCase {
checkPropertyAlignment(PropertyAlignment.ALIGN_ON_VALUE);
}
private void checkPropertyAlignment(@NotNull PropertyAlignment alignmentType) throws Exception {
final JsonCodeStyleSettings settings = getCustomJsonSettings();
final PropertyAlignment oldAlignment = settings.PROPERTY_ALIGNMENT;
settings.PROPERTY_ALIGNMENT = alignmentType;
try {
doTest();
}
finally {
settings.PROPERTY_ALIGNMENT = oldAlignment;
}
private void checkPropertyAlignment(@NotNull final PropertyAlignment alignmentType) throws Exception {
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
getCustomSettings().PROPERTY_ALIGNMENT = alignmentType;
doTest();
}
});
}
public void testChopDownArrays() throws Exception {
final JsonCodeStyleSettings customSettings = getCustomJsonSettings();
final int oldArrayWrapping = customSettings.ARRAY_WRAPPING;
customSettings.ARRAY_WRAPPING = WrapType.CHOP_DOWN_IF_LONG.getLegacyRepresentation();
final int oldMargin = getSettings().getRightMargin(JsonLanguage.INSTANCE);
getSettings().setRightMargin(JsonLanguage.INSTANCE, 40);
try {
doTest();
}
finally {
getSettings().setRightMargin(JsonLanguage.INSTANCE, oldMargin);
customSettings.ARRAY_WRAPPING = oldArrayWrapping;
}
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
getCustomSettings().ARRAY_WRAPPING = WrapType.CHOP_DOWN_IF_LONG.getLegacyRepresentation();
getSettings().setRightMargin(JsonLanguage.INSTANCE, 40);
doTest();
}
});
}
// Moved from JavaScript
public void testWeb3830() throws Exception {
final CommonCodeStyleSettings.IndentOptions indentOptions = getCommonJsonSettings().getIndentOptions();
assertNotNull(indentOptions);
final int indent = indentOptions.INDENT_SIZE;
final boolean useTabs = indentOptions.USE_TAB_CHARACTER;
final int tabSize = indentOptions.TAB_SIZE;
try {
indentOptions.INDENT_SIZE = 8;
indentOptions.USE_TAB_CHARACTER = true;
indentOptions.TAB_SIZE = 8;
doTest();
}
finally {
indentOptions.INDENT_SIZE = indent;
indentOptions.USE_TAB_CHARACTER = useTabs;
indentOptions.TAB_SIZE = tabSize;
}
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
CommonCodeStyleSettings.IndentOptions options = getIndentOptions();
options.INDENT_SIZE = 8;
options.USE_TAB_CHARACTER = true;
options.TAB_SIZE = 8;
doTest();
}
});
}
public void testReformatJSon() throws Exception {
final CommonCodeStyleSettings.IndentOptions indentOptions = getCommonJsonSettings().getIndentOptions();
assertNotNull(indentOptions);
final int oldIndentSize = indentOptions.INDENT_SIZE;
try {
indentOptions.INDENT_SIZE = 4;
doTest();
}
finally {
indentOptions.INDENT_SIZE = oldIndentSize;
}
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
getIndentOptions().INDENT_SIZE = 4;
doTest();
}
});
}
public void testReformatJSon2() throws Exception {
final CommonCodeStyleSettings.IndentOptions indentOptions = getCommonJsonSettings().getIndentOptions();
assertNotNull(indentOptions);
final int oldIndentSize = indentOptions.INDENT_SIZE;
try {
indentOptions.INDENT_SIZE = 4;
doTest();
}
finally {
indentOptions.INDENT_SIZE = oldIndentSize;
}
withPreservedSettings(new ThrowableRunnable<Exception>() {
@Override
public void run() throws Exception {
getIndentOptions().INDENT_SIZE = 4;
doTest();
}
});
}
@NotNull
private CommonCodeStyleSettings getCommonJsonSettings() {
private CommonCodeStyleSettings.IndentOptions getIndentOptions() {
CommonCodeStyleSettings.IndentOptions options = getCommonSettings().getIndentOptions();
assertNotNull(options);
return options;
}
@NotNull
private CommonCodeStyleSettings getCommonSettings() {
return getSettings().getCommonSettings(JsonLanguage.INSTANCE);
}
@NotNull
private JsonCodeStyleSettings getCustomJsonSettings() {
private JsonCodeStyleSettings getCustomSettings() {
return getSettings().getCustomSettings(JsonCodeStyleSettings.class);
}
protected void withPreservedSettings(@NotNull ThrowableRunnable<Exception> runnable) throws Exception {
final CodeStyleSettings globalSettings = getSettings();
final CodeStyleSettings copy = globalSettings.clone();
try {
runnable.run();
}
finally {
globalSettings.copyFrom(copy);
}
}
}
@@ -1,6 +1,9 @@
package com.intellij.json;
import com.intellij.json.formatter.JsonCodeStyleSettings;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.TestDataPath;
import com.intellij.testFramework.TestLoggerFactory;
@@ -25,6 +28,23 @@ public abstract class JsonTestCase extends LightCodeInsightFixtureTestCase {
super.setUp();
}
@NotNull
protected CommonCodeStyleSettings getCommonCodeStyleSettings() {
return CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JsonLanguage.INSTANCE);
}
@NotNull
protected JsonCodeStyleSettings getCustomCodeStyleSettings() {
return CodeStyleSettingsManager.getSettings(getProject()).getCustomSettings(JsonCodeStyleSettings.class);
}
@NotNull
protected CommonCodeStyleSettings.IndentOptions getIndentOptions() {
final CommonCodeStyleSettings.IndentOptions options = getCommonCodeStyleSettings().getIndentOptions();
assertNotNull(options);
return options;
}
@NotNull
public String getBasePath() {
return "/json/tests/testData";
@@ -0,0 +1,8 @@
{
"scripts" : {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
<caret>
]
}
}
@@ -0,0 +1,7 @@
{
"scripts" : {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"<caret>
]
}
}
@@ -0,0 +1,8 @@
{
"scripts" : {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
],
<caret>
}
}
@@ -0,0 +1,7 @@
{
"scripts" : {
"post-install-cmd": [
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
],<caret>
}
}
@@ -0,0 +1,5 @@
{
"foo": true,
"bar": false,
"baz"
}
@@ -0,0 +1,4 @@
{
"foo": true,
"bar": false,<caret>
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a" : 1,
"aaa" : 2,
"aaaaa": 3
"require-dev" : {
"phpunit/phpunit" : "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story" : "@stable",
"phpunit/dbunit" : "@stable"
},
"minimum-stability": "dev",
"autoload" : {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra" : {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,19 @@
{
"a": 1,
"aaa": 2,
"aaaaa": 3
"require-dev": {
"phpunit/phpunit": "~3.7",
"phpunit/phpunit-selenium": "@stable",
"phpunit/phpunit-story": "@stable",
"phpunit/dbunit": "@stable"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"DreamFactory\\Yii\\": "src/"
}
},
"extra": {
"branch-alias": {
"dev-develop": "1.5.x-dev"
}
}
}
@@ -1,5 +1,8 @@
[
1, <selection>[2], [true,
false</selection>],
1, <selection>[2],
[
true,
false
]</selection>,
null
]
@@ -1,5 +1,8 @@
[
null,
1, [2], [true,
false]
1, [2],
[
true,
false
]
]
@@ -1,6 +1,10 @@
{
"foo": <selection>false, "bar": 42,
"baz": [1, 2,
3</selection>],
"foo": false,
"bar": <selection>42,
"baz": [
1,
2,
3
]</selection>,
"quux": null
}
@@ -1,6 +1,10 @@
{
"foo": false,
"quux": null,
"foo": false, "bar": 42,
"baz": [1, 2,
3]
"bar": 42,
"baz": [
1,
2,
3
]
}
+1
View File
@@ -15,6 +15,7 @@
}
- (id)initWithArgc:(int)anArgc argv:(char **)anArgv;
BOOL validationJavaVersion();
- (void) launch;
@end
+103 -11
View File
@@ -10,12 +10,16 @@
#import "PropertyFileReader.h"
#import "utils.h"
#import <dlfcn.h>
@class NSAlert;
typedef jint (JNICALL *fun_ptr_t_CreateJavaVM)(JavaVM **pvm, void **env, void *args);
NSBundle *vm;
NSString *const JVMOptions = @"JVMOptions";
NSString* minRequiredJavaVersion = @"1.6.0_65-b14-466.1";
NSString* osxVersion = @"10.10";
BOOL javaUpdateRequired = false;
static NSString *const JVMOptions = @"JVMOptions";
@interface NSString (CustomReplacements)
- (NSString *)replaceAll:(NSString *)pattern to:(NSString *)replacement;
@@ -65,6 +69,80 @@ static NSString *const JVMOptions = @"JVMOptions";
return self;
}
NSString* getOSXVersion(){
NSString *versionString;
NSDictionary * sv = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
versionString = [sv objectForKey:@"ProductVersion"];
//NSLog(@"OS X: %@", versionString);
return versionString;
}
void openUrl(){
CFURLRef url = (__bridge CFURLRef)[NSURL URLWithString:@"http://support.apple.com/kb/DL1572"];
NSString *fileString = @"/Applications/Safari.app/";
FSRef appFSURL;
OSStatus stat2=FSPathMakeRef((const UInt8 *)[fileString UTF8String], &appFSURL, NULL);
if (stat2<0) {
NSLog(@"can't create FSRef of Safari");
}
//create the application parameters structure
LSApplicationParameters appParam;
appParam.version = 0; //should always be zero
appParam.flags = kLSLaunchDefaults; //use the default launch options
appParam.application = &appFSURL; //pass in the reference of applications FSRef
appParam.argv = NULL;
appParam.environment = NULL;
appParam.asyncLaunchRefCon = NULL;
appParam.initialEvent = NULL;
//array of urls. now with a single object array
CFArrayRef array = (__bridge CFArrayRef)[NSArray arrayWithObject:(__bridge id)url];
//open the url with the application
OSStatus stat = LSOpenURLsWithRole(array, kLSRolesAll, NULL, &appParam, NULL, 0);
//kLSRolesAll - the role with which the applicaiton is to be opened (kLSRolesAll accepts any)
if (stat<0) {
NSLog(@"Can not open the url (http://support.apple.com/kb/DL1572) with the Safari");
}
}
void showWarning(NSString* installedJava){
NSAlert* alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:@"Update"];
[alert addButtonWithTitle:@"Cancel"];
NSString* message_description = [NSString stringWithFormat:@"%@%@%@",@"Java version: ", installedJava, @" which is installed on your Mac is obsolete."];
NSString* message_suggestion = @"Would you like to update Java?";
NSString* informativeText =[NSString stringWithFormat:@"%@\n%@",message_description,message_suggestion];
[alert setMessageText:@"Java Update"];
[alert setInformativeText:informativeText ];
[alert setAlertStyle:NSWarningAlertStyle];
if ([alert runModal] == NSAlertFirstButtonReturn){
openUrl();
}
[alert release];
}
BOOL isJavaUpdateRequired(NSString *vmVersion, NSString *requiredVersion){
BOOL needUpdate = false;
NSString* currentOSXVersion = getOSXVersion();
//installedJava = vmVersion;
if ([osxVersion compare:currentOSXVersion options:NSNumericSearch] <= 0){
if ([minRequiredJavaVersion compare:vmVersion options:NSNumericSearch] <= 0){
NSLog(@"find Java: %@", vmVersion);
}else{
//NSLog(@" --- Installed Java is not meet the requirements. Please visit http://support.apple.com/kb/DL1572 and update Java.");
NSLog(@"find Java: %@", vmVersion);
NSLog(@"required JavaVersion: %@", minRequiredJavaVersion);
needUpdate = true;
showWarning(vmVersion);
}
}
return needUpdate;
}
void appendBundle(NSString *path, NSMutableArray *sink) {
if ([path hasSuffix:@"jdk"] || [path hasSuffix:@".jre"]) {
@@ -120,7 +198,9 @@ NSArray *allVms() {
}
NSString *jvmVersion(NSBundle *bundle) {
return [bundle.infoDictionary valueForKey:@"JVMVersion" inDictionary:@"JavaVM" defaultObject:@"0"];
NSString* javaVersion = [bundle.infoDictionary valueForKey:@"JVMVersion" inDictionary:@"JavaVM" defaultObject:@"0"];
//NSLog(@"jvmVersion: %@", javaVersion);
return javaVersion;
}
NSString *requiredJvmVersion() {
@@ -128,15 +208,19 @@ NSString *requiredJvmVersion() {
}
BOOL satisfies(NSString *vmVersion, NSString *requiredVersion) {
if (!javaUpdateRequired){
javaUpdateRequired = isJavaUpdateRequired(vmVersion, requiredVersion);
}
if (javaUpdateRequired){
return !javaUpdateRequired;
}
if ([requiredVersion hasSuffix:@"+"]) {
requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
return [requiredVersion compare:vmVersion options:NSNumericSearch] <= 0;
requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
return [requiredVersion compare:vmVersion options:NSNumericSearch] <= 0;
}
if ([requiredVersion hasSuffix:@"*"]) {
requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
requiredVersion = [requiredVersion substringToIndex:[requiredVersion length] - 1];
}
return [vmVersion hasPrefix:requiredVersion];
}
@@ -158,13 +242,13 @@ NSBundle *findMatchingVm() {
debugLog([NSString stringWithFormat:@"Required VM: %@", required]);
if (required != nil && required != NULL) {
for (NSBundle *vm in vmBundles) {
for (NSBundle *vm in vmBundles) {
if (satisfies(jvmVersion(vm), required)) {
debugLog(@"Chosen VM:");
debugLog([vm bundlePath]);
return vm;
}
}
}
} else {
NSLog(@"Info.plist is corrupted, Absent JVMOptios key.");
exit(-1);
@@ -331,10 +415,18 @@ NSDictionary *parseProperties() {
}
}
BOOL validationJavaVersion(){
vm = findMatchingVm();
if (javaUpdateRequired) {
NSLog(@"update Java is required");
return false;
}
return true;
}
- (void)launch {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSBundle *vm = findMatchingVm();
if (vm == nil) {
NSString *old_launcher = [self expandMacros:@"$APP_PACKAGE/Contents/MacOS/idea_appLauncher"];
execv([old_launcher fileSystemRepresentation], self->argv);
+8 -7
View File
@@ -25,17 +25,18 @@ static void makeSameStackSize(NSThread *thread) {
}
static void launchInNewThread(Launcher *launcher) {
NSThread *thread = [[[NSThread alloc] initWithTarget:launcher selector:@selector(launch) object:nil] autorelease];
makeSameStackSize(thread);
[thread start];
NSThread *thread = [[[NSThread alloc] initWithTarget:launcher selector:@selector(launch) object:nil] autorelease];
makeSameStackSize(thread);
[thread start];
}
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
launchInNewThread([[[Launcher alloc] initWithArgc:argc argv:argv] autorelease]);
parkRunLoop();
if (validationJavaVersion()){
launchInNewThread([[[Launcher alloc] initWithArgc:argc argv:argv] autorelease]);
parkRunLoop();
}
[pool release];
return 0;
}
@@ -273,7 +273,7 @@ public class GlobalInspectionContextBase extends UserDataHolderBase implements G
protected void notifyInspectionsFinished() {
}
protected void performInspectionsWithProgress(@NotNull final AnalysisScope scope, final boolean runGlobalToolsOnly) {
public void performInspectionsWithProgress(@NotNull final AnalysisScope scope, final boolean runGlobalToolsOnly) {
final PsiManager psiManager = PsiManager.getInstance(myProject);
myProgressIndicator = getProgressIndicator();
//init manager in read action
@@ -17,6 +17,9 @@
package com.intellij.psi;
/**
* CAUTION: this is a workaround to fix java method searcher performance.
* This can be removed in future if the searcher is fixed to obey {@link com.intellij.psi.PsiReference#isReferenceTo(PsiElement)} contract.
*
* Can be implemented by {@link com.intellij.psi.PsiReference}
* @author Dmitry Avdeev
*/
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -15,26 +15,8 @@
*/
package com.intellij.psi.stubs;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
/*
* @author max
*/
public interface StubSerializer<T extends StubElement> extends ObjectStubSerializer<T, StubElement> {
@Override
@NotNull
@NonNls
String getExternalId();
@Override
void serialize(@NotNull T stub, @NotNull StubOutputStream dataStream) throws IOException;
@NotNull
@Override
T deserialize(@NotNull StubInputStream dataStream, final StubElement parentStub) throws IOException;
@Override
void indexStub(@NotNull T stub, @NotNull IndexSink sink);
}
@@ -35,7 +35,10 @@ public class ComponentSerializationUtil {
public static <S> void loadComponentState(@NotNull PersistentStateComponent<S> configuration, @Nullable Element element) {
if (element != null) {
Class<S> stateClass = getStateClass(configuration.getClass());
configuration.loadState(XmlSerializer.deserialize(element, stateClass));
S state = XmlSerializer.deserialize(element, stateClass);
if (state != null) {
configuration.loadState(state);
}
}
}
}
@@ -493,7 +493,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
throwGuardedFragment(marker, offset, null, s.toString());
}
updateText(myText.insert(offset, ImmutableText.valueOf(s)), offset, null, s, false, LocalTimeCounter.currentTime());
myText = myText.ensureChunked();
ImmutableText newText = myText.insert(offset, ImmutableText.valueOf(s));
updateText(newText, offset, null, newText.subtext(offset, offset + s.length()), false, LocalTimeCounter.currentTime());
trimToSize();
}
@@ -511,14 +513,13 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
if (!isWritable()) throw new ReadOnlyModificationException(this);
if (startOffset == endOffset) return;
CharSequence sToDelete = myText.subSequence(startOffset, endOffset);
RangeMarker marker = getRangeGuard(startOffset, endOffset);
if (marker != null) {
throwGuardedFragment(marker, startOffset, sToDelete.toString(), null);
throwGuardedFragment(marker, startOffset, myText.subSequence(startOffset, endOffset).toString(), null);
}
updateText(myText.delete(startOffset, endOffset), startOffset, sToDelete, null, false, LocalTimeCounter.currentTime());
myText = myText.ensureChunked();
updateText(myText.delete(startOffset, endOffset), startOffset, myText.subtext(startOffset, endOffset), null, false, LocalTimeCounter.currentTime());
}
@Override
@@ -582,7 +583,7 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
}
CharSequence changedPart = s.subSequence(newStartInString, newEndInString);
CharSequence sToDelete = myText.subSequence(startOffset, endOffset);
CharSequence sToDelete = myText.subtext(startOffset, endOffset);
RangeMarker guard = getRangeGuard(startOffset, endOffset);
if (guard != null) {
throwGuardedFragment(guard, startOffset, sToDelete.toString(), changedPart.toString());
@@ -593,7 +594,9 @@ public class DocumentImpl extends UserDataHolderBase implements DocumentEx {
newText = (ImmutableText)s;
}
else {
myText = myText.ensureChunked();
newText = myText.delete(startOffset, endOffset).insert(startOffset, changedPart);
changedPart = newText.subtext(startOffset, startOffset + changedPart.length());
}
updateText(newText, startOffset, sToDelete, changedPart, wholeTextReplaced, newModificationStamp);
trimToSize();
@@ -25,6 +25,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -57,7 +58,7 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.*;
public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements DocumentListener {
public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements DocumentListener, DocumentBulkUpdateListener {
protected static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiDocumentManagerImpl");
private static final Key<Document> HARD_REF_TO_DOCUMENT = Key.create("HARD_REFERENCE_TO_DOCUMENT");
private static final Key<PsiFile> HARD_REF_TO_PSI = Key.create("HARD_REFERENCE_TO_PSI");
@@ -96,6 +97,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
public void transactionCompleted(@NotNull Document document, @NotNull PsiFile file) {
}
});
bus.connect().subscribe(DocumentBulkUpdateListener.TOPIC, this);
}
@Override
@@ -134,9 +136,19 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
@Nullable
public FileViewProvider getCachedViewProvider(@NotNull Document document) {
final VirtualFile virtualFile = getVirtualFile(document);
if (virtualFile == null) return null;
return getCachedViewProvider(virtualFile);
}
private FileViewProvider getCachedViewProvider(@NotNull VirtualFile virtualFile) {
return ((PsiManagerEx)myPsiManager).getFileManager().findCachedViewProvider(virtualFile);
}
private static VirtualFile getVirtualFile(@NotNull Document document) {
final VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
if (virtualFile == null || !virtualFile.isValid()) return null;
return ((PsiManagerEx)myPsiManager).getFileManager().findCachedViewProvider(virtualFile);
return virtualFile;
}
@Nullable
@@ -319,7 +331,8 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
myLastCommittedTexts.remove(document);
viewProvider.contentsSynchronized();
} else {
}
else {
handleCommitWithoutPsi(document);
}
}
@@ -586,12 +599,19 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
myLastCommittedTexts.put(document, document.getImmutableCharSequence());
}
final FileViewProvider viewProvider = getCachedViewProvider(document);
if (viewProvider == null) return;
if (!isRelevant(viewProvider)) return;
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
boolean isBulk = document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate();
VirtualFile virtualFile = viewProvider.getVirtualFile();
if (virtualFile.getFileType().isBinary()) return;
boolean isRelevant = virtualFile != null && isRelevant(virtualFile);
if (!isBulk && isRelevant) {
mySmartPointerManager.fastenBelts(virtualFile, event.getOffset(), null);
}
final FileViewProvider viewProvider = getCachedViewProvider(document);
boolean inMyProject = viewProvider != null && viewProvider.getManager() == myPsiManager;
if (!isRelevant || !inMyProject) {
return;
}
final List<PsiFile> files = viewProvider.getAllFiles();
PsiFile psiCause = null;
@@ -599,7 +619,6 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
if (file == null) {
throw new AssertionError("View provider "+viewProvider+" ("+viewProvider.getClass()+") returned null in its files array: "+files+" for file "+viewProvider.getVirtualFile());
}
mySmartPointerManager.fastenBelts(file, event.getOffset(), null);
if (mySynchronizer.isInsideAtomicChange(file)) {
psiCause = file;
@@ -619,12 +638,21 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
@Override
public void documentChanged(DocumentEvent event) {
final Document document = event.getDocument();
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
boolean isBulk = document instanceof DocumentEx && ((DocumentEx)document).isInBulkUpdate();
boolean isRelevant = virtualFile != null && isRelevant(virtualFile);
if (!isBulk && isRelevant) {
mySmartPointerManager.unfastenBelts(virtualFile, event.getOffset());
}
final FileViewProvider viewProvider = getCachedViewProvider(document);
if (viewProvider == null) {
handleCommitWithoutPsi(document);
return;
}
if (!isRelevant(viewProvider)) {
boolean inMyProject = viewProvider.getManager() == myPsiManager;
if (!isRelevant || !inMyProject) {
myLastCommittedTexts.remove(document);
return;
}
@@ -633,7 +661,6 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
final List<PsiFile> files = viewProvider.getAllFiles();
boolean commitNecessary = true;
for (PsiFile file : files) {
mySmartPointerManager.unfastenBelts(file, event.getOffset());
if (mySynchronizer.isInsideAtomicChange(file)) {
commitNecessary = false;
@@ -671,6 +698,21 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
}
@Override
public void updateStarted(@NotNull Document document) {
final VirtualFile virtualFile = getVirtualFile(document);
if (virtualFile == null || !isRelevant(virtualFile)) return;
mySmartPointerManager.fastenBelts(virtualFile, 0, null);
}
@Override
public void updateFinished(@NotNull Document document) {
final VirtualFile virtualFile = getVirtualFile(document);
if (virtualFile == null || !isRelevant(virtualFile)) return;
mySmartPointerManager.unfastenBelts(virtualFile, 0);
}
public void handleCommitWithoutPsi(@NotNull Document document) {
final CharSequence prevText = myLastCommittedTexts.remove(document);
if (prevText == null) {
@@ -712,10 +754,8 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
});
}
private boolean isRelevant(@NotNull FileViewProvider viewProvider) {
VirtualFile virtualFile = viewProvider.getVirtualFile();
private boolean isRelevant(@NotNull VirtualFile virtualFile) {
return !virtualFile.getFileType().isBinary() &&
viewProvider.getManager() == myPsiManager &&
!myPsiManager.getProject().isDisposed();
}
@@ -38,13 +38,13 @@ import java.lang.ref.SoftReference;
public class SelfElementInfo implements SmartPointerElementInfo {
protected final VirtualFile myVirtualFile;
private Reference<RangeMarker> myMarkerRef; // create marker only in case of live document
private int mySyncStartOffset;
private int mySyncEndOffset;
protected boolean mySyncMarkerIsValid;
private volatile int mySyncStartOffset;
private volatile int mySyncEndOffset;
protected volatile boolean mySyncMarkerIsValid;
private final Class myType;
protected final Project myProject;
@SuppressWarnings({"UnusedDeclaration"})
private RangeMarker myRangeMarker; //maintain hard reference during modification
private volatile RangeMarker myRangeMarker; //maintains hard reference during modification
protected final Language myLanguage;
protected SelfElementInfo(@NotNull Project project, @NotNull PsiElement anchor) {
@@ -90,7 +90,9 @@ public class SelfElementInfo implements SmartPointerElementInfo {
// before change
@Override
public void fastenBelt(int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
if (!mySyncMarkerIsValid) return;
if (!mySyncMarkerIsValid) {
return;
}
RangeMarker marker = getMarker();
int actualEndOffset = marker == null || !marker.isValid() ? getSyncEndOffset() : marker.getEndOffset();
if (offset > actualEndOffset) {
@@ -115,13 +117,16 @@ public class SelfElementInfo implements SmartPointerElementInfo {
}
}
}
else {
if (marker == null) {
marker = document.createRangeMarker(start, end, true);
}
}
setMarker(marker);
}
else if (!marker.isValid()) {
else if (marker.isValid()) {
setRange(marker);
}
else {
mySyncMarkerIsValid = false;
setMarker(null);
marker = null;
@@ -132,7 +137,9 @@ public class SelfElementInfo implements SmartPointerElementInfo {
// after change
@Override
public void unfastenBelt(int offset) {
if (!mySyncMarkerIsValid) return;
if (!mySyncMarkerIsValid) {
return;
}
RangeMarker marker = getMarker();
if (marker != null) {
if (marker.isValid()) {
@@ -210,10 +217,6 @@ public class SelfElementInfo implements SmartPointerElementInfo {
myMarkerRef = marker == null ? null : new SoftReference<RangeMarker>(marker);
}
@Nullable
public static PsiFile restoreFileFromVirtual(final VirtualFile virtualFile, @NotNull final Project project) {
return restoreFileFromVirtual(virtualFile, project, null);
}
@Nullable
public static PsiFile restoreFileFromVirtual(final VirtualFile virtualFile, @NotNull final Project project, @Nullable final Language language) {
if (virtualFile == null) return null;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -25,51 +25,63 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.source.tree.MarkersHolderFileViewProvider;
import com.intellij.reference.SoftReference;
import com.intellij.util.containers.UnsafeWeakList;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.lang.ref.Reference;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SmartPointerManagerImpl extends SmartPointerManager {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl");
private static final Key<List<SmartPointerEx>> SMART_POINTERS_IN_PSI_FILE_KEY = Key.create("SMART_POINTERS_IN_PSI_FILE_KEY");
private static final Key<Boolean> BELTS_ARE_FASTEN_KEY = Key.create("BELTS_ARE_FASTEN_KEY");
private final Project myProject;
private final Object lock = new Object();
private final Map<VirtualFile, List<SmartPointerEx>> pointers = new THashMap<VirtualFile, List<SmartPointerEx>>();
private final Set<VirtualFile> fastenedFiles = new THashSet<VirtualFile>();
public SmartPointerManagerImpl(Project project) {
myProject = project;
}
public void fastenBelts(@NotNull PsiFile file, int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
public void fastenBelts(@NotNull VirtualFile file, int offset, @Nullable RangeMarker[] cachedRangeMarkers) {
ApplicationManager.getApplication().assertIsDispatchThread();
synchronized (lock) {
if (areBeltsFastened(file)) return;
file.putUserData(BELTS_ARE_FASTEN_KEY, Boolean.TRUE);
List<SmartPointerEx> pointers = getPointers(file);
if (pointers == null) return;
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(file.getProject());
for (SmartPointerEx pointer : pointers) {
if (pointer != null) {
pointer.fastenBelt(offset, cachedRangeMarkers);
if (getAndFasten(file)) return;
if (pointers.isEmpty()) {
this.pointers.remove(file);
}
else {
for (SmartPointerEx pointer : pointers) {
if (pointer != null) {
pointer.fastenBelt(offset, cachedRangeMarkers);
}
}
}
for (DocumentWindow injectedDoc : InjectedLanguageManager.getInstance(myProject).getCachedInjectedDocuments(file)) {
PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc);
if (injectedFile == null) continue;
RangeMarker[] cachedMarkers = getCachedRangeMarkerToInjectedFragment(injectedFile);
fastenBelts(injectedFile, 0, cachedMarkers);
PsiFile psiFile = ((PsiManagerEx)PsiManager.getInstance(myProject)).getFileManager().getCachedPsiFile(file);
if (psiFile != null) {
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(myProject);
for (DocumentWindow injectedDoc : InjectedLanguageManager.getInstance(myProject).getCachedInjectedDocuments(psiFile)) {
PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc);
if (injectedFile == null) continue;
RangeMarker[] cachedMarkers = getCachedRangeMarkerToInjectedFragment(injectedFile);
fastenBelts(injectedFile.getViewProvider().getVirtualFile(), 0, cachedMarkers);
}
}
}
}
@@ -80,24 +92,33 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
return provider.getCachedMarkers();
}
public void unfastenBelts(@NotNull PsiFile file, int offset) {
public void unfastenBelts(@NotNull VirtualFile file, int offset) {
ApplicationManager.getApplication().assertIsDispatchThread();
synchronized (lock) {
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(file.getProject());
file.putUserData(BELTS_ARE_FASTEN_KEY, null);
List<SmartPointerEx> pointers = getPointers(file);
if (pointers == null) return;
for (SmartPointerEx pointer : pointers) {
if (pointer != null) {
pointer.unfastenBelt(offset);
if (!getAndUnfasten(file)) return;
if (pointers.isEmpty()) {
this.pointers.remove(file);
}
else {
for (SmartPointerEx pointer : pointers) {
if (pointer != null) {
pointer.unfastenBelt(offset);
}
}
}
for (DocumentWindow injectedDoc : InjectedLanguageManager.getInstance(myProject).getCachedInjectedDocuments(file)) {
PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc);
if (injectedFile == null) continue;
unfastenBelts(injectedFile, 0);
PsiFile psiFile = ((PsiManagerEx)PsiManager.getInstance(myProject)).getFileManager().getCachedPsiFile(file);
if (psiFile != null) {
PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(myProject);
for (DocumentWindow injectedDoc : InjectedLanguageManager.getInstance(myProject).getCachedInjectedDocuments(psiFile)) {
PsiFile injectedFile = psiDocumentManager.getPsiFile(injectedDoc);
if (injectedFile == null) continue;
unfastenBelts(injectedFile.getViewProvider().getVirtualFile(), 0);
}
}
}
}
@@ -119,13 +140,15 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
SmartPointerEx<E> pointer = getCachedPointer(element);
if (pointer != null) {
containingFile = containingFile == null ? element.getContainingFile() : containingFile;
if (containingFile != null && areBeltsFastened(containingFile)) {
if (containingFile != null && areBeltsFastened(containingFile.getViewProvider().getVirtualFile())) {
pointer.fastenBelt(0, null);
}
}
else {
pointer = new SmartPsiElementPointerImpl<E>(myProject, element, containingFile);
initPointer(pointer, containingFile);
if (containingFile != null) {
initPointer(pointer, containingFile.getViewProvider().getVirtualFile());
}
element.putUserData(CACHED_SMART_POINTER_KEY, new SoftReference<SmartPointerEx>(pointer));
}
if (pointer instanceof SmartPsiElementPointerImpl) {
@@ -156,18 +179,17 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
LOG.error("Invalid element:" + file);
}
SmartPsiFileRangePointerImpl pointer = new SmartPsiFileRangePointerImpl(file, ProperTextRange.create(range));
initPointer(pointer, file);
initPointer(pointer, file.getViewProvider().getVirtualFile());
return pointer;
}
private <E extends PsiElement> void initPointer(@NotNull SmartPointerEx<E> pointer, PsiFile containingFile) {
if (containingFile == null) return;
private <E extends PsiElement> void initPointer(@NotNull SmartPointerEx<E> pointer, @NotNull VirtualFile containingFile) {
synchronized (lock) {
List<SmartPointerEx> pointers = getPointers(containingFile);
if (pointers == null) {
pointers = new UnsafeWeakList<SmartPointerEx>(); // we synchronise access anyway
containingFile.putUserData(SMART_POINTERS_IN_PSI_FILE_KEY, pointers);
this.pointers.put(containingFile, pointers);
}
pointers.add(pointer);
@@ -189,7 +211,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
}
PsiFile containingFile = pointer.getContainingFile();
if (containingFile == null) return false;
List<SmartPointerEx> pointers = getPointers(containingFile);
List<SmartPointerEx> pointers = getPointers(containingFile.getViewProvider().getVirtualFile());
if (pointers == null) return false;
SmartPointerElementInfo info = ((SmartPsiElementPointerImpl)pointer).getElementInfo();
info.cleanup();
@@ -200,22 +222,27 @@ public class SmartPointerManagerImpl extends SmartPointerManager {
return false;
}
private static List<SmartPointerEx> getPointers(@NotNull PsiFile containingFile) {
return containingFile.getUserData(SMART_POINTERS_IN_PSI_FILE_KEY);
private List<SmartPointerEx> getPointers(@NotNull VirtualFile containingFile) {
return pointers.get(containingFile);
}
@TestOnly
public int getPointersNumber(@NotNull PsiFile containingFile) {
synchronized (lock) {
List<SmartPointerEx> pointers = getPointers(containingFile);
List<SmartPointerEx> pointers = getPointers(containingFile.getViewProvider().getVirtualFile());
return pointers == null ? 0 : ((UnsafeWeakList)pointers).toStrongList().size();
}
}
private static boolean areBeltsFastened(@NotNull PsiFile file) {
return file.getUserData(BELTS_ARE_FASTEN_KEY) == Boolean.TRUE;
private boolean getAndFasten(@NotNull VirtualFile file) {
return !fastenedFiles.add(file);
}
private boolean getAndUnfasten(@NotNull VirtualFile file) {
return fastenedFiles.remove(file);
}
private boolean areBeltsFastened(VirtualFile file) {
return fastenedFiles.contains(file);
}
@Override
public boolean pointToTheSameElement(@NotNull SmartPsiElementPointer pointer1, @NotNull SmartPsiElementPointer pointer2) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -42,22 +42,24 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
private final Class<? extends PsiElement> myElementClass;
private byte myReferenceCount;
public SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile) {
SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile) {
this(element, createElementInfo(project, element, containingFile), element.getClass());
}
public SmartPsiElementPointerImpl(@NotNull E element,
@NotNull SmartPointerElementInfo elementInfo,
@NotNull Class<? extends PsiElement> elementClass) {
SmartPsiElementPointerImpl(@NotNull E element,
@NotNull SmartPointerElementInfo elementInfo,
@NotNull Class<? extends PsiElement> elementClass) {
ApplicationManager.getApplication().assertReadAccessAllowed();
cacheElement(element);
myElementClass = elementClass;
myElementInfo = elementInfo;
}
@Override
public boolean equals(Object obj) {
return obj instanceof SmartPsiElementPointer && pointsToTheSameElementAs(this, (SmartPsiElementPointer)obj);
}
@Override
public int hashCode() {
return myElementInfo.elementHashCode();
}
@@ -125,6 +127,9 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
@NotNull
static <E extends PsiElement> SmartPointerElementInfo createElementInfo(@NotNull Project project, @NotNull E element, PsiFile containingFile) {
if (element instanceof PsiDirectory) {
return new DirElementInfo((PsiDirectory)element);
}
if (element instanceof PsiCompiledElement || containingFile == null || !containingFile.isPhysical() || !element.isPhysical()) {
if (element instanceof StubBasedPsiElement && element instanceof PsiCompiledElement) {
if (element instanceof PsiFile) {
@@ -137,9 +142,6 @@ class SmartPsiElementPointerImpl<E extends PsiElement> implements SmartPointerEx
}
return new HardElementInfo(project, element);
}
if (element instanceof PsiDirectory) {
return new DirElementInfo((PsiDirectory)element);
}
for(SmartPointerElementInfoFactory factory: Extensions.getExtensions(SmartPointerElementInfoFactory.EP_NAME)) {
final SmartPointerElementInfo result = factory.createElementInfo(element);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2007 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.dupLocator;
import com.intellij.openapi.components.*;
@@ -22,19 +21,13 @@ import com.intellij.util.xmlb.XmlSerializerUtil;
import java.util.HashSet;
import java.util.Set;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: Apr 8, 2004
* Time: 2:47:43 PM
* To change this template use File | Settings | File Templates.
*/
@State(
name="DuplocatorSettings",
name = "DuplocatorSettings",
storages = {
@Storage(
file = StoragePathMacros.APP_CONFIG + "/other.xml"
)}
@Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml"),
@Storage(file = StoragePathMacros.APP_CONFIG + "/duplocatorSettings.xml")
},
storageChooser = LastStorageChooserForWrite.class
)
public class DuplocatorSettings implements PersistentStateComponent<DuplocatorSettings> {
public boolean DISTINGUISH_VARIABLES = false;
@@ -6,7 +6,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -17,14 +17,12 @@ import java.util.Map;
*/
@State(
name = "MultiLanguageDuplocatorSettings",
storages = {
@Storage(file = StoragePathMacros.APP_CONFIG + "/duplocatorSettings.xml")
}
storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/duplocatorSettings.xml")
)
public class MultilanguageDuplocatorSettings implements PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#com.intellij.dupLocator.MultiLanguageDuplocatorSettings");
private final Map<String, ExternalizableDuplocatorState> mySettingsMap = new HashMap<String, ExternalizableDuplocatorState>();
private final Map<String, ExternalizableDuplocatorState> mySettingsMap = new LinkedHashMap<String, ExternalizableDuplocatorState>();
public static MultilanguageDuplocatorSettings getInstance() {
return ServiceManager.getService(MultilanguageDuplocatorSettings.class);
@@ -0,0 +1 @@
skip: *.gif
@@ -42,9 +42,8 @@ public class CommitNode extends DefaultMutableTreeNode implements CustomRendered
@Override
public void render(@NotNull ColoredTreeCellRenderer renderer) {
new IssueLinkRenderer(myProject, renderer).appendTextWithLinks(getUserObject().getSubject(),
new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER,
renderer.getForeground()));
renderer.append(" ");
new IssueLinkRenderer(myProject, renderer).appendTextWithLinks(getUserObject().getSubject(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
public String getTooltip() {
@@ -39,6 +39,7 @@ import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TreeSelectionEvent;
@@ -116,7 +117,9 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
}
};
myTree.setBorder(new EmptyBorder(2, 0, 0, 0)); //additional vertical indent
myTree.setEditable(true);
myTree.setHorizontalAutoScrollingEnabled(false);
myTree.setShowsRootHandles(root.getChildCount() > 1);
MyTreeCellEditor treeCellEditor = new MyTreeCellEditor();
myTree.setCellEditor(treeCellEditor);
Binary file not shown.

After

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Some files were not shown because too many files have changed in this diff Show More