VCS: todo checkin handler - visualization (merge)

This commit is contained in:
irengrig
2011-02-24 19:21:31 +03:00
465 changed files with 8481 additions and 3961 deletions
+3
View File
@@ -41,6 +41,9 @@
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="com.intellij.ui.components.JBLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="true" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="0" />
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
@@ -0,0 +1,28 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.lang.regexp;
/**
* @author yole
*/
public enum RegExpCapability {
XML_SCHEMA_MODE,
DANGLING_METACHARACTERS,
NESTED_CHARACTER_CLASSES,
OCTAL_NO_LEADING_ZERO,
OMIT_NUMBERS_IN_QUANTIFIERS,
COMMENT_MODE
}
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
class RegExpHighlighter extends SyntaxHighlighterBase {
public class RegExpHighlighter extends SyntaxHighlighterBase {
private static final Map<IElementType, TextAttributesKey> keys1;
private static final Map<IElementType, TextAttributesKey> keys2;
@@ -17,16 +17,20 @@ package org.intellij.lang.regexp;
import com.intellij.lexer.FlexAdapter;
import java.util.EnumSet;
public class RegExpLexer extends FlexAdapter {
private static final int COMMENT_MODE = 1 << 14;
private final EnumSet<RegExpCapability> myCapabilities;
public RegExpLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) {
super(new _RegExLexer(xmlSchemaMode, allowDanglingMetacharacters));
}
public RegExpLexer(EnumSet<RegExpCapability> capabilities) {
super(new _RegExLexer(capabilities));
myCapabilities = capabilities;
}
public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
getFlex().commentMode = (initialState & COMMENT_MODE) != 0;
getFlex().commentMode = (initialState & COMMENT_MODE) != 0 || myCapabilities.contains(RegExpCapability.COMMENT_MODE);
super.start(buffer, startOffset, endOffset, initialState & ~COMMENT_MODE);
}
@@ -23,17 +23,18 @@ import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.EnumSet;
@SuppressWarnings({"RedundantIfStatement"})
public class RegExpParser implements PsiParser {
private boolean myAllowDanglingMetacharacters;
private boolean myAllowOmitNumbersInQuantifiers;
private final EnumSet<RegExpCapability> myCapabilities;
public void setAllowDanglingMetacharacters(boolean allowDanglingMetacharacters) {
myAllowDanglingMetacharacters = allowDanglingMetacharacters;
public RegExpParser() {
myCapabilities = EnumSet.noneOf(RegExpCapability.class);
}
public void setAllowOmitNumbersInQuantifiers(boolean allowOmitNumbersInQuantifiers) {
myAllowOmitNumbersInQuantifiers = allowOmitNumbersInQuantifiers;
public RegExpParser(EnumSet<RegExpCapability> capabilities) {
myCapabilities = capabilities;
}
@NotNull
@@ -136,11 +137,11 @@ public class RegExpParser implements PsiParser {
if (builder.getTokenType() == RegExpTT.LBRACE) {
builder.advanceLexer();
boolean minOmitted = false;
if (builder.getTokenType() == RegExpTT.COMMA && myAllowOmitNumbersInQuantifiers) {
if (builder.getTokenType() == RegExpTT.COMMA && myCapabilities.contains(RegExpCapability.OMIT_NUMBERS_IN_QUANTIFIERS)) {
minOmitted = true;
builder.advanceLexer();
}
else if (builder.getTokenType() != RegExpTT.NUMBER && myAllowDanglingMetacharacters) {
else if (builder.getTokenType() != RegExpTT.NUMBER && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) {
marker.done(RegExpTT.CHARACTER);
return true;
}
@@ -432,7 +433,7 @@ public class RegExpParser implements PsiParser {
marker.drop();
return parseClass(builder);
}
else if (type == RegExpTT.LBRACE && myAllowDanglingMetacharacters) {
else if (type == RegExpTT.LBRACE && myCapabilities.contains(RegExpCapability.DANGLING_METACHARACTERS)) {
builder.advanceLexer();
marker.done(RegExpElementTypes.CHAR);
}
@@ -31,12 +31,14 @@ import com.intellij.psi.tree.TokenSet;
import org.intellij.lang.regexp.psi.impl.*;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
public class RegExpParserDefinition implements ParserDefinition {
private static final TokenSet COMMENT_TOKENS = TokenSet.create(RegExpTT.COMMENT);
@NotNull
public Lexer createLexer(Project project) {
return new RegExpLexer(false, false);
return new RegExpLexer(EnumSet.of(RegExpCapability.NESTED_CHARACTER_CLASSES));
}
public PsiParser createParser(Project project) {
@@ -1,13 +1,13 @@
/* The following code was generated by JFlex 1.4.3 on 01.06.10 15:51 */
/* The following code was generated by JFlex 1.4.3 on 21.02.11 20:37 */
/* It's an automatically generated code. Do not modify it. */
package org.intellij.lang.regexp;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.tree.IElementType;
import java.util.LinkedList;
import java.util.EnumSet;
import com.intellij.psi.StringEscapesTokenTypes;
// IDEADEV-11055
@SuppressWarnings({ "ALL", "SameParameterValue", "WeakerAccess", "SameReturnValue", "RedundantThrows", "UnusedDeclaration", "UnusedDeclaration" })
@@ -15,8 +15,8 @@ import java.util.LinkedList;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
* on 01.06.10 15:51 from the specification file
* <tt>C:/JetBrains/idea.branches/maia/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
* on 21.02.11 20:37 from the specification file
* <tt>C:/JetBrains/IDEA/tools/lexer/../../community/RegExpSupport/src/org/intellij/lang/regexp/regexp-lexer.flex</tt>
*/
class _RegExLexer implements FlexLexer {
/** initial size of the lookahead buffer */
@@ -24,17 +24,18 @@ class _RegExLexer implements FlexLexer {
/** lexical states */
public static final int EMBRACED = 4;
public static final int PY_NAMED_GROUP_REF = 20;
public static final int CLASS1PY = 8;
public static final int PY_NAMED_GROUP_REF = 22;
public static final int QUOTED = 2;
public static final int OPTIONS = 12;
public static final int PY_COND_REF = 22;
public static final int OPTIONS = 14;
public static final int PY_COND_REF = 24;
public static final int YYINITIAL = 0;
public static final int NAMED_GROUP = 16;
public static final int CLASS2 = 8;
public static final int NAMED_GROUP = 18;
public static final int CLASS2 = 10;
public static final int CLASS1 = 6;
public static final int COMMENT = 14;
public static final int QUOTED_NAMED_GROUP = 18;
public static final int PROP = 10;
public static final int COMMENT = 16;
public static final int QUOTED_NAMED_GROUP = 20;
public static final int PROP = 12;
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
@@ -44,7 +45,7 @@ class _RegExLexer implements FlexLexer {
*/
private static final int ZZ_LEXSTATE[] = {
0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
8, 8, 9, 9, 10, 10, 11, 11
8, 8, 9, 9, 10, 10, 11, 11, 12, 12
};
/**
@@ -130,20 +131,21 @@ class _RegExLexer implements FlexLexer {
private static final int [] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\6\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+
"\7\0\1\1\1\2\4\0\1\3\1\4\1\5\1\6"+
"\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"+
"\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\3"+
"\1\35\1\36\1\35\1\37\1\40\1\1\1\41\1\42"+
"\1\2\1\43\1\44\1\45\1\46\1\47\1\50\1\51"+
"\1\52\1\53\1\54\1\55\1\56\2\57\1\60\1\11"+
"\1\61\1\62\1\63\1\64\1\65\1\66\1\0\1\67"+
"\1\70\1\71\1\72\1\0\1\73\1\74\1\75\2\62"+
"\2\63\1\76\1\77\1\100\1\101\1\0\1\74\1\62"+
"\1\102\2\63\1\103\1\74\3\63\1\104";
"\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\0\1\73\1\74"+
"\1\75\1\76\1\0\1\77\1\100\1\101\1\102\2\64"+
"\2\65\1\52\1\103\1\104\1\105\1\106\1\0\1\101"+
"\1\64\1\107\2\65\1\110\1\111\1\101\3\65\1\112";
private static int [] zzUnpackAction() {
int [] result = new int[100];
int [] result = new int[111];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -169,21 +171,22 @@ class _RegExLexer implements FlexLexer {
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\63\0\146\0\231\0\314\0\377\0\u0132\0\u0165"+
"\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0264\0\u0297\0\u0264"+
"\0\u0264\0\u02ca\0\u02fd\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264"+
"\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0330\0\u0264\0\u0363"+
"\0\u0264\0\u0396\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u03c9"+
"\0\u0264\0\u0264\0\u02ca\0\u0264\0\u0264\0\u03fc\0\u042f\0\u0264"+
"\0\u0264\0\u0264\0\u0264\0\u0462\0\u0264\0\u0264\0\u0495\0\u04c8"+
"\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u0264\0\u04fb\0\u0264"+
"\0\u0264\0\u0264\0\u052e\0\u0561\0\u0264\0\u0264\0\u0264\0\u0594"+
"\0\u0264\0\u0264\0\u0264\0\u05c7\0\u05fa\0\u0264\0\u062d\0\u0264"+
"\0\u0660\0\u0693\0\u06c6\0\u06f9\0\u0264\0\u0264\0\u0264\0\u0264"+
"\0\u072c\0\u075f\0\u0264\0\u0264\0\u0792\0\u07c5\0\u0264\0\u0264"+
"\0\u07f8\0\u082b\0\u0264\0\u0264";
"\0\u0198\0\u01cb\0\u01fe\0\u0231\0\u0264\0\u0297\0\u0297\0\u02ca"+
"\0\u0297\0\u0297\0\u02fd\0\u0330\0\u0297\0\u0297\0\u0297\0\u0297"+
"\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0363\0\u0297"+
"\0\u0396\0\u0297\0\u03c9\0\u0297\0\u0297\0\u0297\0\u0297\0\u03fc"+
"\0\u0297\0\u042f\0\u0297\0\u0462\0\u0297\0\u0297\0\u02fd\0\u0297"+
"\0\u0297\0\u0495\0\u04c8\0\u0297\0\u0297\0\u0297\0\u0297\0\u04fb"+
"\0\u0297\0\u052e\0\u0297\0\u0561\0\u0594\0\u0297\0\u0297\0\u0297"+
"\0\u0297\0\u0297\0\u0297\0\u05c7\0\u0297\0\u0297\0\u0297\0\u05fa"+
"\0\u062d\0\u0660\0\u0297\0\u0297\0\u0297\0\u0297\0\u0297\0\u0693"+
"\0\u0297\0\u0297\0\u0297\0\u06c6\0\u06f9\0\u0297\0\u0297\0\u072c"+
"\0\u0297\0\u075f\0\u0792\0\u07c5\0\u07f8\0\u082b\0\u0297\0\u0297"+
"\0\u0297\0\u0297\0\u085e\0\u0891\0\u0297\0\u0297\0\u08c4\0\u08f7"+
"\0\u0561\0\u0297\0\u0297\0\u092a\0\u095d\0\u0297\0\u0297";
private static int [] zzUnpackRowMap() {
int [] result = new int[100];
int [] result = new int[111];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -206,47 +209,53 @@ class _RegExLexer implements FlexLexer {
private static final int [] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\3\15\1\16\1\17\1\20\1\21\1\15\1\22\1\15"+
"\1\23\1\24\1\25\1\26\1\27\1\30\1\31\1\32"+
"\21\15\1\33\1\15\1\34\4\15\1\24\5\15\1\35"+
"\1\15\1\24\12\15\1\36\1\0\47\15\1\37\2\40"+
"\4\37\1\41\12\37\20\42\1\40\1\37\1\42\2\37"+
"\1\40\1\43\12\37\11\44\1\45\1\44\1\0\47\44"+
"\6\15\1\21\1\15\1\22\1\46\1\23\1\47\1\25"+
"\26\15\1\33\5\15\1\50\1\47\7\15\1\47\6\51"+
"\1\52\1\51\1\53\1\51\1\23\50\51\5\54\1\55"+
"\14\54\20\56\1\54\1\57\1\56\6\54\1\60\7\54"+
"\13\10\1\61\46\10\1\61\22\54\20\42\2\54\1\42"+
"\7\54\1\62\30\54\20\42\2\54\1\42\14\54\1\63"+
"\6\54\1\55\14\54\20\42\2\54\1\42\17\54\2\40"+
"\2\54\1\55\14\54\20\42\1\40\1\54\1\42\2\54"+
"\1\40\13\54\101\0\1\64\55\0\1\65\51\0\1\66"+
"\1\67\1\70\4\71\1\66\1\71\1\66\1\71\1\72"+
"\6\71\2\73\2\74\2\75\1\76\1\77\1\76\2\100"+
"\1\101\1\102\1\101\1\103\1\104\1\67\1\71\1\101"+
"\1\72\4\66\1\72\7\66\1\72\37\0\1\105\24\0"+
"\2\40\37\0\1\40\4\0\1\40\14\0\2\42\17\0"+
"\21\42\1\0\1\42\1\0\2\42\64\0\1\106\33\0"+
"\20\56\2\0\1\56\40\0\20\57\2\0\1\57\22\0"+
"\1\107\27\0\1\110\16\0\2\111\1\112\1\113\1\114"+
"\1\115\1\116\2\0\2\67\37\0\1\67\22\0\1\117"+
"\37\0\1\117\20\0\63\120\1\121\2\122\20\121\2\122"+
"\2\121\3\122\3\121\1\122\1\121\1\122\2\121\1\122"+
"\20\121\1\123\2\124\20\123\2\124\2\123\3\124\3\123"+
"\1\124\1\123\1\124\2\123\1\124\20\123\55\0\1\125"+
"\1\0\1\126\60\0\1\127\1\130\4\0\5\131\1\0"+
"\55\131\2\0\1\132\37\0\1\132\20\0\64\133\2\134"+
"\20\133\2\134\2\133\3\134\3\133\1\134\1\133\1\134"+
"\2\133\1\134\20\133\64\135\2\136\20\135\2\136\2\135"+
"\3\136\3\135\1\136\1\135\1\136\2\135\1\136\20\135"+
"\5\131\1\137\55\131\2\0\1\140\37\0\1\140\20\0"+
"\64\141\2\142\20\141\2\142\2\141\3\142\3\141\1\142"+
"\1\141\1\142\2\141\1\142\20\141\64\143\2\144\20\143"+
"\2\144\2\143\3\144\3\143\1\144\1\143\1\144\2\143"+
"\1\144\20\143";
"\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\1\16\1\35\4\16\1\25\5\16\1\36"+
"\1\16\1\25\12\16\1\37\1\0\47\16\1\40\2\41"+
"\4\40\1\42\12\40\20\43\1\41\1\40\1\43\2\40"+
"\1\41\1\44\12\40\11\45\1\46\1\45\1\0\62\45"+
"\1\0\1\47\46\45\6\16\1\22\1\16\1\50\1\51"+
"\1\52\1\53\1\26\26\16\1\34\5\16\1\54\1\53"+
"\7\16\1\53\6\55\1\56\1\55\1\57\1\55\1\24"+
"\50\55\5\60\1\61\14\60\20\62\1\60\1\63\1\62"+
"\6\60\1\64\7\60\13\11\1\65\46\11\1\65\22\60"+
"\20\43\2\60\1\43\7\60\1\66\30\60\20\43\2\60"+
"\1\43\14\60\1\67\6\60\1\61\14\60\20\43\2\60"+
"\1\43\17\60\2\41\2\60\1\61\14\60\20\43\1\41"+
"\1\60\1\43\2\60\1\41\13\60\101\0\1\70\55\0"+
"\1\71\2\0\1\72\46\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\106\1\77\4\73\1\77"+
"\7\73\1\77\37\0\1\113\24\0\2\41\37\0\1\41"+
"\4\0\1\41\14\0\2\43\17\0\21\43\1\0\1\43"+
"\1\0\2\43\24\0\1\114\2\0\1\72\46\0\1\73"+
"\1\74\1\75\4\76\1\73\1\76\1\115\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\106"+
"\1\77\4\73\1\77\7\73\1\77\51\0\1\116\33\0"+
"\20\62\2\0\1\62\40\0\20\63\2\0\1\63\22\0"+
"\1\117\27\0\1\120\16\0\2\121\1\122\1\123\1\124"+
"\1\125\1\126\12\0\1\127\52\0\2\74\37\0\1\74"+
"\22\0\1\130\37\0\1\130\20\0\63\131\1\132\2\133"+
"\20\132\2\133\2\132\3\133\3\132\1\133\1\132\1\133"+
"\2\132\1\133\20\132\1\134\2\135\20\134\2\135\2\134"+
"\3\135\3\134\1\135\1\134\1\135\2\134\1\135\20\134"+
"\1\0\1\74\1\136\37\0\1\136\75\0\1\137\1\0"+
"\1\140\60\0\1\141\1\142\4\0\5\143\1\0\55\143"+
"\2\0\1\144\37\0\1\144\20\0\64\145\2\146\20\145"+
"\2\146\2\145\3\146\3\145\1\146\1\145\1\146\2\145"+
"\1\146\20\145\64\147\2\150\20\147\2\150\2\147\3\150"+
"\3\147\1\150\1\147\1\150\2\147\1\150\20\147\1\0"+
"\1\74\1\151\37\0\1\151\20\0\5\143\1\152\55\143"+
"\2\0\1\153\37\0\1\153\20\0\64\154\2\155\20\154"+
"\2\155\2\154\3\155\3\154\1\155\1\154\1\155\2\154"+
"\1\155\20\154\64\156\2\157\20\156\2\157\2\156\3\157"+
"\3\156\1\157\1\156\1\157\2\156\1\157\20\156";
private static int [] zzUnpackTrans() {
int [] result = new int[2142];
int [] result = new int[2448];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -287,15 +296,16 @@ class _RegExLexer implements FlexLexer {
private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\6\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\5\11\1\1\2\11"+
"\1\1\2\11\2\1\4\11\1\1\2\11\2\1\6\11"+
"\1\1\3\11\2\1\3\11\1\0\3\11\1\1\1\0"+
"\1\11\1\1\1\11\4\1\4\11\1\0\1\1\2\11"+
"\2\1\2\11\2\1\2\11";
"\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\0\1\11\2\1\6\11\1\1\3\11"+
"\3\1\5\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";
private static int [] zzUnpackAttribute() {
int [] result = new int[100];
int [] result = new int[111];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -358,15 +368,21 @@ class _RegExLexer implements FlexLexer {
private final LinkedList<Integer> states = new LinkedList();
// 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.
// as well, but is currently unfinished as it requires to tweak more places than just the lexer.
private boolean xmlSchemaMode;
private boolean allowDanglingMetacharacters;
_RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) {
private boolean allowDanglingMetacharacters;
private boolean allowNestedCharacterClasses;
private boolean allowOctalNoLeadingZero;
_RegExLexer(EnumSet<RegExpCapability> capabilities) {
this((java.io.Reader)null);
this.xmlSchemaMode = xmlSchemaMode;
this.allowDanglingMetacharacters = allowDanglingMetacharacters;
this.xmlSchemaMode = capabilities.contains(RegExpCapability.XML_SCHEMA_MODE);
this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS);
this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES);
this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO);
this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE);
}
private void yypushstate(int state) {
@@ -636,272 +652,219 @@ class _RegExLexer implements FlexLexer {
zzMarkedPos = zzMarkedPosL;
switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
case 7:
{ if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE;
}
case 69: break;
case 6:
{ return RegExpTT.GROUP_END;
}
case 70: break;
case 38:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN;
}
case 71: break;
case 14:
{ return RegExpTT.STAR;
}
case 72: break;
case 42:
{ return RegExpTT.ESC_CHARACTER;
}
case 73: break;
case 28:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER;
}
case 74: break;
case 43:
{ return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE;
case 74:
{ return RegExpTT.UNICODE_CHAR;
}
case 75: break;
case 39:
{ return RegExpTT.REDUNDANT_ESCAPE;
case 7:
{ if (yystate() != CLASS2) yypushstate(EMBRACED); return RegExpTT.LBRACE;
}
case 76: break;
case 24:
{ return RegExpTT.COMMA;
}
case 77: break;
case 58:
{ yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP;
}
case 78: break;
case 64:
{ return RegExpTT.POS_LOOKBEHIND;
}
case 79: break;
case 41:
{ return RegExpTT.BAD_OCT_VALUE;
}
case 80: break;
case 10:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER;
}
case 81: break;
case 30:
{ yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE;
}
case 82: break;
case 51:
{ return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
}
case 83: break;
case 65:
{ return RegExpTT.NEG_LOOKBEHIND;
}
case 84: break;
case 68:
{ return RegExpTT.UNICODE_CHAR;
}
case 85: break;
case 61:
{ if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL;
}
case 86: break;
case 37:
{ yybegin(OPTIONS); return RegExpTT.SET_OPTIONS;
}
case 87: break;
case 12:
{ return RegExpTT.DOLLAR;
}
case 88: break;
case 52:
{ yypopstate(); return RegExpTT.QUOTE_END;
}
case 89: break;
case 56:
case 60:
{ return RegExpTT.POS_LOOKAHEAD;
}
case 90: break;
case 22:
{ yypopstate(); return RegExpTT.RBRACE;
}
case 91: break;
case 3:
{ return RegExpTT.CHARACTER;
}
case 92: break;
case 57:
{ return RegExpTT.NEG_LOOKAHEAD;
}
case 93: break;
case 44:
{ return RegExpTT.ESC_CTRL_CHARACTER;
}
case 94: break;
case 23:
{ return RegExpTT.NAME;
}
case 95: break;
case 53:
{ return RegExpTT.ANDAND;
}
case 96: break;
case 13:
{ return RegExpTT.QUEST;
}
case 97: break;
case 46:
{ return RegExpTT.CHAR_CLASS;
}
case 98: break;
case 17:
{ return RegExpTT.MINUS;
}
case 99: break;
case 67:
case 78: break;
case 73:
{ return RegExpTT.COMMENT;
}
case 100: break;
case 40:
{ return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
}
case 101: break;
case 16:
{ return RegExpTT.UNION;
}
case 102: break;
case 47:
{ if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
case 103: break;
case 60:
{ return RegExpTT.OCT_CHAR;
}
case 104: break;
case 4:
{ return RegExpTT.DOT;
}
case 105: break;
case 32:
{ yybegin(YYINITIAL); return RegExpTT.GROUP_END;
}
case 106: break;
case 21:
{ return RegExpTT.NUMBER;
}
case 107: break;
case 35:
{ yybegin(YYINITIAL); return RegExpTT.GT;
}
case 108: break;
case 59:
{ yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP;
}
case 109: break;
case 54:
{ yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF;
}
case 110: break;
case 48:
{ yypushstate(PROP); return RegExpTT.PROPERTY;
}
case 111: break;
case 18:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
}
case 112: break;
case 33:
{ handleOptions(); return RegExpTT.OPTIONS_OFF;
}
case 113: break;
case 34:
{ yybegin(YYINITIAL); return RegExpTT.COLON;
}
case 114: break;
case 25:
{ assert false : yytext();
}
case 115: break;
case 62:
{ yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF;
}
case 116: break;
case 27:
{ yypopstate(); return RegExpTT.CLASS_END;
}
case 117: break;
case 11:
{ return RegExpTT.CARET;
}
case 118: break;
case 1:
{ handleOptions(); return RegExpTT.OPTIONS_ON;
}
case 119: break;
case 29:
{ yypopstate(); yypushback(1);
}
case 120: break;
case 45:
{ return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
}
case 121: break;
case 63:
case 79: break;
case 68:
{ yybegin(NAMED_GROUP); return RegExpTT.PYTHON_NAMED_GROUP;
}
case 122: break;
case 19:
{ if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER;
case 80: break;
case 14:
{ return RegExpTT.STAR;
}
case 123: break;
case 66:
{ return RegExpTT.HEX_CHAR;
case 81: break;
case 58:
{ yybegin(PY_COND_REF); return RegExpTT.PYTHON_COND_REF;
}
case 124: break;
case 82: break;
case 48:
{ return RegExpTT.CHAR_CLASS;
}
case 83: break;
case 35:
{ handleOptions(); return RegExpTT.OPTIONS_OFF;
}
case 84: break;
case 54:
{ yypopstate(); return RegExpTT.QUOTE_END;
}
case 85: break;
case 34:
{ yybegin(YYINITIAL); return RegExpTT.GROUP_END;
}
case 86: break;
case 5:
{ return RegExpTT.GROUP_BEGIN;
}
case 125: break;
case 8:
{ yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN;
case 87: break;
case 36:
{ yybegin(YYINITIAL); return RegExpTT.COLON;
}
case 126: break;
case 55:
case 88: break;
case 6:
{ return RegExpTT.GROUP_END;
}
case 89: break;
case 25:
{ assert false : yytext();
}
case 90: break;
case 18:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CHARACTER;
}
case 91: break;
case 45:
{ return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE;
}
case 92: break;
case 23:
{ return RegExpTT.NAME;
}
case 93: break;
case 72:
{ if (allowOctalNoLeadingZero) return RegExpTT.OCT_CHAR;
return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
}
case 94: break;
case 29:
{ yypopstate(); return RegExpTT.CLASS_END;
}
case 95: break;
case 33:
{ yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
}
case 96: break;
case 51:
{ yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
}
case 97: break;
case 21:
{ return RegExpTT.NUMBER;
}
case 98: break;
case 4:
{ return RegExpTT.DOT;
}
case 99: break;
case 70:
{ return RegExpTT.NEG_LOOKBEHIND;
}
case 100: break;
case 40:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ yypushstate(CLASS1);
return RegExpTT.CLASS_BEGIN;
}
case 101: break;
case 61:
{ return RegExpTT.NEG_LOOKAHEAD;
}
case 102: break;
case 10:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.CTRL_CHARACTER;
}
case 103: break;
case 59:
{ return RegExpTT.NON_CAPT_GROUP;
}
case 127: break;
case 9:
{ return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
case 104: break;
case 63:
{ yybegin(QUOTED_NAMED_GROUP); return RegExpTT.RUBY_QUOTED_NAMED_GROUP;
}
case 128: break;
case 36:
{ yybegin(YYINITIAL); return RegExpTT.QUOTE;
case 105: break;
case 28:
{ if (allowNestedCharacterClasses) {
yypushstate(CLASS2);
return RegExpTT.CLASS_BEGIN;
}
return RegExpTT.CHARACTER;
}
case 129: break;
case 106: break;
case 19:
{ if (commentMode) { yypushstate(COMMENT); return RegExpTT.COMMENT; } else return RegExpTT.CHARACTER;
}
case 107: break;
case 50:
{ return RegExpTT.BAD_HEX_VALUE;
{ yypushstate(PROP); return RegExpTT.PROPERTY;
}
case 130: break;
case 108: break;
case 8:
{ yypushstate(CLASS2);
return RegExpTT.CLASS_BEGIN;
}
case 109: break;
case 69:
{ return RegExpTT.POS_LOOKBEHIND;
}
case 110: break;
case 42:
{ return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER;
}
case 111: break;
case 71:
{ return RegExpTT.HEX_CHAR;
}
case 112: break;
case 1:
{ handleOptions(); return RegExpTT.OPTIONS_ON;
}
case 113: break;
case 57:
{ return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER;
}
case 114: break;
case 2:
{ yypopstate(); return RegExpTT.COMMENT;
}
case 131: break;
case 49:
{ yypushstate(QUOTED); return RegExpTT.QUOTE_BEGIN;
case 115: break;
case 17:
{ return RegExpTT.MINUS;
}
case 132: break;
case 26:
{ yybegin(CLASS2); return RegExpTT.CHARACTER;
case 116: break;
case 46:
{ return RegExpTT.ESC_CTRL_CHARACTER;
}
case 133: break;
case 117: break;
case 32:
{ yypopstate(); yypushstate(EMBRACED); return RegExpTT.LBRACE;
}
case 118: break;
case 13:
{ return RegExpTT.QUEST;
}
case 119: break;
case 15:
{ return RegExpTT.PLUS;
}
case 134: break;
case 120: break;
case 65:
{ return RegExpTT.OCT_CHAR;
}
case 121: break;
case 38:
{ yybegin(YYINITIAL); return RegExpTT.QUOTE;
}
case 122: break;
case 64:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ if (!allowNestedCharacterClasses) {
yypushstate(CLASS1PY);
}
else {
yypushstate(CLASS2);
}
return RegExpTT.CLASS_BEGIN;
}
case 123: break;
case 20:
{ if (allowDanglingMetacharacters) {
yypopstate(); yypushback(1);
@@ -909,11 +872,110 @@ class _RegExLexer implements FlexLexer {
return RegExpTT.BAD_CHARACTER;
}
}
case 135: break;
case 124: break;
case 31:
{ yybegin(YYINITIAL); return RegExpTT.BAD_CHARACTER;
{ yypopstate(); yypushback(1);
}
case 125: break;
case 27:
{ yybegin(CLASS1); return RegExpTT.CARET;
}
case 126: break;
case 55:
// lookahead expression with fixed base length
zzMarkedPos = zzStartRead + 1;
{ if (allowNestedCharacterClasses) {
yypushstate(CLASS1);
return RegExpTT.CLASS_BEGIN;
}
return RegExpTT.CHARACTER;
}
case 127: break;
case 56:
{ if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER;
return RegExpTT.REDUNDANT_ESCAPE;
}
case 128: break;
case 37:
{ yybegin(YYINITIAL); return RegExpTT.GT;
}
case 129: break;
case 67:
{ yybegin(PY_NAMED_GROUP_REF); return RegExpTT.PYTHON_NAMED_GROUP_REF;
}
case 130: break;
case 16:
{ return RegExpTT.UNION;
}
case 131: break;
case 3:
{ return RegExpTT.CHARACTER;
}
case 132: break;
case 62:
{ yybegin(NAMED_GROUP); return RegExpTT.RUBY_NAMED_GROUP;
}
case 133: break;
case 39:
{ yybegin(OPTIONS); return RegExpTT.SET_OPTIONS;
}
case 134: break;
case 26:
{ yybegin(CLASS2); return RegExpTT.CHARACTER;
}
case 135: break;
case 66:
{ if (xmlSchemaMode) { yypushback(1); return RegExpTT.CHAR_CLASS; } else return RegExpTT.CTRL;
}
case 136: break;
case 30:
{ return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER;
}
case 137: break;
case 12:
{ return RegExpTT.DOLLAR;
}
case 138: break;
case 49:
{ if (xmlSchemaMode) return RegExpTT.CHAR_CLASS; else return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
case 139: break;
case 41:
{ return RegExpTT.REDUNDANT_ESCAPE;
}
case 140: break;
case 47:
{ return yystate() != CLASS2 ? RegExpTT.BOUNDARY : RegExpTT.ESC_CHARACTER;
}
case 141: break;
case 22:
{ yypopstate(); return RegExpTT.RBRACE;
}
case 142: break;
case 53:
{ return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
}
case 143: break;
case 43:
{ return RegExpTT.BAD_OCT_VALUE;
}
case 144: break;
case 52:
{ return RegExpTT.BAD_HEX_VALUE;
}
case 145: break;
case 9:
{ return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
case 146: break;
case 11:
{ return RegExpTT.CARET;
}
case 147: break;
case 44:
{ return RegExpTT.ESC_CHARACTER;
}
case 148: break;
default:
if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
zzAtEOF = true;
@@ -4,6 +4,7 @@ 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;
// IDEADEV-11055
@@ -23,15 +24,21 @@ import com.intellij.psi.StringEscapesTokenTypes;
private final LinkedList<Integer> states = new LinkedList();
// 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.
// as well, but is currently unfinished as it requires to tweak more places than just the lexer.
private boolean xmlSchemaMode;
private boolean allowDanglingMetacharacters;
_RegExLexer(boolean xmlSchemaMode, boolean allowDanglingMetacharacters) {
private boolean allowDanglingMetacharacters;
private boolean allowNestedCharacterClasses;
private boolean allowOctalNoLeadingZero;
_RegExLexer(EnumSet<RegExpCapability> capabilities) {
this((java.io.Reader)null);
this.xmlSchemaMode = xmlSchemaMode;
this.allowDanglingMetacharacters = allowDanglingMetacharacters;
this.xmlSchemaMode = capabilities.contains(RegExpCapability.XML_SCHEMA_MODE);
this.allowDanglingMetacharacters = capabilities.contains(RegExpCapability.DANGLING_METACHARACTERS);
this.allowNestedCharacterClasses = capabilities.contains(RegExpCapability.NESTED_CHARACTER_CLASSES);
this.allowOctalNoLeadingZero = capabilities.contains(RegExpCapability.OCTAL_NO_LEADING_ZERO);
this.commentMode = capabilities.contains(RegExpCapability.COMMENT_MODE);
}
private void yypushstate(int state) {
@@ -58,6 +65,7 @@ import com.intellij.psi.StringEscapesTokenTypes;
%xstate QUOTED
%xstate EMBRACED
%xstate CLASS1
%xstate CLASS1PY
%state CLASS2
%state PROP
%xstate OPTIONS
@@ -133,7 +141,10 @@ HEX_CHAR=[0-9a-fA-F]
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;
}
{ESCAPE} {DIGITS} { return yystate() != CLASS2 ? RegExpTT.BACKREF : RegExpTT.ESC_CHARACTER; }
{ESCAPE} "-" { return RegExpTT.ESC_CHARACTER; }
@@ -146,7 +157,15 @@ HEX_CHAR=[0-9a-fA-F]
{ESCAPE} [:letter:] { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; }
{ESCAPE} [\n\b\t\r\f ] { return commentMode ? RegExpTT.CHARACTER : RegExpTT.REDUNDANT_ESCAPE; }
<CLASS2> {
{ESCAPE} {RBRACKET} { if (!allowNestedCharacterClasses) return RegExpTT.CHARACTER;
return RegExpTT.REDUNDANT_ESCAPE; }
}
{ESCAPE} {ANY} { return RegExpTT.REDUNDANT_ESCAPE; }
{ESCAPE} { return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN; }
<PROP> {
@@ -175,8 +194,37 @@ HEX_CHAR=[0-9a-fA-F]
"-" { return RegExpTT.MINUS; }
"^" { return RegExpTT.CARET; }
{LBRACKET} / {RBRACKET} { yypushstate(CLASS1); return RegExpTT.CLASS_BEGIN; }
{LBRACKET} { yypushstate(CLASS2); return RegExpTT.CLASS_BEGIN; }
<CLASS2> {
{LBRACKET} { if (allowNestedCharacterClasses) {
yypushstate(CLASS2);
return RegExpTT.CLASS_BEGIN;
}
return RegExpTT.CHARACTER;
}
{LBRACKET} / {RBRACKET} { if (allowNestedCharacterClasses) {
yypushstate(CLASS1);
return RegExpTT.CLASS_BEGIN;
}
return RegExpTT.CHARACTER;
}
}
{LBRACKET} / {RBRACKET} { yypushstate(CLASS1);
return RegExpTT.CLASS_BEGIN; }
/* Python understands that, Java doesn't */
{LBRACKET} / "^" {RBRACKET} { if (!allowNestedCharacterClasses) {
yypushstate(CLASS1PY);
}
else {
yypushstate(CLASS2);
}
return RegExpTT.CLASS_BEGIN;
}
{LBRACKET} { yypushstate(CLASS2);
return RegExpTT.CLASS_BEGIN; }
/* []abc] is legal. The first ] is treated as literal character */
<CLASS1> {
@@ -184,14 +232,20 @@ HEX_CHAR=[0-9a-fA-F]
. { assert false : yytext(); }
}
<CLASS1PY> {
"^" { yybegin(CLASS1); return RegExpTT.CARET; }
. { assert false : yytext(); }
}
<CLASS2> {
{RBRACKET} { yypopstate(); return RegExpTT.CLASS_END; }
"&&" { return RegExpTT.ANDAND; }
"&&" { return allowNestedCharacterClasses ? RegExpTT.ANDAND : RegExpTT.CHARACTER; }
[\n\b\t\r\f] { return commentMode ? com.intellij.psi.TokenType.WHITE_SPACE : RegExpTT.ESC_CHARACTER; }
{ANY} { return RegExpTT.CHARACTER; }
}
<YYINITIAL> {
{LPAREN} { return RegExpTT.GROUP_BEGIN; }
{RPAREN} { return RegExpTT.GROUP_END; }
@@ -15,9 +15,8 @@
*/
package com.intellij.debugger.ui.tree.render;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContext;
@@ -29,6 +28,7 @@ import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiExpression;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
import com.sun.jdi.*;
import org.jdom.Element;
@@ -73,7 +73,7 @@ public class ToStringRenderer extends NodeRendererImpl {
final Value value = valueDescriptor.getValue();
BatchEvaluator.getBatchEvaluator(evaluationContext.getDebugProcess()).invoke(new ToStringCommand(evaluationContext, value) {
public void evaluationResult(String message) {
valueDescriptor.setValueLabel(message != null ? "\"" + message + "\"" : "");
valueDescriptor.setValueLabel(message != null ? "\"" + DebuggerUtilsEx.truncateString(message) + "\"" : "");
labelListener.labelChanged();
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.listeners.RefactoringElementAdapter;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import org.jetbrains.annotations.NotNull;
@@ -85,7 +86,7 @@ public class RefactoringListeners {
}
}
private static abstract class RenameElement<T extends PsiElement> implements RefactoringElementListener {
private static abstract class RenameElement<T extends PsiElement> extends RefactoringElementAdapter {
private final Accessor<T> myAccessor;
private final String myPath;
@@ -94,22 +95,15 @@ public class RefactoringListeners {
myPath = path;
}
public void elementMoved(@NotNull final PsiElement newElement) {
setName((T)newElement);
}
public void elementRenamed(@NotNull final PsiElement newElement) {
setName((T)newElement);
}
private void setName(@NotNull T newElement) {
String qualifiedName = getQualifiedName(newElement);
public void elementRenamedOrMoved(@NotNull final PsiElement newElement) {
T newElement1 = (T)newElement;
String qualifiedName = getQualifiedName(newElement1);
if (myPath.length() > 0) {
qualifiedName = qualifiedName + "." + myPath;
newElement = findNewElement(newElement, qualifiedName);
newElement1 = findNewElement(newElement1, qualifiedName);
}
if (newElement != null) {
myAccessor.setPsiElement(newElement);
if (newElement1 != null) {
myAccessor.setPsiElement(newElement1);
}
else {
myAccessor.setName(qualifiedName);
@@ -18,13 +18,10 @@ package com.intellij.execution.ui;
import com.intellij.execution.ExecutionBundle;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.ui.PopupHandler;
import com.intellij.util.ui.EmptyClipboardOwner;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
public class ConfigurationArgumentsHelpArea extends JPanel {
@@ -68,17 +65,8 @@ public class ConfigurationArgumentsHelpArea extends JPanel {
}
public void actionPerformed(final AnActionEvent e) {
try {
final StringSelection contents = new StringSelection(myHelpArea.getText().trim());
final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) {
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(contents, EmptyClipboardOwner.INSTANCE);
} else {
CopyPasteManager.getInstance().setContents(contents);
}
} catch(Exception ex) {
}
final StringSelection contents = new StringSelection(myHelpArea.getText().trim());
CopyPasteManager.getInstance().setContents(contents);
}
}
@@ -19,6 +19,7 @@ package com.intellij.ide.palette.impl;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.palette.PaletteDragEventListener;
import com.intellij.ide.palette.PaletteItem;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
@@ -60,20 +61,22 @@ public class PaletteManager implements ProjectComponent {
}
public void projectOpened() {
StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() {
public void run() {
myPaletteWindow = new PaletteWindow(myProject);
myPaletteToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(IdeBundle.message("toolwindow.palette"),
myPaletteWindow,
ToolWindowAnchor.RIGHT,
myProject,
true, false);
myPaletteToolWindow.setIcon(IconLoader.getIcon("/general/toolWindowPalette.png"));
myPaletteToolWindow.setAvailable(false, null);
final MyFileEditorManagerListener myListener = new MyFileEditorManagerListener();
myFileEditorManager.addFileEditorManagerListener(myListener, myProject);
}
});
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() {
public void run() {
myPaletteWindow = new PaletteWindow(myProject);
myPaletteToolWindow = ToolWindowManager.getInstance(myProject).registerToolWindow(IdeBundle.message("toolwindow.palette"),
myPaletteWindow,
ToolWindowAnchor.RIGHT,
myProject,
true);
myPaletteToolWindow.setIcon(IconLoader.getIcon("/general/toolWindowPalette.png"));
myPaletteToolWindow.setAvailable(false, null);
final MyFileEditorManagerListener myListener = new MyFileEditorManagerListener();
myFileEditorManager.addFileEditorManagerListener(myListener, myProject);
}
});
}
}
public void projectClosed() {
+1
View File
@@ -4,6 +4,7 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/testSrc" isTestSource="true" />
</content>
<orderEntry type="module" module-name="boot" />
<orderEntry type="inheritedJdk" />
@@ -206,10 +206,10 @@ public class ExceptionUtil {
PsiClassType exception = getUnhandledException(statement, topElement);
unhandledExceptions = exception == null ? Collections.<PsiClassType>emptyList() : Collections.singletonList(exception);
}
else if (element instanceof PsiCodeBlock
&& element.getParent() instanceof PsiMethod
&& ((PsiMethod)element.getParent()).isConstructor()
&& !firstStatementIsConstructorCall((PsiCodeBlock)element)) {
else if (element instanceof PsiCodeBlock &&
element.getParent() instanceof PsiMethod &&
((PsiMethod)element.getParent()).isConstructor() &&
!firstStatementIsConstructorCall((PsiCodeBlock)element)) {
// there is implicit parent constructor call
final PsiMethod constructor = (PsiMethod)element.getParent();
final PsiClass aClass = constructor.getContainingClass();
@@ -246,6 +246,16 @@ public class ExceptionUtil {
unhandledExceptions = unhandled;
}
if (element instanceof PsiResource) {
final List<PsiClassType> unhandled = getUnhandledCloserExceptions((PsiResource)element, topElement);
if (unhandledExceptions == null) {
unhandledExceptions = unhandled;
}
else {
unhandledExceptions.addAll(unhandled);
}
}
if (unhandledExceptions != null) {
if (foundExceptions == null) {
foundExceptions = new THashSet<PsiClassType>();
@@ -309,19 +319,36 @@ public class ExceptionUtil {
}
@NotNull
public static List<PsiClassType> getUnhandledExceptions(PsiCallExpression methodCall, PsiElement topElement) {
public static List<PsiClassType> getUnhandledExceptions(final PsiCallExpression methodCall, final PsiElement topElement) {
final JavaResolveResult result = methodCall.resolveMethodGenerics();
PsiMethod method = (PsiMethod)result.getElement();
return getUnhandledExceptions(method, methodCall, topElement,
ApplicationManager.getApplication().runReadAction(new Computable<PsiSubstitutor>() {
public PsiSubstitutor compute() {
return result.getSubstitutor();
}
}));
final PsiMethod method = (PsiMethod)result.getElement();
final PsiSubstitutor substitutor = ApplicationManager.getApplication().runReadAction(new Computable<PsiSubstitutor>() {
public PsiSubstitutor compute() {
return result.getSubstitutor();
}
});
return getUnhandledExceptions(method, methodCall, topElement, substitutor);
}
@NotNull
public static List<PsiClassType> getUnhandledCloserExceptions(final PsiResource resource, final PsiElement topElement) {
final PsiType resourceType = resource.getType();
if (resourceType instanceof PsiClassType) {
final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
if (resourceClass != null) {
final PsiMethod[] closers = resourceClass.findMethodsByName("close", false);
for (final PsiMethod method : closers) {
if (method.getParameterList().getParametersCount() == 0) {
return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY);
}
}
}
}
return Collections.emptyList();
}
@Nullable
public static PsiClassType getUnhandledException(PsiThrowStatement throwStatement, PsiElement topElement){
public static PsiClassType getUnhandledException(PsiThrowStatement throwStatement, PsiElement topElement) {
final PsiExpression exception = throwStatement.getException();
if (exception != null) {
final PsiType type = exception.getType();
@@ -335,7 +362,6 @@ public class ExceptionUtil {
return null;
}
@NotNull
private static List<PsiClassType> getUnhandledExceptions(PsiMethod method,
PsiElement element,
@@ -953,7 +953,7 @@ public class ExpectedTypesProvider {
if (index >= params.length) {
return TailType.NONE;
}
if (index == params.length - 1) {
if (index == params.length - 1 || index == params.length - 2 && params[index + 1].isVarArgs()) {
//myTailType = CompletionUtil.NONE_TAIL;
final PsiElement call = argument.getParent().getParent();
if (call instanceof JspMethodCall) return TailType.NONE;
@@ -31,7 +31,6 @@ import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,16 +38,15 @@ import java.util.Map;
import static com.intellij.patterns.PsiJavaPatterns.psiClass;
import static com.intellij.patterns.PsiJavaPatterns.psiElement;
import static com.intellij.patterns.StandardPatterns.not;
/**
* @author peter
*/
public class BasicExpressionCompletionContributor extends ExpressionSmartCompletionContributor{
public class BasicExpressionCompletionContributor {
public static final ElementPattern<PsiElement> AFTER_DOT = psiElement().afterLeaf(".");
private static void addKeyword(final CompletionResultSet result, final PsiElement element, final String s) {
result.addElement(createKeywordLookupItem(element, s));
private static void addKeyword(final Consumer<LookupElement> result, final PsiElement element, final String s) {
result.consume(createKeywordLookupItem(element, s));
}
public static LookupElement createKeywordLookupItem(final PsiElement element, final String s) {
@@ -61,31 +59,29 @@ public class BasicExpressionCompletionContributor extends ExpressionSmartComplet
}
}
public static void fillCompletionVariants(JavaSmartCompletionParameters parameters,
final Consumer<LookupElement> result,
PrefixMatcher matcher) {
final PsiElement element = parameters.getPosition();
if (PsiJavaPatterns.psiElement().afterLeaf(
PsiJavaPatterns.psiElement().withText(".").afterLeaf(
PsiJavaPatterns.psiElement().withParent(
PsiJavaPatterns.psiElement().referencing(psiClass())))).accepts(element)) {
addKeyword(result, element, PsiKeyword.CLASS);
addKeyword(result, element, PsiKeyword.THIS);
public BasicExpressionCompletionContributor() {
extend(PsiJavaPatterns.psiElement().afterLeaf(
PsiJavaPatterns.psiElement().withText(".").afterLeaf(
PsiJavaPatterns.psiElement().withParent(
PsiJavaPatterns.psiElement().referencing(psiClass())))), new CompletionProvider<JavaSmartCompletionParameters>() {
public void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement element = parameters.getPosition();
addKeyword(result, element, PsiKeyword.CLASS);
addKeyword(result, element, PsiKeyword.THIS);
}
}
});
if (!AFTER_DOT.accepts(element)) {
CollectionsUtilityMethodsProvider.addCompletions(parameters, result);
ClassLiteralGetter.addCompletions(parameters, result, matcher);
extend(not(AFTER_DOT), new CollectionsUtilityMethodsProvider());
extend(not(AFTER_DOT), new ClassLiteralGetter());
extend(not(AFTER_DOT), new CompletionProvider<JavaSmartCompletionParameters>() {
protected void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
final PsiElement position = parameters.getPosition();
final PsiType expectedType = parameters.getExpectedType();
for (final TemplateImpl template : TemplateSettings.getInstance().getTemplates()) {
if (!template.isDeactivated() && template.getTemplateContext().isEnabled(new SmartCompletionContextType())) {
result.addElement(new SmartCompletionTemplateItem(template, position));
result.consume(new SmartCompletionTemplateItem(template, position));
}
}
@@ -100,17 +96,12 @@ public class BasicExpressionCompletionContributor extends ExpressionSmartComplet
}
for (final PsiExpression expression : ThisGetter.getThisExpressionVariants(position)) {
result.addElement(new ExpressionLookupItem(expression));
result.consume(new ExpressionLookupItem(expression));
}
}
processDataflowExpressionTypes(position, expectedType, result.getPrefixMatcher(), new Consumer<LookupElement>() {
public void consume(LookupElement decorator) {
result.addElement(decorator);
}
});
}
});
processDataflowExpressionTypes(position, expectedType, matcher, result);
}
}
@@ -15,19 +15,21 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.NonNls;
import com.intellij.util.ProcessingContext;
import com.intellij.psi.*;
import static com.intellij.psi.CommonClassNames.*;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.*;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import static com.intellij.psi.CommonClassNames.*;
/**
* @author peter
*/
class CollectionsUtilityMethodsProvider extends CompletionProvider<JavaSmartCompletionParameters> {
public void addCompletions(@NotNull final JavaSmartCompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
class CollectionsUtilityMethodsProvider {
public static void addCompletions(@NotNull final JavaSmartCompletionParameters parameters,
@NotNull final Consumer<LookupElement> result) {
final PsiElement element = parameters.getPosition();
final PsiElement parent = element.getParent();
@@ -63,7 +65,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider<JavaSmartComp
}
private static void addCollectionMethod(final CompletionResultSet result, final PsiType expectedType,
private static void addCollectionMethod(final Consumer<LookupElement> result, final PsiType expectedType,
final PsiType defaultType, final String baseClassName,
@NonNls final String method, @NotNull final PsiClass collectionsClass) {
if (isClassType(expectedType, baseClassName) || isClassType(expectedType, JAVA_UTIL_COLLECTION)) {
@@ -73,7 +75,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider<JavaSmartComp
}
}
private static void addMethodItem(CompletionResultSet result, PsiType expectedType, String methodName, PsiClass containingClass) {
private static void addMethodItem(Consumer<LookupElement> result, PsiType expectedType, String methodName, PsiClass containingClass) {
final PsiMethod[] methods = containingClass.findMethodsByName(methodName, false);
if (methods.length == 0) {
return;
@@ -83,7 +85,7 @@ class CollectionsUtilityMethodsProvider extends CompletionProvider<JavaSmartComp
final JavaMethodCallElement item = new JavaMethodCallElement(method);
JavaCompletionUtil.qualify(item).setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType));
result.addElement(item);
result.consume(item);
}
private static boolean isClassType(final PsiType type, final String className) {
@@ -21,7 +21,6 @@ import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.TailTypes;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -31,7 +30,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -73,20 +71,6 @@ public class DefaultInsertHandler extends TemplateInsertHandler implements Clone
handleParentheses(false, false, tailType, context, state);
handleBrackets(item, document, state);
if (item.getObject() instanceof PsiVariable) {
if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(((PsiVariable) item.getObject()).getType())) {
PsiDocumentManager.getInstance(project).commitDocument(document);
final PsiReferenceExpression ref =
PsiTreeUtil.findElementOfClassAtOffset(file, state.tailOffset - 1, PsiReferenceExpression.class, false);
if (ref != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
document.insertString(ref.getTextRange().getStartOffset(), "!");
state.caretOffset++;
state.tailOffset++;
}
}
}
context.setTailOffset(state.tailOffset);
state.caretOffset = processTail(tailType, state.caretOffset, state.tailOffset, editor);
editor.getSelectionModel().removeSelection();
@@ -1,47 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.openapi.util.Pair;
import com.intellij.patterns.ElementPattern;
import com.intellij.psi.PsiElement;
import com.intellij.util.ProcessingContext;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
public abstract class ExpressionSmartCompletionContributor extends AbstractCompletionContributor<JavaSmartCompletionParameters> {
private final List<Pair<ElementPattern<? extends PsiElement>, CompletionProvider<JavaSmartCompletionParameters>>> myList =
new ArrayList<Pair<ElementPattern<? extends PsiElement>, CompletionProvider<JavaSmartCompletionParameters>>>();
public final void extend(final ElementPattern<? extends PsiElement> place, CompletionProvider<JavaSmartCompletionParameters> provider) {
myList.add(new Pair<ElementPattern<? extends PsiElement>, CompletionProvider<JavaSmartCompletionParameters>>(place, provider));
}
public void fillCompletionVariants(final JavaSmartCompletionParameters parameters, CompletionResultSet result) {
for (final Pair<ElementPattern<? extends PsiElement>, CompletionProvider<JavaSmartCompletionParameters>> pair : myList) {
final ProcessingContext context = new ProcessingContext();
if (pair.first.accepts(parameters.getPosition(), context)) {
pair.second.addCompletionVariants(parameters, context, result);
}
}
}
}
@@ -56,7 +56,7 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
CompletionService.getCompletionService().setAdvertisementText(CompletionBundle.message("completion.class.name.hint.2", getActionShortcut(IdeActions.ACTION_CLASS_NAME_COMPLETION)));
}
final CompletionResultSet result = JavaCompletionContributor.addJavaSorting(parameters, _result);
final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result);
final PsiElement insertedElement = parameters.getPosition();
@@ -15,7 +15,6 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.daemon.impl.quickfix.ImportClassFix;
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
@@ -182,7 +181,7 @@ public class JavaCompletionContributor extends CompletionContributor {
}
final CompletionResultSet result = addJavaSorting(parameters, _result);
final CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result);
if (ANNOTATION_ATTRIBUTE_NAME.accepts(position)) {
completeAnnotationAttributeName(result, position, parameters);
@@ -207,18 +206,6 @@ public class JavaCompletionContributor extends CompletionContributor {
result.stopHere();
}
public static CompletionResultSet addJavaSorting(CompletionParameters parameters, CompletionResultSet result) {
final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition());
final ExpectedTypeInfo[] expectedTypes = afterNew ? JavaSmartCompletionContributor.getExpectedTypes(parameters) : ExpectedTypeInfo.EMPTY_ARRAY;
return result.withRelevanceSorter(CompletionSorter.defaultSorter(parameters).weighBefore("liftShorter", new LookupElementWeigher("expectedAfterNew") {
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
return -((Enum)PreferExpectedTypeWeigher.weigh(element, expectedTypes)).ordinal();
}
}));
}
public static void addAllClasses(CompletionParameters parameters,
final CompletionResultSet result,
PsiElement position,
@@ -39,6 +39,7 @@ import com.intellij.psi.jsp.JspElementType;
import com.intellij.psi.scope.ElementClassFilter;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NonNls;
@@ -503,8 +504,9 @@ public class JavaCompletionData extends JavaAwareCompletionData{
new ParentElementFilter(new ClassFilter(PsiSwitchLabelStatement.class)),
new LeftNeighbour(new OrFilter(
new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 2),
new AndFilter(new TextFilter(";", "}", ":"),new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 3)
))))));
new AndFilter(new TextFilter(";", ":"),new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 3)),
new AndFilter(new TextFilter("}"), new ParentElementFilter(new ClassFilter(PsiSwitchStatement.class), 4))
)))));
variant.includeScopeClass(PsiElement.class, false);
variant.addCompletion(PsiKeyword.CASE, TailType.SPACE);
variant.addCompletion(PsiKeyword.DEFAULT, TailType.CASE_COLON);
@@ -549,12 +551,19 @@ public class JavaCompletionData extends JavaAwareCompletionData{
}
@Override
public void fillCompletions(CompletionParameters parameters, CompletionResultSet result) {
public void fillCompletions(CompletionParameters parameters, final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
return;
}
final PsiExpressionStatement expressionStatement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class);
if (expressionStatement != null && expressionStatement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) {
if (!psiElement().withSuperParent(2, PsiSwitchStatement.class).accepts(expressionStatement)) {
result.addElement(createKeyword(position, PsiKeyword.FINAL));
}
}
if (SUPER_OR_THIS_PATTERN.accepts(position)) {
if (AFTER_DOT.accepts(position) && !isInsideQualifierClass(position)) return;
@@ -605,7 +614,7 @@ public class JavaCompletionData extends JavaAwareCompletionData{
if (!PsiKeyword.VOID.equals(primitiveType)) {
result.addElement(TailTypeDecorator.withTail(createKeyword(position, primitiveType), TailType.SPACE));
}
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.SPACE));
//result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.SPACE));
}
}
@@ -630,7 +639,12 @@ public class JavaCompletionData extends JavaAwareCompletionData{
!(position.getParent() instanceof PsiLiteralExpression) &&
!(position.getParent().getParent() instanceof PsiSwitchLabelStatement)) {
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
MembersGetter.addMembers(position, info.getDefaultType(), result);
MembersGetter.addMembers(position, info.getDefaultType(), new Consumer<LookupElement>() {
@Override
public void consume(LookupElement element) {
result.addElement(element);
}
});
}
}
}
@@ -0,0 +1,592 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypeInfoImpl;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementWeigher;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author peter
*/
public class JavaCompletionSorting {
private JavaCompletionSorting() {
}
public static CompletionResultSet addJavaSorting(final CompletionParameters parameters, CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
final ExpectedTypeInfo[] expectedTypes = PsiJavaPatterns.psiElement().beforeLeaf(PsiJavaPatterns.psiElement().withText(".")).accepts(position) ? ExpectedTypeInfo.EMPTY_ARRAY : JavaSmartCompletionContributor.getExpectedTypes(parameters);
final CompletionType type = parameters.getCompletionType();
final boolean smart = type == CompletionType.SMART;
final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position);
List<LookupElementWeigher> afterNegativeStats = new ArrayList<LookupElementWeigher>();
ContainerUtil.addIfNotNull(afterNegativeStats, smart ? new PreferDefaultTypeWeigher(expectedTypes, parameters) : preferStatics(position));
afterNegativeStats.add(new PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(type));
ContainerUtil.addIfNotNull(afterNegativeStats, recursion(parameters, expectedTypes));
if (!smart && !afterNew) {
afterNegativeStats.add(new PreferExpected(false, expectedTypes));
}
afterNegativeStats.add(new PreferSimilarlyEnding(expectedTypes));
List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>();
afterProximity.add(new PreferContainingSameWords(expectedTypes));
if (smart) {
afterProximity.add(new PreferFieldsAndGetters());
}
afterProximity.add(new PreferShorter(expectedTypes));
CompletionSorter sorter = CompletionSorter.defaultSorter(parameters);
if (!smart && afterNew) {
sorter = sorter.weighBefore("liftShorter", new PreferExpected(true, expectedTypes));
}
sorter = sorter.weighAfter("negativeStats", afterNegativeStats.toArray(new LookupElementWeigher[afterNegativeStats.size()]));
sorter = sorter.weighAfter("prefix", new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(), new PreferEnumConstants(parameters));
sorter = sorter.weighAfter("proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()]));
return result.withRelevanceSorter(sorter);
}
@Nullable
private static LookupElementWeigher recursion(CompletionParameters parameters, final ExpectedTypeInfo[] expectedInfos) {
final PsiElement position = parameters.getPosition();
final PsiMethod positionMethod = PsiTreeUtil.getParentOfType(position, PsiMethod.class, false);
final ElementFilter filter = JavaCompletionUtil.recursionFilter(position);
final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class);
final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class);
if (reference == null) return null;
return new RecursionWeigher(filter, position, reference, expression, positionMethod, expectedInfos);
}
@Nullable
private static LookupElementWeigher preferStatics(PsiElement position) {
if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) {
return null;
}
if (position.getParent() instanceof PsiReferenceExpression) {
final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent();
final PsiElement qualifier = refExpr.getQualifier();
if (qualifier == null) {
return null;
}
if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !(((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass)) {
return null;
}
}
return new LookupElementWeigher("statics") {
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object o = element.getObject();
if (!(o instanceof PsiMember)) return 0;
if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) {
if (o instanceof PsiMethod) return -5;
if (o instanceof PsiField) return -4;
}
if (o instanceof PsiClass) return -3;
//instance method or field
return -5;
}
};
}
private static ExpectedTypeMatching getExpectedTypeMatching(LookupElement item, ExpectedTypeInfo[] expectedInfos) {
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (itemType == null) return ExpectedTypeMatching.normal;
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
final PsiType defaultType = expectedInfo.getDefaultType();
final PsiType expectedType = expectedInfo.getType();
if (!expectedType.isValid()) {
return ExpectedTypeMatching.normal;
}
if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) {
return ExpectedTypeMatching.ofDefaultType;
}
if (expectedType.isAssignableFrom(itemType)) {
return ExpectedTypeMatching.expected;
}
}
return ExpectedTypeMatching.normal;
}
@Nullable
private static String getLookupObjectName(Object o) {
if (o instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)o;
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(variable.getProject());
VariableKind variableKind = codeStyleManager.getVariableKind(variable);
return codeStyleManager.variableNameToPropertyName(variable.getName(), variableKind);
}
if (o instanceof PsiMethod) {
return ((PsiMethod)o).getName();
}
return null;
}
private static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos, String prefix) {
int res = 0;
if (name != null && expectedInfos != null) {
if (prefix.equals(name)) {
res = Integer.MAX_VALUE;
} else {
final List<String> words = NameUtil.nameToWordsLowerCase(name);
final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name));
int max1 = calcMatch(words, 0, expectedInfos);
max1 = calcMatch(wordsNoDigits, max1, expectedInfos);
res = max1;
}
}
return res;
}
private static String truncDigits(String name){
int count = name.length() - 1;
while (count >= 0) {
char c = name.charAt(count);
if (!Character.isDigit(c)) break;
count--;
}
return name.substring(0, count + 1);
}
private static int calcMatch(final List<String> words, int max, ExpectedTypeInfo[] myExpectedInfos) {
for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) {
String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName;
if (expectedName == null) continue;
max = calcMatch(expectedName, words, max);
max = calcMatch(truncDigits(expectedName), words, max);
}
return max;
}
private static int calcMatch(final String expectedName, final List<String> words, int max) {
if (expectedName == null) return max;
String[] expectedWords = NameUtil.nameToWords(expectedName);
int limit = Math.min(words.size(), expectedWords.length);
for (int i = 0; i < limit; i++) {
String word = words.get(words.size() - i - 1);
String expectedWord = expectedWords[expectedWords.length - i - 1];
if (word.equalsIgnoreCase(expectedWord)) {
max = Math.max(max, i + 1);
}
else {
break;
}
}
return max;
}
private static class PreferDefaultTypeWeigher extends LookupElementWeigher {
private final PsiTypeParameter myTypeParameter;
private final ExpectedTypeInfo[] myExpectedTypes;
private final CompletionParameters myParameters;
private final CompletionLocation myLocation;
public PreferDefaultTypeWeigher(ExpectedTypeInfo[] expectedTypes, CompletionParameters parameters) {
super("defaultType");
myExpectedTypes = expectedTypes;
myParameters = parameters;
final Pair<PsiClass,Integer> pair = JavaSmartCompletionContributor.getTypeParameterInfo(parameters.getPosition());
myTypeParameter = pair == null ? null : pair.first.getTypeParameters()[pair.second.intValue()];
myLocation = new CompletionLocation(myParameters);
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement item) {
final Object object = item.getObject();
if (object instanceof PsiClass) {
if (myTypeParameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(myTypeParameter)))) {
return MyResult.exactlyExpected;
}
}
if (myExpectedTypes == null) return MyResult.normal;
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (itemType == null || !itemType.isValid()) return MyResult.normal;
if (object instanceof PsiClass) {
for (final ExpectedTypeInfo info : myExpectedTypes) {
if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) {
return AbstractExpectedTypeSkipper.skips(item, myLocation) ? MyResult.expectedNoSelect : MyResult.exactlyExpected;
}
}
}
for (final ExpectedTypeInfo expectedInfo : myExpectedTypes) {
final PsiType defaultType = expectedInfo.getDefaultType();
final PsiType expectedType = expectedInfo.getType();
if (!expectedType.isValid()) {
return MyResult.normal;
}
if (defaultType != expectedType) {
if (defaultType.equals(itemType)) {
return MyResult.exactlyDefault;
}
if (defaultType.isAssignableFrom(itemType)) {
return MyResult.ofDefaultType;
}
}
if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) {
return MyResult.exactlyExpected;
}
}
return MyResult.normal;
}
private enum MyResult {
expectedNoSelect,
exactlyDefault,
ofDefaultType,
exactlyExpected,
normal,
}
}
private static class RecursionWeigher extends LookupElementWeigher {
private final ElementFilter myFilter;
private final PsiElement myPosition;
private final PsiReferenceExpression myReference;
private final PsiMethodCallExpression myExpression;
private final PsiMethod myPositionMethod;
private final ExpectedTypeInfo[] myExpectedInfos;
private final PsiExpression myQualifier;
private final boolean myDelegate;
public RecursionWeigher(ElementFilter filter,
PsiElement position,
@NotNull PsiReferenceExpression reference,
PsiMethodCallExpression expression,
PsiMethod positionMethod, ExpectedTypeInfo[] expectedInfos) {
super("recursion");
myFilter = filter;
myPosition = position;
myReference = reference;
myExpression = expression;
myPositionMethod = positionMethod;
myExpectedInfos = expectedInfos;
myQualifier = myReference.getQualifierExpression();
myDelegate = myQualifier != null && !(myQualifier instanceof PsiThisExpression);
}
private enum Result {
delegation,
normal,
passingObjectToItself,
recursive,
}
@NotNull
@Override
public Result weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal;
if (myFilter != null && !myFilter.isAcceptable(object, myPosition)) {
return Result.recursive;
}
if (isPassingObjectToItself(object)) {
return Result.passingObjectToItself;
}
if (myExpression != null && myPositionMethod != null) {
if (myExpectedInfos != null) {
final PsiType itemType = JavaCompletionUtil.getLookupElementType(element);
if (itemType != null) {
for (final ExpectedTypeInfo expectedInfo : myExpectedInfos) {
if (myPositionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) {
return myDelegate ? Result.delegation : Result.recursive;
}
}
}
}
return Result.normal;
}
if (object instanceof PsiMethod && myPositionMethod != null) {
final PsiMethod method = (PsiMethod)object;
if (PsiTreeUtil.isAncestor(myReference, myPosition, false) &&
Comparing.equal(method.getName(), myPositionMethod.getName())) {
if (!myDelegate && findDeepestSuper(method).equals(findDeepestSuper(myPositionMethod))) {
return Result.recursive;
}
return Result.delegation;
}
}
return Result.normal;
}
private boolean isPassingObjectToItself(Object object) {
if (object instanceof PsiThisExpression) {
return !myDelegate || myQualifier instanceof PsiSuperExpression;
}
return myQualifier instanceof PsiReferenceExpression &&
object.equals(((PsiReferenceExpression)myQualifier).advancedResolve(true).getElement());
}
@NotNull
private static PsiMethod findDeepestSuper(@NotNull final PsiMethod method) {
final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst();
return first == null ? method : first;
}
}
private enum ExpectedTypeMatching {
ofDefaultType,
expected,
normal,
}
private static class PreferAccessible extends LookupElementWeigher {
private final PsiElement myPosition;
public PreferAccessible(PsiElement position) {
super("accessible");
myPosition = position;
}
private enum MyEnum {
NORMAL,
DEPRECATED,
INACCESSIBLE,
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
if (object instanceof PsiDocCommentOwner) {
final PsiDocCommentOwner member = (PsiDocCommentOwner)object;
if (!member.isValid()) {
return MyEnum.NORMAL;
}
if (!JavaPsiFacade.getInstance(member.getProject()).getResolveHelper().isAccessible(member, myPosition, null)) return MyEnum.INACCESSIBLE;
if (member.isDeprecated()) return MyEnum.DEPRECATED;
}
return MyEnum.NORMAL;
}
}
private static class PreferNonGeneric extends LookupElementWeigher {
public PreferNonGeneric() {
super("nonGeneric");
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
if (object instanceof PsiMethod) {
PsiType type = ((PsiMethod)object).getReturnType();
final JavaMethodCallElement callItem = element.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
if (callItem != null) {
type = callItem.getSubstitutor().substitute(type);
}
if (type instanceof PsiClassType && ((PsiClassType) type).resolve() instanceof PsiTypeParameter) return 1;
}
return 0;
}
}
private static class PreferSimple extends LookupElementWeigher {
public PreferSimple() {
super("simple");
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final PsiTypeLookupItem lookupItem = element.as(PsiTypeLookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null) {
return lookupItem.getBracketsCount();
}
if (element.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) {
return 239;
}
return 0;
}
}
private static class PreferEnumConstants extends LookupElementWeigher {
private final CompletionParameters myParameters;
public PreferEnumConstants(CompletionParameters parameters) {
super("constants");
myParameters = parameters;
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
if (element.getObject() instanceof PsiEnumConstant) return -2;
if (!(myParameters.getOriginalFile() instanceof PsiJavaFile)) return -1;
if (PsiKeyword.TRUE.equals(element.getLookupString()) || PsiKeyword.FALSE.equals(element.getLookupString())) {
boolean inReturn = PsiTreeUtil.getParentOfType(myParameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class) != null;
return inReturn ? -2 : 0;
}
return -1;
}
}
private static class PreferExpected extends LookupElementWeigher {
private final boolean myAcceptClasses;
private final ExpectedTypeInfo[] myExpectedTypes;
public PreferExpected(boolean acceptClasses, ExpectedTypeInfo[] expectedTypes) {
super("expectedType");
myAcceptClasses = acceptClasses;
myExpectedTypes = expectedTypes;
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement item) {
return item.getObject() instanceof PsiClass && !myAcceptClasses
? ExpectedTypeMatching.normal : getExpectedTypeMatching(item, myExpectedTypes);
}
}
private static class PreferSimilarlyEnding extends LookupElementWeigher {
private final ExpectedTypeInfo[] myExpectedTypes;
public PreferSimilarlyEnding(ExpectedTypeInfo[] expectedTypes) {
super("nameEnd");
myExpectedTypes = expectedTypes;
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final String name = getLookupObjectName(element.getObject());
return -getNameEndMatchingDegree(name, myExpectedTypes, element.getPrefixMatcher().getPrefix());
}
}
private static class PreferContainingSameWords extends LookupElementWeigher {
private final ExpectedTypeInfo[] myExpectedTypes;
public PreferContainingSameWords(ExpectedTypeInfo[] expectedTypes) {
super("sameWords");
myExpectedTypes = expectedTypes;
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
final String name = getLookupObjectName(object);
if (name != null) {
int max = 0;
final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name));
for (ExpectedTypeInfo myExpectedInfo : myExpectedTypes) {
String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName;
if (expectedName != null) {
final THashSet<String> set = new THashSet<String>(NameUtil.nameToWordsLowerCase(truncDigits(expectedName)));
set.retainAll(wordsNoDigits);
max = Math.max(max, set.size());
}
}
return -max;
}
return 0;
}
}
private static class PreferFieldsAndGetters extends LookupElementWeigher {
public PreferFieldsAndGetters() {
super("fieldsAndGetters");
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
if (object instanceof PsiField) return -2;
if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)object)) return -1;
return 0;
}
}
private static class PreferShorter extends LookupElementWeigher {
private final ExpectedTypeInfo[] myExpectedTypes;
public PreferShorter(ExpectedTypeInfo[] expectedTypes) {
super("shorter");
myExpectedTypes = expectedTypes;
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement element) {
final Object object = element.getObject();
final String name = getLookupObjectName(object);
if (name != null && getNameEndMatchingDegree(name, myExpectedTypes, element.getPrefixMatcher().getPrefix()) != 0) {
return NameUtil.nameToWords(name).length - 1000;
}
return 0;
}
}
}
@@ -105,23 +105,15 @@ public class JavaCompletionUtil {
public static Set<PsiType> getExpectedTypes(final CompletionParameters parameters) {
final PsiExpression expr = PsiTreeUtil.getContextOfType(parameters.getPosition(), PsiExpression.class, true);
if (expr != null) {
final ExpectedTypeInfo[] expectedInfos = JavaSmartCompletionContributor.getExpectedTypes(parameters);
if(expectedInfos != null){
final Set<PsiType> set = new THashSet<PsiType>();
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
set.add(expectedInfo.getType());
}
return set;
final Set<PsiType> set = new THashSet<PsiType>();
for (final ExpectedTypeInfo expectedInfo : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
set.add(expectedInfo.getType());
}
return set;
}
return null;
}
static final NullableLazyKey<PsiMethod, CompletionLocation> POSITION_METHOD = NullableLazyKey.create("positionMethod", new NullableFunction<CompletionLocation, PsiMethod>() {
public PsiMethod fun(final CompletionLocation location) {
return PsiTreeUtil.getParentOfType(location.getCompletionParameters().getPosition(), PsiMethod.class, false);
}
});
public static final Key<List<PsiMethod>> ALL_METHODS_ATTRIBUTE = Key.create("allMethods");
public static PsiType getQualifierType(LookupItem item) {
@@ -323,26 +315,12 @@ public class JavaCompletionUtil {
final PsiReference reference = file.findReferenceAt(selectionEndOffset);
if(reference != null) {
/*
if(reference instanceof PsiJavaCodeReferenceElement){
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getParent().getTextRange().getEndOffset());
}
else{
}
*/
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET,
reference.getElement().getTextRange().getStartOffset() + reference.getRangeInElement().getEndOffset());
element = file.findElementAt(offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));
}
else if (isWord(element)){
/*
if(element instanceof PsiIdentifier && element.getParent() instanceof PsiJavaCodeReferenceElement){
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getParent().getTextRange().getEndOffset());
}
else{
}
*/
offsetMap.addOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET, element.getTextRange().getEndOffset());
element = file.findElementAt(offsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));
@@ -432,75 +410,6 @@ public class JavaCompletionUtil {
return null;
}
public static int getNameEndMatchingDegree(final String name, ExpectedTypeInfo[] expectedInfos, String prefix) {
int res = 0;
if (name != null && expectedInfos != null) {
if (prefix.equals(name)) {
res = Integer.MAX_VALUE;
} else {
final List<String> words = NameUtil.nameToWordsLowerCase(name);
final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(truncDigits(name));
int max1 = calcMatch(words, 0, expectedInfos);
max1 = calcMatch(wordsNoDigits, max1, expectedInfos);
res = max1;
}
}
return res;
}
static String truncDigits(String name){
int count = name.length() - 1;
while (count >= 0) {
char c = name.charAt(count);
if (!Character.isDigit(c)) break;
count--;
}
return name.substring(0, count + 1);
}
private static int calcMatch(final List<String> words, int max, ExpectedTypeInfo[] myExpectedInfos) {
for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) {
String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName;
if (expectedName == null) continue;
max = calcMatch(expectedName, words, max);
max = calcMatch(truncDigits(expectedName), words, max);
}
return max;
}
static int calcMatch(final String expectedName, final List<String> words, int max) {
if (expectedName == null) return max;
String[] expectedWords = NameUtil.nameToWords(expectedName);
int limit = Math.min(words.size(), expectedWords.length);
for (int i = 0; i < limit; i++) {
String word = words.get(words.size() - i - 1);
String expectedWord = expectedWords[expectedWords.length - i - 1];
if (word.equalsIgnoreCase(expectedWord)) {
max = Math.max(max, i + 1);
}
else {
break;
}
}
return max;
}
@Nullable
static String getLookupObjectName(Object o) {
if (o instanceof PsiVariable) {
final PsiVariable variable = (PsiVariable)o;
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(variable.getProject());
VariableKind variableKind = codeStyleManager.getVariableKind(variable);
return codeStyleManager.variableNameToPropertyName(variable.getName(), variableKind);
}
if (o instanceof PsiMethod) {
return ((PsiMethod)o).getName();
}
return null;
}
@Nullable
public static PsiType getLookupElementType(final LookupElement element) {
TypedLookupItem typed = element.as(TypedLookupItem.CLASS_CONDITION_KEY);
@@ -573,7 +482,7 @@ public class JavaCompletionUtil {
return matcher.prefixMatches(s);
}
};
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, nameCondition);
final JavaCompletionProcessor processor = new JavaCompletionProcessor(element, elementFilter, checkAccess, parameters.getInvocationCount() <= 1, nameCondition);
javaReference.processVariants(processor);
final Collection<CompletionElement> plainResults = processor.getResults();
@@ -77,7 +77,7 @@ public class JavaDocCompletionContributor extends CompletionContributor {
if (ref instanceof PsiJavaReference) {
result.stopHere();
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, null);
final JavaCompletionProcessor processor = new JavaCompletionProcessor(position, TrueFilter.INSTANCE, false, false, null);
((PsiJavaReference) ref).processVariants(processor);
for (final CompletionElement _item : processor.getResults()) {
@@ -135,8 +135,11 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
final PsiStatement statement = elementFactory
.createStatementFromText(psiType.getCanonicalText() + " v = new " + canonicalText + "<>()", parameters.getOriginalFile());
final PsiVariable declaredVar = (PsiVariable)((PsiDeclarationStatement)statement).getDeclaredElements()[0];
final PsiExpression initializer = declaredVar.getInitializer();
psiType = initializer.getType();
final PsiNewExpression initializer = (PsiNewExpression)declaredVar.getInitializer();
final boolean hasDefaultConstructorOrNoGenericsOne = PsiDiamondType.hasDefaultConstructor(psiClass) || !PsiDiamondType.haveConstructorsGenericsParameters(psiClass);
if (hasDefaultConstructorOrNoGenericsOne && PsiDiamondType.resolveInferredTypes(initializer).getErrorMessage() == null) {
psiType = initializer.getType();
}
}
}
final LookupItem item = PsiTypeLookupItem.createLookupItem(psiType, parameters.getPosition());
@@ -141,6 +141,12 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
return false;
}
}
if (leaf != null) {
final PsiElement parent = leaf.getParent();
if (parent instanceof PsiReferenceExpression && ((PsiReferenceExpression)parent).getTypeParameters().length > 0) {
return false;
}
}
return SmartCompletionDecorator.hasUnboundTypeParams(getObject());
}
@@ -197,9 +197,9 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
final JavaSmartCompletionParameters parameters = new JavaSmartCompletionParameters(params, info);
final PsiType type = info.getType();
final CompletionService service = CompletionService.getCompletionService();
new BasicExpressionCompletionContributor().fillCompletionVariants(parameters, service.createResultSet(parameters, new Consumer<LookupElement>() {
public void consume(final LookupElement lookupElement) {
BasicExpressionCompletionContributor.fillCompletionVariants(parameters, new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
final TypedLookupItem typed = lookupElement.as(TypedLookupItem.CLASS_CONDITION_KEY);
if (typed != null) {
final PsiType psiType = typed.getType();
@@ -208,12 +208,12 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
}
}
}, JavaSmartCompletionContributor.this));
ReferenceExpressionCompletionContributor.fillCompletionVariants(parameters, service.createResultSet(parameters, new Consumer<LookupElement>() {
}, result.getPrefixMatcher());
ReferenceExpressionCompletionContributor.fillCompletionVariants(parameters, new Consumer<LookupElement>() {
public void consume(final LookupElement lookupElement) {
result.addElement(decorate(lookupElement, _infos));
}
}, JavaSmartCompletionContributor.this));
});
}
}
@@ -335,6 +335,11 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
extend(CompletionType.SMART, AFTER_NEW, new JavaInheritorsGetter(ConstructorInsertHandler.SMART_INSTANCE));
}
@Override
public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
super.fillCompletionVariants(parameters, JavaCompletionSorting.addJavaSorting(parameters, result));
}
public static SmartCompletionDecorator decorate(LookupElement lookupElement, Collection<ExpectedTypeInfo> infos) {
if (lookupElement instanceof LookupItem) {
final LookupItem lookupItem = (LookupItem)lookupElement;
@@ -397,6 +402,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
}
@NotNull
public static ExpectedTypeInfo[] getExpectedTypes(final CompletionParameters parameters) {
final PsiElement position = parameters.getPosition();
if (psiElement().withParent(psiElement(PsiReferenceExpression.class).withParent(PsiThrowStatement.class)).accepts(position)) {
@@ -1,36 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class NameEndMatchingDegreeWeigher extends CompletionWeigher {
public Integer weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final String name = JavaCompletionUtil.getLookupObjectName(element.getObject());
return JavaCompletionUtil.getNameEndMatchingDegree(name, JavaCompletionUtil.EXPECTED_TYPES.getValue(location),
element.getPrefixMatcher().getPrefix());
}
}
@@ -1,51 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiDocCommentOwner;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PreferAccessibleWeigher extends CompletionWeigher {
public MyEnum weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object object = item.getObject();
if (object instanceof PsiDocCommentOwner) {
final PsiDocCommentOwner member = (PsiDocCommentOwner)object;
if (!member.isValid()) {
return MyEnum.NORMAL;
}
if (!JavaPsiFacade.getInstance(member.getProject()).getResolveHelper().isAccessible(member, location.getCompletionParameters().getPosition(), null)) return MyEnum.INACCESSIBLE;
if (member.isDeprecated()) return MyEnum.DEPRECATED;
}
return MyEnum.NORMAL;
}
private enum MyEnum {
INACCESSIBLE,
DEPRECATED,
NORMAL
}
}
@@ -1,105 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.NullableLazyKey;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeParameter;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.NullableFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PreferDefaultTypeWeigher extends CompletionWeigher {
private static final NullableLazyKey<PsiTypeParameter, CompletionLocation> TYPE_PARAMETER = NullableLazyKey.create("expectedTypes", new NullableFunction<CompletionLocation, PsiTypeParameter>() {
@Nullable
public PsiTypeParameter fun(final CompletionLocation location) {
final Pair<PsiClass,Integer> pair =
JavaSmartCompletionContributor.getTypeParameterInfo(location.getCompletionParameters().getPosition());
if (pair == null) return null;
return pair.first.getTypeParameters()[pair.second.intValue()];
}
});
private enum MyResult {
normal,
exactlyExpected,
ofDefaultType,
exactlyDefault,
expectedNoSelect
}
public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object object = item.getObject();
if (location.getCompletionType() != CompletionType.SMART) return MyResult.normal;
if (object instanceof PsiClass) {
final PsiTypeParameter parameter = TYPE_PARAMETER.getValue(location);
if (parameter != null && object.equals(PsiUtil.resolveClassInType(TypeConversionUtil.typeParameterErasure(parameter)))) {
return MyResult.exactlyExpected;
}
}
ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
if (expectedInfos == null) return MyResult.normal;
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (itemType == null || !itemType.isValid()) return MyResult.normal;
if (object instanceof PsiClass) {
for (final ExpectedTypeInfo info : expectedInfos) {
if (TypeConversionUtil.erasure(info.getType().getDeepComponentType()).equals(TypeConversionUtil.erasure(itemType))) {
return AbstractExpectedTypeSkipper.skips(item, location) ? MyResult.expectedNoSelect : MyResult.exactlyExpected;
}
}
}
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
final PsiType defaultType = expectedInfo.getDefaultType();
final PsiType expectedType = expectedInfo.getType();
if (!expectedType.isValid()) {
return MyResult.normal;
}
if (defaultType != expectedType) {
if (defaultType.equals(itemType)) {
return MyResult.exactlyDefault;
}
if (defaultType.isAssignableFrom(itemType)) {
return MyResult.ofDefaultType;
}
}
if (PsiType.VOID.equals(itemType) && PsiType.VOID.equals(expectedType)) {
return MyResult.exactlyExpected;
}
}
return MyResult.normal;
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PreferEnumConstantsWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
if (item.getObject() instanceof PsiEnumConstant) return 2;
final CompletionParameters parameters = location.getCompletionParameters();
if (!(parameters.getOriginalFile() instanceof PsiJavaFile)) return 1;
if (PsiKeyword.TRUE.equals(item.getLookupString()) || PsiKeyword.FALSE.equals(item.getLookupString())) {
boolean inReturn = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class) != null;
return inReturn ? 2 : 0;
}
return 1;
}
}
@@ -1,70 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class PreferExpectedTypeWeigher extends CompletionWeigher {
private enum MyResult {
normal,
expected,
ofDefaultType,
}
public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location.getCompletionType() != CompletionType.BASIC) return MyResult.normal;
if (item.getObject() instanceof PsiClass) {
if (!JavaSmartCompletionContributor.AFTER_NEW.accepts(location.getCompletionParameters().getPosition())) {
return MyResult.normal;
}
}
ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
if (expectedInfos == null) return MyResult.normal;
return weigh(item, expectedInfos);
}
public static MyResult weigh(LookupElement item, ExpectedTypeInfo[] expectedInfos) {
PsiType itemType = JavaCompletionUtil.getLookupElementType(item);
if (itemType == null) return MyResult.normal;
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
final PsiType defaultType = expectedInfo.getDefaultType();
final PsiType expectedType = expectedInfo.getType();
if (!expectedType.isValid()) {
return MyResult.normal;
}
if (defaultType != expectedType && defaultType.isAssignableFrom(itemType)) {
return MyResult.ofDefaultType;
}
if (expectedType.isAssignableFrom(itemType)) {
return MyResult.expected;
}
}
return MyResult.normal;
}
}
@@ -1,41 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PropertyUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PreferFieldsAndGettersWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
if (location.getCompletionType() != CompletionType.SMART) return 0;
final Object object = item.getObject();
if (object instanceof PsiField) return 2;
if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)object)) return 1;
return 0;
}
}
@@ -16,38 +16,47 @@
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementWeigher;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends CompletionWeigher {
public class PreferLocalVariablesLiteralsAndAnnoMethodsWeigher extends LookupElementWeigher {
private final CompletionType myCompletionType;
enum MyResult {
className,
classLiteral,
normal,
superMethodParameters,
localOrParameter,
annoMethod,
public PreferLocalVariablesLiteralsAndAnnoMethodsWeigher(CompletionType completionType) {
super("local");
myCompletionType = completionType;
}
public MyResult weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
enum MyResult {
annoMethod,
localOrParameter,
superMethodParameters,
normal,
classLiteral,
className,
}
@NotNull
@Override
public Comparable weigh(@NotNull LookupElement item) {
final Object object = item.getObject();
if (object instanceof PsiLocalVariable || object instanceof PsiParameter || object instanceof PsiThisExpression) {
return MyResult.localOrParameter;
}
if (location.getCompletionType() == CompletionType.SMART) {
if (myCompletionType == CompletionType.SMART) {
if (object instanceof String && item.getUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS) == Boolean.TRUE) {
return MyResult.superMethodParameters;
}
return MyResult.normal;
}
if (location.getCompletionType() == CompletionType.BASIC) {
if (myCompletionType == CompletionType.BASIC) {
if (object instanceof PsiKeyword && PsiKeyword.CLASS.equals(item.getLookupString())) {
return MyResult.classLiteral;
}
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeParameter;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class PreferNonGenericWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
final Object object = item.getObject();
if (object instanceof PsiMethod) {
PsiType type = ((PsiMethod)object).getReturnType();
final JavaMethodCallElement callItem = item.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
if (callItem != null) {
type = callItem.getSubstitutor().substitute(type);
}
if (type instanceof PsiClassType && ((PsiClassType) type).resolve() instanceof PsiTypeParameter) return -1;
}
return 0;
}
}
@@ -1,44 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.codeStyle.NameUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
*/
public class PreferShorterWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object object = item.getObject();
final String name = JavaCompletionUtil.getLookupObjectName(object);
final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
if (name != null && expectedInfos != null && JavaCompletionUtil.getNameEndMatchingDegree(name, expectedInfos,
item.getPrefixMatcher().getPrefix()) != 0) {
return 239 - NameUtil.nameToWords(name).length;
}
return 0;
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class PreferSimpleWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
final PsiTypeLookupItem lookupItem = item.as(PsiTypeLookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null) {
return -lookupItem.getBracketsCount();
}
if (item.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) {
return -239;
}
return 0;
}
}
@@ -1,106 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class RecursionWeigher extends CompletionWeigher {
private enum Result {
recursive,
passingObjectToItself,
normal,
delegation,
}
public Result weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
if (location.getCompletionType() != CompletionType.BASIC && location.getCompletionType() != CompletionType.SMART) return Result.normal;
final Object object = element.getObject();
if (!(object instanceof PsiMethod || object instanceof PsiVariable || object instanceof PsiExpression)) return Result.normal;
final PsiMethod positionMethod = JavaCompletionUtil.POSITION_METHOD.getValue(location);
final PsiElement position = location.getCompletionParameters().getPosition();
final ElementFilter filter = JavaCompletionUtil.recursionFilter(position);
if (filter != null && !filter.isAcceptable(object, position)) {
return Result.recursive;
}
final PsiMethodCallExpression expression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class, true, PsiClass.class);
final PsiReferenceExpression reference = expression != null ? expression.getMethodExpression() : PsiTreeUtil.getParentOfType(position, PsiReferenceExpression.class);
if (reference == null) return Result.normal;
final PsiExpression qualifier = reference.getQualifierExpression();
boolean isDelegate = qualifier != null && !(qualifier instanceof PsiThisExpression);
if (isPassingObjectToItself(object, qualifier, isDelegate)) {
return Result.passingObjectToItself;
}
if (expression != null && positionMethod != null) {
final ExpectedTypeInfo[] expectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
if (expectedInfos != null) {
final PsiType itemType = JavaCompletionUtil.getLookupElementType(element);
if (itemType != null) {
for (final ExpectedTypeInfo expectedInfo : expectedInfos) {
if (positionMethod.equals(expectedInfo.getCalledMethod()) && expectedInfo.getType().isAssignableFrom(itemType)) {
return isDelegate ? Result.delegation : Result.recursive;
}
}
}
}
return Result.normal;
}
if (object instanceof PsiMethod && positionMethod != null) {
final PsiMethod method = (PsiMethod)object;
if (PsiTreeUtil.isAncestor(reference, position, false) &&
Comparing.equal(method.getName(), positionMethod.getName()) &&
method.getParameterList().getParametersCount() == positionMethod.getParameterList().getParametersCount()) {
if (findDeepestSuper(method).equals(findDeepestSuper(positionMethod))) {
return isDelegate ? Result.delegation : Result.recursive;
}
}
}
return Result.normal;
}
private static boolean isPassingObjectToItself(Object object, PsiExpression qualifier, boolean delegate) {
if (object instanceof PsiThisExpression) {
return !delegate || qualifier instanceof PsiSuperExpression;
}
return qualifier instanceof PsiReferenceExpression &&
object.equals(((PsiReferenceExpression)qualifier).advancedResolve(true).getElement());
}
@NotNull
private static PsiMethod findDeepestSuper(@NotNull final PsiMethod method) {
final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst();
return first == null ? method : first;
}
}
@@ -104,7 +104,7 @@ public class ReferenceExpressionCompletionContributor {
return TrueFilter.INSTANCE;
}
public static void fillCompletionVariants(final JavaSmartCompletionParameters parameters, final CompletionResultSet result) {
public static void fillCompletionVariants(final JavaSmartCompletionParameters parameters, final Consumer<LookupElement> result) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
final PsiElement element = parameters.getPosition();
@@ -115,7 +115,7 @@ public class ReferenceExpressionCompletionContributor {
if (reference != null) {
final ElementFilter filter = getReferenceFilter(element, false);
for (final LookupElement item : completeFinalReference(element, reference, filter, parameters)) {
result.addElement(item);
result.consume(item);
}
final boolean secondTime = parameters.getInvocationCount() >= 2;
@@ -180,7 +180,7 @@ public class ReferenceExpressionCompletionContributor {
}
private static void addSingleArrayElementAccess(PsiElement element, LookupElement item, JavaSmartCompletionParameters parameters,
CompletionResultSet result) {
Consumer<LookupElement> result) {
if (item.getObject() instanceof PsiLocalVariable) {
final PsiLocalVariable variable = (PsiLocalVariable)item.getObject();
final PsiType type = variable.getType();
@@ -192,7 +192,7 @@ public class ReferenceExpressionCompletionContributor {
if (dimensions.length == 1 && "1".equals(dimensions[0].getText()) && newExpression.getArrayInitializer() == null) {
final String text = variable.getName() + "[0]";
final PsiExpression conversion = createExpression(text, element);
result.addElement(new ExpressionLookupItem(conversion).setIcon(variable.getIcon(Iconable.ICON_FLAG_VISIBILITY)));
result.consume(new ExpressionLookupItem(conversion).setIcon(variable.getIcon(Iconable.ICON_FLAG_VISIBILITY)));
}
}
}
@@ -204,7 +204,7 @@ public class ReferenceExpressionCompletionContributor {
}
private static void addSecondCompletionVariants(PsiElement element, PsiReference reference, LookupElement baseItem,
JavaSmartCompletionParameters parameters, CompletionResultSet result) {
JavaSmartCompletionParameters parameters, Consumer<LookupElement> result) {
final Object object = baseItem.getObject();
try {
@@ -236,7 +236,7 @@ public class ReferenceExpressionCompletionContributor {
}
private static void addArrayMemberAccessors(final PsiElement element, final String prefix, final PsiType itemType,
final PsiElement qualifier, final CompletionResultSet result, PsiModifierListOwner object,
final PsiElement qualifier, final Consumer<LookupElement> result, PsiModifierListOwner object,
final PsiType expectedType)
throws IncorrectOperationException {
if (itemType instanceof PsiArrayType && expectedType.isAssignableFrom(((PsiArrayType)itemType).getComponentType())) {
@@ -262,7 +262,7 @@ public class ReferenceExpressionCompletionContributor {
editor.getCaretModel().moveToOffset(tailOffset + 1 + callSpace.length());
}
});
result.addElement(item);
result.consume(item);
}
}
@@ -276,7 +276,7 @@ public class ReferenceExpressionCompletionContributor {
return false;
}
private static void addArraysAsListConversions(final PsiElement element, final String prefix, final PsiType itemType, final CompletionResultSet result,
private static void addArraysAsListConversions(final PsiElement element, final String prefix, final PsiType itemType, final Consumer<LookupElement> result,
@Nullable PsiElement qualifier,
final PsiType expectedType) throws IncorrectOperationException {
PsiType componentType = PsiUtil.extractIterableTypeParameter(expectedType, true);
@@ -321,11 +321,11 @@ public class ReferenceExpressionCompletionContributor {
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
}
});
result.addElement(item);
result.consume(item);
}
private static void addToArrayConversions(final PsiElement element, final Object object, final String prefix, final PsiType itemType,
final CompletionResultSet result, @Nullable final PsiElement qualifier,
final Consumer<LookupElement> result, @Nullable final PsiElement qualifier,
final PsiType expectedType) {
final String callSpace = getSpace(CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_WITHIN_METHOD_CALL_PARENTHESES);
final PsiType componentType = PsiUtil.extractIterableTypeParameter(itemType, true);
@@ -380,7 +380,7 @@ public class ReferenceExpressionCompletionContributor {
}
private static void addChainedCallVariants(final PsiElement place, LookupElement qualifierItem,
final CompletionResultSet result,
final Consumer<LookupElement> result,
PsiType qualifierType,
final PsiType expectedType, JavaSmartCompletionParameters parameters) throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(place.getProject()).getElementFactory();
@@ -404,7 +404,7 @@ public class ReferenceExpressionCompletionContributor {
final ElementFilter filter = getReferenceFilter(place, true);
for (final LookupElement item : completeFinalReference(place, mockRef, filter, parameters)) {
if (shoudChain(place, varType, expectedType, item)) {
result.addElement(JavaChainLookupElement.chainElements(qualifierItem, item));
result.consume(JavaChainLookupElement.chainElements(qualifierItem, item));
}
}
}
@@ -454,7 +454,7 @@ public class ReferenceExpressionCompletionContributor {
return true;
}
private static void addToArrayConversion(final PsiElement element, final String prefix, @NonNls final String expressionString, @NonNls String presentableString, final CompletionResultSet result, PsiElement qualifier) {
private static void addToArrayConversion(final PsiElement element, final String prefix, @NonNls final String expressionString, @NonNls String presentableString, final Consumer<LookupElement> result, PsiElement qualifier) {
final boolean callSpace = CodeStyleSettingsManager.getSettings(element.getProject()).SPACE_WITHIN_METHOD_CALL_PARENTHESES;
final PsiExpression conversion;
try {
@@ -490,7 +490,7 @@ public class ReferenceExpressionCompletionContributor {
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
}
});
result.addElement(item);
result.consume(item);
}
private static boolean isEmptyArrayInitializer(@Nullable PsiElement element) {
@@ -1,56 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypeInfoImpl;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.codeStyle.NameUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author peter
*/
public class SameWordsWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object object = item.getObject();
final String name = JavaCompletionUtil.getLookupObjectName(object);
final ExpectedTypeInfo[] myExpectedInfos = JavaCompletionUtil.EXPECTED_TYPES.getValue(location);
if (name != null && myExpectedInfos != null) {
int max = 0;
final List<String> wordsNoDigits = NameUtil.nameToWordsLowerCase(JavaCompletionUtil.truncDigits(name));
for (ExpectedTypeInfo myExpectedInfo : myExpectedInfos) {
String expectedName = ((ExpectedTypeInfoImpl)myExpectedInfo).expectedName;
if (expectedName != null) {
final THashSet<String> set = new THashSet<String>(NameUtil.nameToWordsLowerCase(JavaCompletionUtil.truncDigits(expectedName)));
set.retainAll(wordsNoDigits);
max = Math.max(max, set.size());
}
}
return max;
}
return 0;
}
}
@@ -8,7 +8,6 @@ import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.util.Key;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.PsiElementPattern;
import com.intellij.psi.*;
@@ -16,9 +15,11 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.tree.java.PsiEmptyExpressionImpl;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -27,58 +28,101 @@ class SmartCastProvider extends CompletionProvider<CompletionParameters> {
static final PsiElementPattern.Capture<PsiElement> INSIDE_TYPECAST_TYPE = PlatformPatterns.psiElement().afterLeaf(
PlatformPatterns.psiElement().withText("(").withParent(
PsiTypeCastExpression.class));
public static final Key<Boolean> TYPE_CAST = Key.create("TYPE_CAST");
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
for (final ExpectedTypeInfo type : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
if (type.getType() == PsiType.VOID) {
for (final ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) {
final PsiElement originalPosition = parameters.getOriginalPosition();
final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(originalPosition);
PsiType type = info.getDefaultType();
if (type instanceof PsiWildcardType) {
type = ((PsiWildcardType)type).getBound();
}
if (type == null || type == PsiType.VOID) {
continue;
}
final boolean overwrite = INSIDE_TYPECAST_TYPE.accepts(parameters.getOriginalPosition());
final LookupElement item = AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE.applyPolicy(new LookupElementDecorator<LookupItem>(
PsiTypeLookupItem.createLookupItem(type.getDefaultType(), parameters.getPosition())) {
@Override
public void handleInsert(InsertionContext context) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.casting");
final Editor editor = context.getEditor();
final Document document = editor.getDocument();
if (overwrite) {
document.deleteString(context.getSelectionEndOffset(),
context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));
result.addElement(createSmartCastElement(parameters, overwrite, type));
if (type instanceof PsiPrimitiveType) {
final PsiType castedType = getCastedExpressionType(originalPosition);
if (castedType != null && !(castedType instanceof PsiPrimitiveType)) {
final PsiClassType boxedType = ((PsiPrimitiveType)type).getBoxedType(originalPosition);
if (boxedType != null) {
result.addElement(createSmartCastElement(parameters, overwrite, boxedType));
}
final CodeStyleSettings csSettings = CodeStyleSettingsManager.getSettings(context.getProject());
final int oldTail = context.getTailOffset();
context.setTailOffset(RParenthTailType.addRParenth(editor, oldTail, csSettings.SPACE_WITHIN_CAST_PARENTHESES));
//todo let the delegate handle insertion itself
final LookupItem typeItem = getDelegate();
final InsertionContext typeContext = CompletionUtil.newContext(context, typeItem, context.getStartOffset(), oldTail);
new DefaultInsertHandler().handleInsert(typeContext, typeItem);
final PsiTypeCastExpression castExpression =
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiTypeCastExpression.class, false);
if (castExpression != null) {
final PsiTypeElement typeElement = castExpression.getCastType();
if (typeElement != null) {
CodeStyleManager.getInstance(context.getProject()).reformat(typeElement);
}
}
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
if (csSettings.SPACE_AFTER_TYPE_CAST) {
context.setTailOffset(TailType.insertChar(editor, context.getTailOffset(), ' '));
}
editor.getCaretModel().moveToOffset(context.getTailOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
});
item.putUserData(TYPE_CAST, Boolean.TRUE);
result.addElement(item);
}
}
}
@Nullable
private static PsiType getCastedExpressionType(PsiElement originalPosition) {
if (INSIDE_TYPECAST_TYPE.accepts(originalPosition)) {
final PsiTypeCastExpression cast = PsiTreeUtil.getParentOfType(originalPosition, PsiTypeCastExpression.class);
if (cast != null) {
final PsiExpression operand = cast.getOperand();
return operand == null ? null : operand.getType();
}
}
final PsiParenthesizedExpression parens = PsiTreeUtil.getParentOfType(originalPosition, PsiParenthesizedExpression.class, true, PsiStatement.class);
if (parens != null) {
final PsiExpression rightSide = parens.getExpression();
if (rightSide != null) {
return rightSide.getType();
}
PsiElement next = parens.getNextSibling();
while (next != null && (next instanceof PsiEmptyExpressionImpl || next instanceof PsiErrorElement || next instanceof PsiWhiteSpace)) {
next = next.getNextSibling();
}
if (next instanceof PsiExpression) {
return ((PsiExpression)next).getType();
}
return null;
}
return null;
}
private static LookupElement createSmartCastElement(final CompletionParameters parameters, final boolean overwrite, final PsiType type) {
return AutoCompletionPolicy.ALWAYS_AUTOCOMPLETE.applyPolicy(new LookupElementDecorator<LookupItem>(
PsiTypeLookupItem.createLookupItem(type, parameters.getPosition())) {
@Override
public void handleInsert(InsertionContext context) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.casting");
final Editor editor = context.getEditor();
final Document document = editor.getDocument();
if (overwrite) {
document.deleteString(context.getSelectionEndOffset(),
context.getOffsetMap().getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET));
}
final CodeStyleSettings csSettings = CodeStyleSettingsManager.getSettings(context.getProject());
final int oldTail = context.getTailOffset();
context.setTailOffset(RParenthTailType.addRParenth(editor, oldTail, csSettings.SPACE_WITHIN_CAST_PARENTHESES));
//todo let the delegate handle insertion itself
final LookupItem typeItem = getDelegate();
final InsertionContext typeContext = CompletionUtil.newContext(context, typeItem, context.getStartOffset(), oldTail);
new DefaultInsertHandler().handleInsert(typeContext, typeItem);
final PsiTypeCastExpression castExpression =
PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getStartOffset(), PsiTypeCastExpression.class, false);
if (castExpression != null) {
final PsiTypeElement typeElement = castExpression.getCastType();
if (typeElement != null) {
CodeStyleManager.getInstance(context.getProject()).reformat(typeElement);
}
}
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting();
if (csSettings.SPACE_AFTER_TYPE_CAST) {
context.setTailOffset(TailType.insertChar(editor, context.getTailOffset(), ' '));
}
editor.getCaretModel().moveToOffset(context.getTailOffset());
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
});
}
}
@@ -1,61 +0,0 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class StaticMembersWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull LookupElement element, @NotNull CompletionLocation loc) {
if (loc.getCompletionType() != CompletionType.BASIC) return 0;
// cheap weigher applicability goes first
final Object o = element.getObject();
if (!(o instanceof PsiMember)) return 0;
final PsiElement position = loc.getCompletionParameters().getPosition();
if (PsiTreeUtil.getParentOfType(position, PsiDocComment.class) != null) return 0;
if (position.getParent() instanceof PsiReferenceExpression) {
final PsiReferenceExpression refExpr = (PsiReferenceExpression)position.getParent();
final PsiElement qualifier = refExpr.getQualifier();
if (qualifier == null) {
return 0;
}
if (!(qualifier instanceof PsiJavaCodeReferenceElement) || !(((PsiJavaCodeReferenceElement)qualifier).resolve() instanceof PsiClass)) {
return 0;
}
}
if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC)) {
if (o instanceof PsiMethod) return 5;
if (o instanceof PsiField) return 4;
}
if (o instanceof PsiClass) {
//if (((PsiClass) o).getContainingClass() != null) return 2;
return 3;
}
//instance method or field
return 5;
}
}
@@ -26,14 +26,13 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.scope.BaseScopeProcessor;
import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.JavaScopeProcessorEvent;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* Created by IntelliJ IDEA.
@@ -58,8 +57,9 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
private PsiClass myQualifierClass = null;
private final Condition<String> myMatcher;
private final boolean myCheckAccess;
private final Set<PsiField> myNonInitializedFields = new HashSet<PsiField>();
public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, @Nullable Condition<String> nameCondition) {
public JavaCompletionProcessor(PsiElement element, ElementFilter filter, final boolean checkAccess, boolean checkInitialized, @Nullable Condition<String> nameCondition) {
myCheckAccess = checkAccess;
mySettings = CodeInsightSettings.getInstance();
myResults = new ArrayList<CompletionElement>();
@@ -102,6 +102,65 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
}
}
}
if (checkInitialized) {
myNonInitializedFields.addAll(getNonInitializedFields(element));
}
}
private static Set<PsiField> getNonInitializedFields(PsiElement element) {
final PsiStatement statement = PsiTreeUtil.getParentOfType(element, PsiStatement.class);
final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, true, PsiClass.class);
if (statement == null || method == null || !method.isConstructor()) {
return Collections.emptySet();
}
PsiElement parent = element.getParent();
while (parent != statement) {
PsiElement next = parent.getParent();
if (next instanceof PsiAssignmentExpression && parent == ((PsiAssignmentExpression)next).getLExpression()) {
return Collections.emptySet();
}
if (parent instanceof PsiReferenceExpression && next instanceof PsiExpressionStatement) {
return Collections.emptySet();
}
parent = next;
}
final Set<PsiField> fields = new HashSet<PsiField>();
final PsiClass containingClass = method.getContainingClass();
assert containingClass != null;
for (PsiField field : containingClass.getFields()) {
if (!field.hasModifierProperty(PsiModifier.STATIC) && field.getInitializer() == null) {
fields.add(field);
}
}
method.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) {
final PsiExpression lExpression = expression.getLExpression();
if (lExpression instanceof PsiReferenceExpression) {
//noinspection SuspiciousMethodCalls
fields.remove(((PsiReferenceExpression)lExpression).resolve());
}
}
super.visitAssignmentExpression(expression);
}
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
if (expression.getTextRange().getStartOffset() < statement.getTextRange().getStartOffset()) {
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
if (methodExpression.textMatches("this")) {
fields.clear();
}
}
super.visitMethodCallExpression(expression);
}
});
return fields;
}
public void handleEvent(Event event, Object associated){
@@ -113,19 +172,24 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme
}
}
public boolean execute(PsiElement element, ResolveState state){
if(!(element instanceof PsiClass) && element instanceof PsiModifierListOwner){
public boolean execute(PsiElement element, ResolveState state) {
//noinspection SuspiciousMethodCalls
if (myNonInitializedFields.contains(element)) {
return true;
}
if (!(element instanceof PsiClass) && element instanceof PsiModifierListOwner) {
PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)element;
if(myStatic){
if(!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)){
if (myStatic) {
if (!modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) {
// we don't need non static method in static context.
return true;
}
}
else{
if(!mySettings.SHOW_STATIC_AFTER_INSTANCE
&& modifierListOwner.hasModifierProperty(PsiModifier.STATIC)
&& !myMembersFlag){
else {
if (!mySettings.SHOW_STATIC_AFTER_INSTANCE
&& modifierListOwner.hasModifierProperty(PsiModifier.STATIC)
&& !myMembersFlag) {
// according settings we don't need to process such fields/methods
return true;
}
@@ -16,16 +16,23 @@
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -221,7 +228,7 @@ public class AnnotationsHighlightUtil {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("annotation.invalid.annotation.member.type"));
}
public static HighlightInfo checkApplicability(PsiAnnotation annotation) {
public static HighlightInfo checkApplicability(final PsiAnnotation annotation) {
PsiAnnotationOwner owner = annotation.getOwner();
if (!(owner instanceof PsiModifierList || owner instanceof PsiTypeElement || owner instanceof PsiMethodReceiver || owner instanceof PsiTypeParameter)) return null;
PsiElement member = ((PsiElement)owner).getParent();
@@ -231,7 +238,9 @@ public class AnnotationsHighlightUtil {
String description = JavaErrorMessages.message("annotation.not.applicable",
nameRef.getText(),
JavaErrorMessages.message("annotation.target." + elementTypeFields[0]));
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description);
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description);
QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation));
return highlightInfo;
}
public static boolean isAnnotationApplicableTo(PsiAnnotation annotation, boolean strict, String... elementTypeFields) {
@@ -445,4 +454,40 @@ public class AnnotationsHighlightUtil {
return classType.equalsToText("java.lang.Class") || classType.equalsToText("java.lang.String") ? Boolean.TRUE : Boolean.FALSE;
}
}
private static class DeleteNotApplicableAnnotationAction implements IntentionAction {
private final PsiAnnotation myAnnotation;
public DeleteNotApplicableAnnotationAction(PsiAnnotation annotation) {
myAnnotation = annotation;
}
@NotNull
@Override
public String getText() {
return "Remove";
}
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;
myAnnotation.delete();
}
@Override
public boolean startInWriteAction() {
return true;
}
}
}
@@ -107,6 +107,22 @@ public class GenericsHighlightUtil {
}
}
PsiDiamondType.DiamondInferenceResult inferenceResult = null;
PsiTypeElement[] referenceElements = null;
if (referenceParameterList != null) {
referenceElements = referenceParameterList.getTypeParameterElements();
if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) {
if (!typeParameterListOwner.hasTypeParameters()) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], "Diamond operator is not applicable for non-parameterized types");
}
inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes();
final String errorMessage = inferenceResult.getErrorMessage();
if (errorMessage != null) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], errorMessage);
}
}
}
final PsiTypeParameter[] typeParameters = typeParameterListOwner.getTypeParameters();
final int targetParametersNum = typeParameters.length;
final int refParametersNum = referenceParameterList == null ? 0 : referenceParameterList.getTypeArguments().length;
@@ -140,9 +156,8 @@ public class GenericsHighlightUtil {
// bounds check
if (targetParametersNum > 0 && refParametersNum != 0) {
final PsiTypeElement[] referenceElements = referenceParameterList.getTypeParameterElements();
if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) {
final PsiType[] types = ((PsiDiamondType)referenceElements[0].getType()).getInferredTypes();
if (inferenceResult != null) {
final PsiType[] types = inferenceResult.getTypes();
for (int i = 0; i < typeParameters.length; i++) {
final PsiType type = types[i];
final HighlightInfo highlightInfo = checkTypeParameterWithinItsBound(typeParameters[i], substitutor, type, referenceElements[0]);
@@ -13,15 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: cdr
* Date: Aug 8, 2002
* Time: 5:55:01 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.codeInsight.daemon.impl.analysis;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
@@ -43,9 +34,14 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author cdr
* Date: Aug 8, 2002
*/
public class HighlightControlFlowUtil {
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
private HighlightControlFlowUtil() { }
@Nullable
public static HighlightInfo checkMissingReturnStatement(PsiMethod method) {
@@ -297,7 +293,7 @@ public class HighlightControlFlowUtil {
topBlock = JspPsiUtil.isInJspFile(scope) && scope instanceof PsiFile ? scope : PsiUtil.getTopLevelEnclosingCodeBlock(expression, scope);
if (variable instanceof PsiField) {
// non final field already initalized with default value
// non final field already initialized with default value
if (!variable.hasModifierProperty(PsiModifier.FINAL)) return null;
// final field may be initialized in ctor or class initializer only
// if we're inside non-ctr method, skip it
@@ -314,9 +310,9 @@ public class HighlightControlFlowUtil {
if (parent instanceof PsiMethod) {
PsiMethod constructor = (PsiMethod)parent;
if (!parent.getManager().areElementsEquivalent(constructor.getContainingClass(), ((PsiField)variable).getContainingClass())) return null;
// static variables already initalized in class initalizers
// static variables already initialized in class initializers
if (variable.hasModifierProperty(PsiModifier.STATIC)) return null;
// as a last chance, field may be initalized in this() call
// as a last chance, field may be initialized in this() call
final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
@@ -338,7 +334,7 @@ public class HighlightControlFlowUtil {
aClass = classInitializer.getContainingClass();
}
else {
// field reference outside codeblock
// field reference outside code block
// check variable initialized before its usage
final PsiField field = (PsiField)variable;
@@ -356,7 +352,7 @@ public class HighlightControlFlowUtil {
&& variableDefinitelyAssignedIn(variable, constructor.getBody())) {
return null;
}
// as a last chance, field may be initalized in this() call
// as a last chance, field may be initialized in this() call
final List<PsiMethod> redirectedConstructors = getChainedConstructors(constructor);
for (int j = 0; redirectedConstructors != null && j < redirectedConstructors.size(); j++) {
PsiMethod redirectedConstructor = redirectedConstructors.get(j);
@@ -371,13 +367,13 @@ public class HighlightControlFlowUtil {
}
if (aClass != null) {
// field may be initialized in class initalizer
// field may be initialized in class initializer
final PsiClassInitializer[] initializers = aClass.getInitializers();
for (PsiClassInitializer initializer : initializers) {
PsiCodeBlock body = initializer.getBody();
if (body == block) break;
// variable referenced in initializer must be initialized in initializer preceding assignment
// varaibel refernced in field initializer or in class initializier
// variable referenced in field initializer or in class initializer
boolean shouldCheckInitializerOrder = block == null || block.getParent() instanceof PsiClassInitializer;
if (shouldCheckInitializerOrder && startOffset < initializer.getTextRange().getStartOffset()) continue;
if (initializer.hasModifierProperty(PsiModifier.STATIC)
@@ -449,6 +445,7 @@ public class HighlightControlFlowUtil {
}
@Nullable
public static HighlightInfo checkFinalVariableMightAlreadyHaveBeenAssignedTo(PsiVariable variable,
PsiReferenceExpression expression,
Map<PsiElement, Collection<ControlFlowUtil.VariableInfo>> finalVarProblems) {
@@ -473,7 +470,7 @@ public class HighlightControlFlowUtil {
final PsiField field = (PsiField)variable;
final PsiClass aClass = field.getContainingClass();
if (aClass == null) return null;
// field can get assigned in other field inititializers
// field can get assigned in other field initializers
final PsiField[] fields = aClass.getFields();
boolean isFieldStatic = field.hasModifierProperty(PsiModifier.STATIC);
for (PsiField psiField : fields) {
@@ -565,7 +562,8 @@ public class HighlightControlFlowUtil {
}
public static HighlightInfo checkFinalVariableInitalizedInLoop(PsiReferenceExpression expression, PsiElement resolved) {
@Nullable
public static HighlightInfo checkFinalVariableInitializedInLoop(PsiReferenceExpression expression, PsiElement resolved) {
if (ControlFlowUtil.isVariableAssignedInLoop(expression, resolved)) {
String description = JavaErrorMessages.message("variable.assigned.in.loop", ((PsiVariable)resolved).getName());
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(
@@ -580,6 +578,7 @@ public class HighlightControlFlowUtil {
}
@Nullable
public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression) {
PsiReferenceExpression reference = null;
if (expression instanceof PsiAssignmentExpression) {
@@ -659,6 +658,7 @@ public class HighlightControlFlowUtil {
}
@Nullable
static HighlightInfo checkVariableMustBeFinal(PsiVariable variable, PsiJavaCodeReferenceElement context) {
if (variable.hasModifierProperty(PsiModifier.FINAL)) return null;
final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context);
@@ -672,23 +672,30 @@ public class HighlightControlFlowUtil {
return null;
}
@Nullable
public static PsiClass getInnerClassVariableReferencedFrom(PsiVariable variable, PsiElement context) {
PsiElement scope;
if (variable instanceof PsiLocalVariable) {
scope = variable.getParent().getParent(); // code block or for statement
PsiElement[] scope;
if (variable instanceof PsiScopedLocalVariable) {
scope = ((PsiScopedLocalVariable)variable).getDeclarationScope();
}
else if (variable instanceof PsiLocalVariable) {
scope = new PsiElement[]{variable.getParent().getParent()}; // code block or for statement
}
else if (variable instanceof PsiParameter) {
scope = ((PsiParameter)variable).getDeclarationScope();
scope = new PsiElement[]{((PsiParameter)variable).getDeclarationScope()};
}
else {
scope = variable.getParent();
scope = new PsiElement[]{variable.getParent()};
}
if (scope.getContainingFile() != context.getContainingFile()) return null;
if (scope.length < 1 || scope[0].getContainingFile() != context.getContainingFile()) return null;
PsiElement parent = context.getParent();
PsiElement prevParent = context;
outer:
while (parent != null) {
if (parent.equals(scope)) break;
for (PsiElement scopeElement : scope) {
if (parent.equals(scopeElement)) break outer;
}
if (parent instanceof PsiClass && !(prevParent instanceof PsiExpressionList && parent instanceof PsiAnonymousClass)) {
return (PsiClass)parent;
}
@@ -699,6 +706,7 @@ public class HighlightControlFlowUtil {
}
@Nullable
public static HighlightInfo checkInitializerCompleteNormally(PsiClassInitializer initializer) {
final PsiCodeBlock body = initializer.getBody();
// unhandled exceptions already reported
@@ -36,6 +36,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
import com.intellij.psi.javadoc.PsiDocComment;
@@ -45,6 +46,7 @@ import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashMap;
@@ -73,8 +75,7 @@ public class HighlightUtil {
@NonNls private static final String SERIAL_PERSISTENT_FIELDS_FIELD_NAME = "serialPersistentFields";
private static final QuickFixFactory QUICK_FIX_FACTORY = QuickFixFactory.getInstance();
private HighlightUtil() {
}
private HighlightUtil() { }
static {
ourClassIncompatibleModifiers = new THashMap<String, Set<String>>(8);
@@ -345,6 +346,7 @@ public class HighlightUtil {
}
@Nullable
static HighlightInfo checkVariableExpected(PsiExpression expression) {
PsiExpression lValue;
if (expression instanceof PsiAssignmentExpression) {
@@ -543,33 +545,39 @@ public class HighlightUtil {
return errorResult;
}
public static String getUnhandledExceptionsDescriptor(Collection<PsiClassType> unhandledExceptions) {
StringBuilder exceptionsText = new StringBuilder();
for (PsiClassType unhandledException : unhandledExceptions) {
if (exceptionsText.length() != 0) exceptionsText.append(", ");
exceptionsText.append(formatType(unhandledException));
}
return JavaErrorMessages.message("unhandled.exceptions", exceptionsText.toString(), unhandledExceptions.size());
public static String getUnhandledExceptionsDescriptor(final Collection<PsiClassType> unhandled) {
return getUnhandledExceptionsDescriptor(unhandled, null);
}
private static String getUnhandledExceptionsDescriptor(final Collection<PsiClassType> unhandled, final String source) {
final String exceptions = StringUtil.join(unhandled, new Function<PsiClassType, String>() {
@Override public String fun(PsiClassType type) { return formatType(type); }
}, ", ");
return source != null ? JavaErrorMessages.message("unhandled.close.exceptions", exceptions, unhandled.size(), source)
: JavaErrorMessages.message("unhandled.exceptions", exceptions, unhandled.size());
}
@Nullable
static HighlightInfo checkVariableAlreadyDefined(PsiVariable variable) {
if (variable instanceof ExternallyDefinedPsiElement) return null;
boolean isIncorrect = false;
PsiIdentifier identifier = variable.getNameIdentifier();
assert identifier != null : variable;
String name = variable.getName();
if (variable instanceof PsiLocalVariable ||
variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiCatchSection ||
variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiForeachStatement) {
PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class);
VariablesNotProcessor proc = new VariablesNotProcessor(variable, false){
PsiElement scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class, PsiResourceList.class);
VariablesNotProcessor proc = new VariablesNotProcessor(variable, false) {
protected boolean check(final PsiVariable var, final ResolveState state) {
return (var instanceof PsiLocalVariable || var instanceof PsiParameter) && super.check(var, state);
}
};
PsiScopesUtil.treeWalkUp(proc, identifier, scope);
if (scope instanceof PsiResourceList && proc.size() == 0) {
scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class);
PsiScopesUtil.treeWalkUp(proc, identifier, scope);
}
if (proc.size() > 0) {
isIncorrect = true;
}
@@ -631,26 +639,47 @@ public class HighlightUtil {
}
public static HighlightInfo checkUnhandledExceptions(PsiElement element, TextRange fixRange) {
List<PsiClassType> unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element);
HighlightInfo errorResult = null;
if (!unhandledExceptions.isEmpty()) {
if (fixRange == null) {
fixRange = element.getTextRange();
}
HighlightInfoType highlightType = getUnhandledExceptionHighlightType(element);
if (highlightType == null) return null;
errorResult = HighlightInfo.createHighlightInfo(highlightType, fixRange, getUnhandledExceptionsDescriptor(unhandledExceptions));
QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToCatchFix());
QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithTryCatchFix(element));
if (unhandledExceptions.size() == 1) {
QuickFixAction.registerQuickFixAction(errorResult, new GeneralizeCatchFix(element, unhandledExceptions.get(0)));
}
}
@Nullable
public static HighlightInfo checkUnhandledExceptions(final PsiElement element, TextRange fixRange) {
final List<PsiClassType> unhandledExceptions = ExceptionUtil.getUnhandledExceptions(element);
if (unhandledExceptions.isEmpty()) return null;
final HighlightInfoType highlightType = getUnhandledExceptionHighlightType(element);
if (highlightType == null) return null;
if (fixRange == null) fixRange = element.getTextRange();
final String description = getUnhandledExceptionsDescriptor(unhandledExceptions);
final HighlightInfo errorResult = HighlightInfo.createHighlightInfo(highlightType, fixRange, description);
registerUnhandledExceptionFixes(element, errorResult, unhandledExceptions);
return errorResult;
}
@Nullable
public static HighlightInfo checkUnhandledCloserExceptions(final PsiResource resource) {
final List<PsiClassType> unhandled = ExceptionUtil.getUnhandledCloserExceptions(resource, null);
if (unhandled.isEmpty()) return null;
final HighlightInfoType highlightType = getUnhandledExceptionHighlightType(resource);
if (highlightType == null) return null;
final String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource");
final HighlightInfo highlight = HighlightInfo.createHighlightInfo(highlightType, resource, description);
registerUnhandledExceptionFixes(resource, highlight, unhandled);
return highlight;
}
private static void registerUnhandledExceptionFixes(final PsiElement element,
final HighlightInfo errorResult,
final List<PsiClassType> unhandled) {
QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToCatchFix());
QuickFixAction.registerQuickFixAction(errorResult, new AddExceptionToThrowsFix(element));
QuickFixAction.registerQuickFixAction(errorResult, new SurroundWithTryCatchFix(element));
if (unhandled.size() == 1) {
QuickFixAction.registerQuickFixAction(errorResult, new GeneralizeCatchFix(element, unhandled.get(0)));
}
}
@Nullable
private static HighlightInfoType getUnhandledExceptionHighlightType(final PsiElement element) {
if (!JspPsiUtil.isInJspFile(element)) {
return HighlightInfoType.UNHANDLED_EXCEPTION;
@@ -697,6 +726,7 @@ public class HighlightUtil {
}
@Nullable
static HighlightInfo checkIllegalModifierCombination(PsiKeyword keyword, PsiModifierList modifierList) {
@Modifier String modifier = keyword.getText();
String incompatible = getIncompatibleModifier(modifier, modifierList);
@@ -864,13 +894,11 @@ public class HighlightUtil {
assert tryBlock != null : statement;
thrownTypes.addAll(ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock));
final PsiParameterList resources = statement.getResourceList();
final PsiResourceList resources = statement.getResourceList();
if (resources != null) {
thrownTypes.addAll(ExceptionUtil.collectUnhandledExceptions(resources, resources));
}
// todo: add exceptions from resource's close() method
final PsiType caughtType = parameter.getType();
if (caughtType instanceof PsiClassType) {
return checkSimpleCatchParameter(parameter, thrownTypes, (PsiClassType)caughtType);
@@ -950,6 +978,7 @@ public class HighlightUtil {
}
@Nullable
public static HighlightInfo checkSwitchSelectorType(PsiSwitchStatement statement) {
PsiExpression expression = statement.getExpression();
HighlightInfo errorResult = null;
@@ -1110,19 +1139,32 @@ public class HighlightUtil {
@Nullable
public static HighlightInfo checkCatchParameterIsThrowable(PsiParameter parameter) {
public static HighlightInfo checkCatchParameterIsThrowable(final PsiParameter parameter) {
if (parameter.getDeclarationScope() instanceof PsiCatchSection) {
PsiType type = parameter.getType();
final PsiType type = parameter.getType();
return checkMustBeThrowable(type, parameter, true);
}
return null;
}
public static void checkArrayInitalizer(final PsiExpression initializer, final HighlightInfoHolder holder) {
if (! (initializer instanceof PsiArrayInitializerExpression)) return;
@Nullable
public static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResource resource) {
final PsiType type = resource.getType();
if (type == null) return null;
final PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory();
final PsiClassType autoCloseable = factory.createTypeByFQClassName("java.lang.AutoCloseable", resource.getResolveScope());
if (TypeConversionUtil.isAssignable(autoCloseable, type)) return null;
return createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange());
}
@Nullable
public static Collection<HighlightInfo> checkArrayInitializer(final PsiExpression initializer) {
if (! (initializer instanceof PsiArrayInitializerExpression)) return null;
final PsiType arrayInitializerType = initializer.getType();
if (! (arrayInitializerType instanceof PsiArrayType)) return;
if (! (arrayInitializerType instanceof PsiArrayType)) return null;
final PsiType componentType = ((PsiArrayType) arrayInitializerType).getComponentType();
final PsiArrayInitializerExpression arrayInitializer = (PsiArrayInitializerExpression) initializer;
@@ -1130,11 +1172,12 @@ public class HighlightUtil {
boolean arrayTypeFixChecked = false;
VariableArrayTypeFix fix = null;
final Collection<HighlightInfo> result = Lists.newArrayList();
final PsiExpression[] initializers = arrayInitializer.getInitializers();
for (PsiExpression expression : initializers) {
final HighlightInfo info = checkArrayInitalizerCompatibleTypes(expression, componentType);
final HighlightInfo info = checkArrayInitializerCompatibleTypes(expression, componentType);
if (info != null) {
holder.add(info);
result.add(info);
if (!arrayTypeFixChecked) {
final PsiType checkResult = sameType(initializers);
@@ -1146,6 +1189,7 @@ public class HighlightUtil {
}
}
}
return result;
}
@Nullable
@@ -1157,6 +1201,7 @@ public class HighlightUtil {
return null;
}
@Nullable
public static PsiType sameType(PsiExpression[] expressions) {
PsiType type = null;
for (PsiExpression expression : expressions) {
@@ -1178,7 +1223,7 @@ public class HighlightUtil {
}
@Nullable
private static HighlightInfo checkArrayInitalizerCompatibleTypes(PsiExpression initializer, final PsiType componentType) {
private static HighlightInfo checkArrayInitializerCompatibleTypes(PsiExpression initializer, final PsiType componentType) {
PsiType initializerType = initializer.getType();
if (initializerType == null) {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, initializer,
@@ -1212,16 +1257,12 @@ public class HighlightUtil {
PsiVariable variable = (PsiVariable)parent;
if (variable.getType() instanceof PsiArrayType) return null;
}
else if (parent instanceof PsiNewExpression) {
else if (parent instanceof PsiNewExpression || parent instanceof PsiArrayInitializerExpression) {
return null;
}
else if (parent instanceof PsiArrayInitializerExpression) {
return null;
}
HighlightInfo info =
HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("expression.expected"));
QuickFixAction.registerQuickFixAction(info, new AddNewArrayExpressionFix(expression));
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("expression.expected"));
QuickFixAction.registerQuickFixAction(info, new AddNewArrayExpressionFix(expression));
return info;
}
@@ -1393,13 +1434,11 @@ public class HighlightUtil {
if (typeOwner instanceof PsiMethod) {
if (((PsiMethod)typeOwner).getReturnTypeElement() == parent) return null;
}
else if (typeOwner instanceof PsiClassObjectAccessExpression &&
TypeConversionUtil.isVoidType(((PsiClassObjectAccessExpression)typeOwner).getOperand().getType())) {
// like in Class c = void.class;
return null;
}
else if (typeOwner != null && PsiUtilBase.hasErrorElementChild(typeOwner)) {
// do not highlight incomplete declarations
else if (// like in Class c = void.class;
typeOwner instanceof PsiClassObjectAccessExpression &&
TypeConversionUtil.isVoidType(((PsiClassObjectAccessExpression)typeOwner).getOperand().getType()) ||
// do not highlight incomplete declarations
typeOwner != null && PsiUtilBase.hasErrorElementChild(typeOwner)) {
return null;
}
else if (typeOwner instanceof JavaCodeFragment) {
@@ -1510,6 +1549,7 @@ public class HighlightUtil {
return checkReferenceToOurInstanceInsideThisOrSuper(expression, referencedClass, resolvedName);
}
@Nullable
private static HighlightInfo checkReferenceToOurInstanceInsideThisOrSuper(final PsiElement expression,
final PsiClass referencedClass,
final String resolvedName) {
@@ -1551,6 +1591,7 @@ public class HighlightUtil {
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description);
}
@Nullable
public static HighlightInfo checkImplicitThisReferenceBeforeSuper(PsiClass aClass) {
if (aClass instanceof PsiAnonymousClass) return null;
PsiClass superClass = aClass.getSuperClass();
@@ -1589,6 +1630,7 @@ public class HighlightUtil {
return element != null;
}
@Nullable
private static String getMethodExpressionName(PsiElement element) {
if (!(element instanceof PsiMethodCallExpression)) return null;
PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)element).getMethodExpression();
@@ -2082,6 +2124,7 @@ public class HighlightUtil {
return aClass == null || isSerializable(aClass);
}
@Nullable
public static HighlightInfo checkClassReferenceAfterQualifier(final PsiReferenceExpression expression, final PsiElement resolved) {
if (!(resolved instanceof PsiClass)) return null;
final PsiExpression qualifier = expression.getQualifierExpression();
@@ -342,7 +342,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkCannotWriteToFinal(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableExpected(expression));
if (!myHolder.hasErrorResults()) HighlightUtil.checkArrayInitalizer(expression, myHolder);
if (!myHolder.hasErrorResults()) myHolder.addAll(HighlightUtil.checkArrayInitializer(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTernaryOperatorConditionIsBoolean(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssertOperatorTypes(expression));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkSynchronizedExpressionType(expression));
@@ -820,7 +820,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightControlFlowUtil.checkFinalVariableMightAlreadyHaveBeenAssignedTo(variable, expression, myFinalVarProblems));
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitalizedInLoop(expression, resolved));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalVariableInitializedInLoop(expression, resolved));
}
}
@@ -897,8 +897,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override public void visitTryStatement(PsiTryStatement statement) {
super.visitTryStatement(statement);
if (!myHolder.hasErrorResults()) {
PsiParameter[] parameters = statement.getCatchBlockParameters();
for (PsiParameter parameter : parameters) {
for (PsiParameter parameter : statement.getCatchBlockParameters()) {
myHolder.addAll(HighlightUtil.checkExceptionThrownInTry(parameter));
myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
myHolder.add(GenericsHighlightUtil.checkCatchParameterIsClass(parameter));
@@ -906,6 +905,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
@Override
public void visitResource(final PsiResource resource) {
myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource));
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource));
}
}
@Override public void visitTypeElement(PsiTypeElement type) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
@@ -24,7 +24,6 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.JavaPsiFacadeEx;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
@@ -61,23 +60,18 @@ public class CreateMethodQuickFix implements LocalQuickFix {
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
try {
if (!CodeInsightUtilBase.preparePsiElementForWrite(myTargetClass.getContainingFile())) return;
if (!CodeInsightUtilBase.preparePsiElementForWrite(myTargetClass.getContainingFile())) return;
PsiMethod method = createMethod(project);
List<Pair<PsiExpression, PsiType>> arguments =
ContainerUtil.map2List(method.getParameterList().getParameters(), new Function<PsiParameter, Pair<PsiExpression, PsiType>>() {
public Pair<PsiExpression, PsiType> fun(PsiParameter psiParameter) {
return Pair.create(null, psiParameter.getType());
}
});
PsiMethod method = createMethod(project);
List<Pair<PsiExpression, PsiType>> arguments =
ContainerUtil.map2List(method.getParameterList().getParameters(), new Function<PsiParameter, Pair<PsiExpression, PsiType>>() {
public Pair<PsiExpression, PsiType> fun(PsiParameter psiParameter) {
return Pair.create(null, psiParameter.getType());
}
});
method = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences((PsiMethod)myTargetClass.add(method));
CreateMethodFromUsageFix.doCreate(myTargetClass, method, arguments, PsiSubstitutor.EMPTY, ExpectedTypeInfo.EMPTY_ARRAY, method);
}
catch (IncorrectOperationException e) {
throw new RuntimeException(e);
}
method = (PsiMethod)JavaCodeStyleManager.getInstance(project).shortenClassReferences((PsiMethod)myTargetClass.add(method));
CreateMethodFromUsageFix.doCreate(myTargetClass, method, arguments, PsiSubstitutor.EMPTY, ExpectedTypeInfo.EMPTY_ARRAY, method);
}
private PsiMethod createMethod(Project project) {
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.compiler.ModuleCompilerUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.Result;
@@ -42,8 +43,6 @@ import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.compiler.ModuleCompilerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -72,12 +71,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
try {
invoke(project, null, descriptor.getPsiElement().getContainingFile());
}
catch (IncorrectOperationException e) {
throw new RuntimeException(e);
}
invoke(project, null, descriptor.getPsiElement().getContainingFile());
}
@Nullable
@@ -27,21 +27,19 @@ import com.intellij.psi.scope.processor.VariablesNotProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Created by IntelliJ IDEA.
* User: cdr
* @author cdr
* Date: Nov 20, 2002
* Time: 3:01:25 PM
* To change this template use Options | File Templates.
*/
public class ReuseVariableDeclarationFix implements IntentionAction {
private final PsiVariable variable;
private final PsiIdentifier identifier;
private final PsiVariable myVariable;
private final PsiIdentifier myIdentifier;
public ReuseVariableDeclarationFix(PsiVariable variable, PsiIdentifier identifier) {
this.variable = variable;
this.identifier = identifier;
public ReuseVariableDeclarationFix(final PsiVariable variable, final PsiIdentifier identifier) {
this.myVariable = variable;
this.myIdentifier = identifier;
}
@NotNull
@@ -51,55 +49,63 @@ public class ReuseVariableDeclarationFix implements IntentionAction {
@NotNull
public String getText() {
return QuickFixBundle.message("reuse.variable.declaration.text", variable.getName());
return QuickFixBundle.message("reuse.variable.declaration.text", myVariable.getName());
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
PsiVariable previousVariable = findPreviousVariable();
return
variable != null
&& variable.isValid()
&& variable instanceof PsiLocalVariable
&& previousVariable != null
&& Comparing.equal(previousVariable.getType(), variable.getType())
&& identifier != null
&& identifier.isValid()
&& variable.getManager().isInProject(variable);
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
final PsiVariable previousVariable = findPreviousVariable();
return myVariable != null &&
myVariable.isValid() &&
myVariable instanceof PsiLocalVariable &&
!(myVariable.getParent() instanceof PsiResource && myVariable.getInitializer() == null) &&
previousVariable != null &&
Comparing.equal(previousVariable.getType(), myVariable.getType()) &&
myIdentifier != null &&
myIdentifier.isValid() &&
myVariable.getManager().isInProject(myVariable);
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PsiVariable refVariable = findPreviousVariable();
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
final PsiVariable refVariable = findPreviousVariable();
if (refVariable == null) return;
if (!CodeInsightUtil.preparePsiElementsForWrite(variable, refVariable)) return;
PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false);
if (variable.getInitializer() == null) {
variable.delete();
if (!CodeInsightUtil.preparePsiElementsForWrite(myVariable, refVariable)) return;
final PsiExpression initializer = myVariable.getInitializer();
if (initializer == null) {
myVariable.delete();
return;
}
PsiDeclarationStatement declaration = (PsiDeclarationStatement) variable.getParent();
PsiElementFactory factory = JavaPsiFacade.getInstance(variable.getProject()).getElementFactory();
PsiStatement statement = factory.createStatementFromText(variable.getName() + " = " + variable.getInitializer().getText()+";", variable);
declaration.replace(statement);
PsiUtil.setModifierProperty(refVariable, PsiModifier.FINAL, false);
final PsiElementFactory factory = JavaPsiFacade.getInstance(myVariable.getProject()).getElementFactory();
final PsiElement replacement;
final PsiElement parent = myVariable.getParent();
if (parent instanceof PsiResource) {
replacement = factory.createResourceFromText(myVariable.getName() + " = " + initializer.getText(), null);
}
else {
replacement = factory.createStatementFromText(myVariable.getName() + " = " + initializer.getText() + ";", null);
}
parent.replace(replacement);
}
@Nullable
private PsiVariable findPreviousVariable() {
PsiElement scope = variable.getParent();
PsiElement scope = myVariable.getParent();
while (scope != null) {
if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break;
scope = scope.getParent();
}
if (scope == null) return null;
VariablesNotProcessor proc = new VariablesNotProcessor(variable, false);
PsiScopesUtil.treeWalkUp(proc, identifier, scope);
if(proc.size() > 0)
return proc.getResult(0);
return null;
final VariablesNotProcessor proc = new VariablesNotProcessor(myVariable, false);
PsiScopesUtil.treeWalkUp(proc, myIdentifier, scope);
return proc.size() > 0 ? proc.getResult(0) : null;
}
public boolean startInWriteAction() {
return true;
}
}
@@ -117,6 +117,11 @@ public class JavadocTypedHandler extends TypedHandlerDelegate {
return null;
}
return text.subSequence(i + 1, endOffset).toString();
// There is a possible case that opening tag has attributes, e.g. <a href='bla-bla-bla'>[offset]. We want to extract
// only tag name then.
case ' ':
case '\t': endOffset = i;
}
}
return null;
@@ -221,6 +221,11 @@ public class JavaDocInfoGenerator {
else if (myElement instanceof PsiVariable) {
generateVariableJavaDoc(buffer, (PsiVariable)myElement);
}
else if (myElement instanceof PsiDirectory) {
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)myElement);
if (aPackage == null) return null;
generatePackageJavaDoc(buffer, aPackage);
}
else if (myElement instanceof PsiPackage) {
generatePackageJavaDoc(buffer, (PsiPackage) myElement);
} else {
@@ -2,10 +2,11 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.CodeCompletionFeatures;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
/**
@@ -34,17 +35,27 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
public void handleInsert(InsertionContext context) {
super.handleInsert(context);
if (context.getCompletionChar() == '=') {
final char completionChar = context.getCompletionChar();
if (completionChar == '=') {
context.setAddCompletionChar(false);
TailType.EQ.processTail(context.getEditor(), context.getTailOffset());
}
else if (context.getCompletionChar() == ',' && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
else if (completionChar == ',' && getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
context.setAddCompletionChar(false);
TailType.COMMA.processTail(context.getEditor(), context.getTailOffset());
}
else if (context.getCompletionChar() == '.') {
else if (completionChar == '.') {
AutoPopupController.getInstance(context.getProject()).autoPopupMemberLookup(context.getEditor(), null);
}
else if (completionChar == '!' && PsiType.BOOLEAN.isAssignableFrom(getObject().getType())) {
context.setAddCompletionChar(false);
final PsiReferenceExpression ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
if (ref != null) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EXCLAMATION_FINISH);
context.getDocument().insertString(ref.getTextRange().getStartOffset(), "!");
}
}
}
}
@@ -15,12 +15,14 @@
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -65,15 +67,39 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT
@Override
public void visitNewExpression(PsiNewExpression expression) {
if (PsiUtil.getLanguageLevel(expression).isAtLeast(LanguageLevel.JDK_1_7)) {
final PsiJavaCodeReferenceElement classReference = expression.getClassReference();
final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
if (classReference != null) {
final PsiReferenceParameterList parameterList = classReference.getParameterList();
if (parameterList != null) {
final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements();
if (typeElements.length > 0) {
if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) return;
holder.registerProblem(parameterList, "Redundant type argument #ref #loc",
ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix());
final PsiDiamondType.DiamondInferenceResult inferenceResult = PsiDiamondType.resolveInferredTypes(expression);
if (inferenceResult.getErrorMessage() == null) {
final PsiType[] types = inferenceResult.getTypes();
final PsiType[] typeArguments = parameterList.getTypeArguments();
if (types.length == typeArguments.length) {
for (int i = 0, typeArgumentsLength = typeArguments.length; i < typeArgumentsLength; i++) {
PsiType typeArgument = typeArguments[i];
if (types[i] instanceof PsiWildcardType) {
final PsiWildcardType wildcardType = (PsiWildcardType)types[i];
final PsiType bound = wildcardType.getBound();
if (bound != null) {
if (wildcardType.isExtends()) {
if (bound.isAssignableFrom(typeArgument)) continue;
} else {
if (typeArgument.isAssignableFrom(bound)) continue;
}
}
}
if (!typeArgument.equals(types[i])) {
return;
}
}
}
holder.registerProblem(parameterList, "Redundant type argument #ref #loc",
ProblemHighlightType.LIKE_UNUSED_SYMBOL, new ReplaceWithDiamondFix());
}
}
}
}
@@ -99,6 +125,7 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaLocalInspectionT
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement psiElement = descriptor.getPsiElement();
if (psiElement instanceof PsiReferenceParameterList) {
if (!CodeInsightUtilBase.prepareFileForWrite(psiElement.getContainingFile())) return;
final PsiTypeElement[] parameterElements = ((PsiReferenceParameterList)psiElement).getTypeParameterElements();
psiElement.deleteChildRange(parameterElements[0], parameterElements[parameterElements.length - 1]);
}
@@ -97,7 +97,7 @@ public class DefUseInspection extends BaseLocalInspectionTool {
PsiElement context = info.getContext();
PsiVariable psiVariable = info.getVariable();
if (context instanceof PsiDeclarationStatement) {
if (context instanceof PsiDeclarationStatement || context instanceof PsiResource) {
if (!info.isRead()) {
if (!isOnTheFly) {
holder.registerProblem(psiVariable.getNameIdentifier(),
@@ -220,7 +220,10 @@ public class JavaLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett
" throws Exception { \n" +
" foo.foo().bar(\"arg1\", \n" +
" \"arg2\"); \n" +
" new Object() {};" +
" } \n" +
" class TestInnerClass {}\n" +
" interface TestInnerInterface {}\n" +
"}\n" +
"\n" +
"enum Breed {\n" +
@@ -23,6 +23,7 @@ import com.intellij.openapi.roots.ui.util.ModifiableCellAppearance;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
@@ -51,7 +52,8 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer {
ModifiableCellAppearance result;
if (psiElement instanceof PsiElement && !((PsiElement)psiElement).isValid()) {
result = CompositeAppearance.single(name);
} else {
}
else {
PsiClass psiClass = getContainingClass(psiElement);
if (isInheritedMember(node, psiClass) && psiClass != null) {
CompositeAppearance.DequeEnd ending = new CompositeAppearance().getEnding();
@@ -84,13 +86,13 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer {
}
}
public static String getNameOf(PsiElement psiElement) {
private static String getNameOf(PsiElement psiElement) {
if (psiElement instanceof PsiMethod)
return PsiFormatUtil.formatMethod((PsiMethod)psiElement,
PsiSubstitutor.EMPTY,
PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE | PsiFormatUtil.TYPE_AFTER |
PsiFormatUtil.SHOW_PARAMETERS,
PsiFormatUtil.SHOW_TYPE
PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_TYPE | PsiFormatUtilBase.TYPE_AFTER |
PsiFormatUtilBase.SHOW_PARAMETERS,
PsiFormatUtilBase.SHOW_TYPE
);
return psiElement.toString();
}
@@ -109,23 +111,17 @@ public class StructureNodeRenderer extends ColoredTreeCellRenderer {
return new SimpleTextAttributes(nameAttributes.getStyle() | SimpleTextAttributes.STYLE_STRIKEOUT, nameAttributes.getFgColor());
}
public static boolean isDeprecated(Object psiElement) {
if (psiElement instanceof PsiDocCommentOwner)
return ((PsiDocCommentOwner) psiElement).isDeprecated();
return false;
private static boolean isDeprecated(Object psiElement) {
return psiElement instanceof PsiDocCommentOwner && ((PsiDocCommentOwner)psiElement).isDeprecated();
}
public static PsiClass getContainingClass(Object element) {
private static PsiClass getContainingClass(Object element) {
if (element instanceof PsiMember)
return ((PsiMember) element).getContainingClass();
if (element instanceof PsiClass) {
PsiElement parent = ((PsiClass) element).getParent();
return (PsiClass) (parent instanceof PsiClass ? parent : null);
}
return null;
}
public static PsiClass getTreeParentClass(Object value) {
private static PsiClass getTreeParentClass(Object value) {
if (!(value instanceof TreeNode))
return null;
for (TreeNode treeNode = ((TreeNode) value).getParent(); treeNode != null; treeNode = treeNode.getParent()) {
@@ -35,10 +35,8 @@ public class JavaClassTreeElement extends JavaClassTreeElementBase<PsiClass> {
}
private Collection<StructureViewTreeElement> getClassChildren() {
ArrayList<StructureViewTreeElement> array = new ArrayList<StructureViewTreeElement>();
final PsiClass aClass = getElement();
if (aClass == null) return array;
if (aClass == null) return Collections.emptyList();
List<PsiElement> children = Arrays.asList(aClass.getChildren());
Collection<PsiElement> ownChildren = new THashSet<PsiElement>();
@@ -47,6 +45,7 @@ public class JavaClassTreeElement extends JavaClassTreeElementBase<PsiClass> {
ContainerUtil.addAll(ownChildren, aClass.getInnerClasses());
ContainerUtil.addAll(ownChildren, aClass.getInitializers());
Collection<PsiElement> inherited = new LinkedHashSet<PsiElement>(children);
List<StructureViewTreeElement> array = new ArrayList<StructureViewTreeElement>(inherited.size());
aClass.processDeclarations(new AddAllMembersProcessor(inherited, aClass), ResolveState.initial(), null, aClass);
@@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.Collection;
public class JavaFileTreeElement extends PsiTreeElementBase<PsiJavaFile> implements ItemPresentation {
public JavaFileTreeElement(PsiJavaFile file) {
super(file);
}
@@ -31,11 +31,12 @@ import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.PsiBuilderUtil.nextTokenType;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
import static com.intellij.lang.java.parser.JavaParserUtil.exprType;
public class DeclarationParser {
public enum Context {
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE, RESOURCE_LIST
}
private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD);
@@ -222,7 +223,7 @@ public class DeclarationParser {
if (tokenType == null) return null;
if (tokenType == JavaTokenType.LBRACE) {
if (context == Context.FILE || context == Context.CODE_BLOCK) return null;
if (context == Context.FILE || context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) return null;
}
else if (tokenType == JavaTokenType.IDENTIFIER || ElementType.PRIMITIVE_TYPE_BIT_SET.contains(tokenType)) {
if (context == Context.FILE) return null;
@@ -234,7 +235,7 @@ public class DeclarationParser {
else if (!ElementType.MODIFIER_BIT_SET.contains(tokenType) &&
!ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType) &&
tokenType != JavaTokenType.AT &&
(context == Context.CODE_BLOCK || tokenType != JavaTokenType.LT)) {
(context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST || tokenType != JavaTokenType.LT)) {
return null;
}
@@ -278,7 +279,7 @@ public class DeclarationParser {
final PsiBuilder.Marker idPos = builder.mark();
type = parseTypeNotNull(builder);
if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor
if (context == Context.CODE_BLOCK) {
if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) {
declaration.rollbackTo();
return null;
}
@@ -301,6 +302,10 @@ public class DeclarationParser {
declaration.drop();
return modList;
}
else if (context == Context.RESOURCE_LIST) {
declaration.rollbackTo();
return null;
}
final PsiBuilder.Marker codeBlock = StatementParser.parseCodeBlock(builder);
assert codeBlock != null : builder.getOriginalText();
@@ -326,7 +331,7 @@ public class DeclarationParser {
}
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
if (context == Context.CODE_BLOCK && modListInfo.second) {
if ((context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) && modListInfo.second) {
declaration.rollbackTo();
return null;
}
@@ -447,33 +452,33 @@ public class DeclarationParser {
@NotNull
public static PsiBuilder.Marker parseParameterList(final PsiBuilder builder) {
return parseParameterList(builder, false);
return parseElementList(builder, false);
}
@NotNull
public static PsiBuilder.Marker parseResourceList(final PsiBuilder builder) {
return parseParameterList(builder, true);
return parseElementList(builder, true);
}
@NotNull
private static PsiBuilder.Marker parseParameterList(final PsiBuilder builder, final boolean resources) {
private static PsiBuilder.Marker parseElementList(final PsiBuilder builder, final boolean resources) {
assert builder.getTokenType() == JavaTokenType.LPARENTH : builder.getTokenType();
final PsiBuilder.Marker paramList = builder.mark();
final PsiBuilder.Marker elementList = builder.mark();
builder.advanceLexer();
final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA;
final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma");
final String noParameterMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter");
final String noElementMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter");
PsiBuilder.Marker invalidElements = null;
String errorMessage = null;
boolean delimiterExpected = false;
int paramCount = 0;
int elementCount = 0;
while (true) {
final IElementType tokenType = builder.getTokenType();
if (tokenType == null || tokenType == JavaTokenType.RPARENTH || tokenType == JavaTokenType.LBRACE) {
boolean noLastParam = !delimiterExpected && paramCount > 0;
if (noLastParam) {
boolean noLastElement = !delimiterExpected && elementCount > 0;
if (noLastElement) {
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
}
if (tokenType == JavaTokenType.RPARENTH) {
@@ -481,13 +486,13 @@ public class DeclarationParser {
invalidElements.error(errorMessage);
invalidElements = null;
}
else if (resources && paramCount == 0) {
else if (resources && elementCount == 0) {
error(builder, JavaErrorMessages.message("expected.resource"));
}
builder.advanceLexer();
}
else {
if (!noLastParam) {
if (!noLastElement) {
if (invalidElements != null) {
invalidElements.error(errorMessage);
}
@@ -510,27 +515,27 @@ public class DeclarationParser {
}
}
else {
final PsiBuilder.Marker param = parseParameter(builder, true, false, resources);
if (param != null) {
final PsiBuilder.Marker listElement = resources ? parseResource(builder) : parseParameter(builder, true, false);
if (listElement != null) {
delimiterExpected = true;
if (invalidElements != null) {
invalidElements.errorBefore(errorMessage, param);
invalidElements.errorBefore(errorMessage, listElement);
invalidElements = null;
}
paramCount++;
elementCount++;
continue;
}
}
if (invalidElements == null) {
if (builder.getTokenType() == delimiter) {
error(builder, noParameterMsg);
error(builder, noElementMsg);
builder.advanceLexer();
continue;
}
else {
invalidElements = builder.mark();
errorMessage = delimiterExpected ? noDelimiterMsg : noParameterMsg;
errorMessage = delimiterExpected ? noDelimiterMsg : noElementMsg;
}
}
@@ -545,19 +550,19 @@ public class DeclarationParser {
invalidElements.error(errorMessage);
}
done(paramList, JavaElementType.PARAMETER_LIST);
return paramList;
done(elementList, resources ? JavaElementType.RESOURCE_LIST : JavaElementType.PARAMETER_LIST);
return elementList;
}
@Nullable
public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunction, final boolean value) {
public static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis, final boolean disjunctiveType) {
final PsiBuilder.Marker param = builder.mark();
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
int flags = ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD;
if (ellipsis) flags |= ReferenceParser.ELLIPSIS;
if (disjunction) flags |= ReferenceParser.DISJUNCTIONS;
if (disjunctiveType) flags |= ReferenceParser.DISJUNCTIONS;
final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseTypeInfo(builder, flags);
if (typeInfo == null) {
@@ -572,23 +577,34 @@ public class DeclarationParser {
}
if (expect(builder, JavaTokenType.IDENTIFIER)) {
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg || value, JavaErrorMessages.message("expected.rparen"));
if (value) {
if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) {
if (ExpressionParser.parse(builder) == null) {
error(builder, JavaErrorMessages.message("expected.expression"));
}
}
}
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
done(param, JavaElementType.PARAMETER);
return param;
}
else {
error(builder, JavaErrorMessages.message("expected.identifier"));
param.drop();
return modListInfo.first;
}
}
done(param, JavaElementType.PARAMETER);
return param;
@Nullable
public static PsiBuilder.Marker parseResource(final PsiBuilder builder) {
PsiBuilder.Marker element = parse(builder, Context.RESOURCE_LIST);
if (exprType(element) == JavaElementType.MODIFIER_LIST) {
return element;
}
else if (element == null) {
element = ExpressionParser.parse(builder);
}
if (element != null) {
final PsiBuilder.Marker resource = element.precede();
done(resource, JavaElementType.RESOURCE);
return resource;
}
return null;
}
@Nullable
@@ -598,7 +614,7 @@ public class DeclarationParser {
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) {
varType = JavaElementType.FIELD;
}
else if (context == Context.CODE_BLOCK) {
else if (context == Context.CODE_BLOCK || context == Context.RESOURCE_LIST) {
varType = JavaElementType.LOCAL_VARIABLE;
}
else {
@@ -629,6 +645,11 @@ public class DeclarationParser {
unclosed = true;
break;
}
if (context == Context.RESOURCE_LIST) break;
}
else if (context == Context.RESOURCE_LIST) {
error(builder, JavaErrorMessages.message("expected.eq"));
break;
}
if (builder.getTokenType() != JavaTokenType.COMMA) break;
@@ -647,26 +668,28 @@ public class DeclarationParser {
builder.advanceLexer();
}
if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) {
builder.advanceLexer();
}
else {
// special treatment (see DeclarationParserTest.testMultiLineUnclosed())
if (!builder.eof() && shouldRollback) {
final CharSequence text = builder.getOriginalText();
final int spaceEnd = builder.getCurrentOffset();
final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES);
final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS);
if (declarationStart < lineStart && lineStart < spaceStart) {
final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES);
declaration.rollbackTo();
return parse(stoppingBuilder(builder, newBufferEnd), context);
}
if (context != Context.RESOURCE_LIST) {
if (builder.getTokenType() == JavaTokenType.SEMICOLON && eatSemicolon) {
builder.advanceLexer();
}
else {
// special treatment (see DeclarationParserTest.testMultiLineUnclosed())
if (!builder.eof() && shouldRollback) {
final CharSequence text = builder.getOriginalText();
final int spaceEnd = builder.getCurrentOffset();
final int spaceStart = CharArrayUtil.shiftBackward(text, spaceEnd-1, WHITESPACES);
final int lineStart = CharArrayUtil.shiftBackwardUntil(text, spaceEnd, LINE_ENDS);
if (!unclosed) {
error(builder, JavaErrorMessages.message("expected.semicolon"));
if (declarationStart < lineStart && lineStart < spaceStart) {
final int newBufferEnd = CharArrayUtil.shiftForward(text, lineStart, WHITESPACES);
declaration.rollbackTo();
return parse(stoppingBuilder(builder, newBufferEnd), context);
}
}
if (!unclosed) {
error(builder, JavaErrorMessages.message("expected.semicolon"));
}
}
}
@@ -375,7 +375,7 @@ public class StatementParser {
}
final PsiBuilder.Marker afterParenth = builder.mark();
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false, false);
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, false);
if (param == null || JavaParserUtil.exprType(param) != JavaElementType.PARAMETER || builder.getTokenType() != JavaTokenType.COLON) {
afterParenth.rollbackTo();
return parseForLoopFromInitialization(builder, statement);
@@ -657,7 +657,7 @@ public class StatementParser {
return false;
}
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder), false);
final PsiBuilder.Marker param = DeclarationParser.parseParameter(builder, false, areMultiCatchSupported(builder));
if (param == null) {
error(builder, JavaErrorMessages.message("expected.parameter"));
}
@@ -68,7 +68,7 @@ public class PomJavaAspectImpl extends PomJavaAspect implements ProjectComponent
if(changeSet == null) return;
final PsiFile containingFile = changeSet.getRootElement().getPsi().getContainingFile();
if(!(containingFile.getLanguage() instanceof JavaLanguage)) return;
final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel, containingFile);
final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel);
set.addChange(new JavaTreeChanged(containingFile));
event.registerChangeSet(this, set);
}
@@ -268,7 +268,6 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
}
}
// generate jump to the top finally block
if (!myFinallyBlocks.isEmpty()) {
final PsiElement finallyBlock = myFinallyBlocks.peek();
@@ -278,13 +277,10 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
addElementOffsetLater(finallyBlock, true);
}
}
}
private void generateCheckedExceptionJumps(PsiElement element) {
//generate jumps to all handled exception handlers
//if (myCatchBlocks.size() != 0) {
//}
Collection<PsiClassType> unhandledExceptions = ExceptionUtil.collectUnhandledExceptions(element, element.getParent());
for (PsiClassType unhandledException : unhandledExceptions) {
ProgressManager.checkCanceled();
@@ -478,7 +474,8 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
finishElement(statement);
}
@Override public void visitDeclarationStatement(PsiDeclarationStatement statement) {
@Override
public void visitDeclarationStatement(PsiDeclarationStatement statement) {
startElement(statement);
int pc = myCurrentFlow.getSize();
PsiElement[] elements = statement.getDeclaredElements();
@@ -488,28 +485,7 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
element.accept(this);
}
else if (element instanceof PsiVariable) {
PsiExpression initializer = ((PsiVariable)element).getInitializer();
if (initializer != null) {
myStartStatementStack.pushStatement(initializer, false);
myEndStatementStack.pushStatement(initializer, false);
initializer.accept(this);
myStartStatementStack.popStatement();
myEndStatementStack.popStatement();
}
if (element instanceof PsiLocalVariable && initializer != null
|| element instanceof PsiField) {
if (element instanceof PsiLocalVariable && !myPolicy.isLocalVariableAccepted((PsiLocalVariable)element)) continue;
if (myAssignmentTargetsAreElements) {
startElement(element);
}
generateWriteInstruction((PsiVariable)element);
if (myAssignmentTargetsAreElements) {
finishElement(element);
}
}
processVariable((PsiVariable)element);
}
}
if (pc == myCurrentFlow.getSize()) {
@@ -519,6 +495,31 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
finishElement(statement);
}
private void processVariable(final PsiVariable element) {
final PsiExpression initializer = element.getInitializer();
if (initializer != null) {
myStartStatementStack.pushStatement(initializer, false);
myEndStatementStack.pushStatement(initializer, false);
initializer.accept(this);
myStartStatementStack.popStatement();
myEndStatementStack.popStatement();
}
if (element instanceof PsiLocalVariable && initializer != null ||
element instanceof PsiField) {
if (element instanceof PsiLocalVariable && !myPolicy.isLocalVariableAccepted((PsiLocalVariable)element)) return;
if (myAssignmentTargetsAreElements) {
startElement(element);
}
generateWriteInstruction(element);
if (myAssignmentTargetsAreElements) {
finishElement(element);
}
}
}
@Override public void visitDoWhileStatement(PsiDoWhileStatement statement) {
startElement(statement);
myStartStatementStack.pushStatement(statement.getBody() == null ? statement : statement.getBody(), true);
@@ -1034,6 +1035,11 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
myFinallyBlocks.push(finallyBlock);
}
PsiResourceList resourceList = statement.getResourceList();
if (resourceList != null) {
generateCheckedExceptionJumps(resourceList);
resourceList.accept(this);
}
PsiCodeBlock tryBlock = statement.getTryBlock();
if (tryBlock != null) {
// javac works as if all checked exceptions can occur at the top of the block
@@ -1156,8 +1162,36 @@ class ControlFlowAnalyzer extends JavaJspElementVisitor {
finishElement(statement);
}
@Override
public void visitResourceList(final PsiResourceList resourceList) {
startElement(resourceList);
@Override public void visitWhileStatement(PsiWhileStatement statement) {
final List<PsiResource> resources = resourceList.getResources();
for (PsiResource resource : resources) {
ProgressManager.checkCanceled();
resource.accept(this);
}
finishElement(resourceList);
}
@Override
public void visitResource(final PsiResource resource) {
startElement(resource);
final PsiElement resourceElement = resource.getResourceElement();
if (resourceElement instanceof PsiLocalVariable) {
processVariable((PsiLocalVariable)resourceElement);
}
else if (resourceElement instanceof PsiExpression) {
resourceElement.accept(this);
}
finishElement(resource);
}
@Override
public void visitWhileStatement(PsiWhileStatement statement) {
startElement(statement);
if (statement.getBody() == null) {
myStartStatementStack.pushStatement(statement, false);
@@ -13,15 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: max
* Date: Mar 22, 2002
* Time: 7:25:02 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.psi.controlFlow;
import com.intellij.openapi.diagnostic.Logger;
@@ -34,16 +25,20 @@ import com.intellij.util.containers.IntArrayList;
import com.intellij.util.containers.Queue;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* @author max
* Date: Mar 22, 2002
*/
public class DefUseUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defUse.DefUseUtil");
private DefUseUtil() {
}
private DefUseUtil() { }
public static class Info {
private final PsiVariable myVariable;
@@ -132,6 +127,7 @@ public class DefUseUtil {
}
}
@Nullable
public static List<Info> getUnusedDefs(PsiCodeBlock body, Set<PsiVariable> outUsedVariables) {
if (body == null) {
return null;
@@ -232,12 +228,13 @@ public class DefUseUtil {
if (instruction instanceof WriteVariableInstruction) {
WriteVariableInstruction writeInstruction = (WriteVariableInstruction)instruction;
if (!defsArmed[i]) {
PsiElement context = flow.getElement(i);
context = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class, PsiAssignmentExpression.class,
PsiPostfixExpression.class, PsiPrefixExpression.class);
PsiElement context = PsiTreeUtil.getNonStrictParentOfType(flow.getElement(i),
PsiStatement.class, PsiAssignmentExpression.class,
PsiPostfixExpression.class, PsiPrefixExpression.class,
PsiResource.class);
PsiVariable psiVariable = writeInstruction.variable;
if (context != null && !(context instanceof PsiTryStatement)) {
if (context instanceof PsiDeclarationStatement && psiVariable.getInitializer() == null) {
if (isDeclaration(context) && psiVariable.getInitializer() == null) {
if (!assignedVariables.contains(psiVariable)) {
unusedDefs.add(new Info(psiVariable, context, false));
}
@@ -251,7 +248,11 @@ public class DefUseUtil {
}
return unusedDefs;
}
private static boolean isDeclaration(final PsiElement context) {
return context instanceof PsiDeclarationStatement ||
context instanceof PsiResource && ((PsiResource)context).getResourceElement() instanceof PsiLocalVariable;
}
@NotNull
@@ -476,5 +477,4 @@ public class DefUseUtil {
return true;
}
};
}
@@ -39,7 +39,12 @@ public class ExcludeSillyAssignment implements ElementFilter {
final PsiExpression left = ((PsiAssignmentExpression)each).getLExpression();
if (left instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)left;
if (referenceExpression.isQualified()) return true;
final PsiElement qualifier = referenceExpression.getQualifier();
if (qualifier != null) {
if (!(qualifier instanceof PsiThisExpression) || ((PsiThisExpression)qualifier).getQualifier() != null) {
return true;
}
}
return !referenceExpression.isReferenceTo((PsiElement)element);
}
@@ -16,30 +16,26 @@
package com.intellij.psi.filters.getters;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.completion.JavaSmartCompletionParameters;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionParameters> {
public class ClassLiteralGetter {
private static final Logger LOG = Logger.getInstance("com.intellij.psi.filters.getters.ClassLiteralGetter");
@Override
protected void addCompletions(@NotNull final JavaSmartCompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
public static void addCompletions(@NotNull final JavaSmartCompletionParameters parameters,
@NotNull Consumer<LookupElement> result, final PrefixMatcher matcher) {
final PrefixMatcher matcher = result.getPrefixMatcher();
final Condition<String> shortNameCondition = new Condition<String>() {
public boolean value(String s) {
return matcher.prefixMatches(s);
@@ -61,7 +57,7 @@ public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionPa
PsiFile file = parameters.getPosition().getContainingFile();
addClassLiteralLookupElement(classParameter, result, file);
if (addInheritors) {
addInheritorClassLiterals(file, shortNameCondition, classParameter, result);
addInheritorClassLiterals(file, shortNameCondition, classParameter, result, matcher);
}
}
@@ -69,9 +65,9 @@ public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionPa
private static void addInheritorClassLiterals(PsiFile context,
Condition<String> shortNameCondition,
final PsiType classParameter,
CompletionResultSet result) {
Consumer<LookupElement> result, PrefixMatcher matcher) {
final String canonicalText = classParameter.getCanonicalText();
if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText) && StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) {
if (CommonClassNames.JAVA_LANG_OBJECT.equals(canonicalText) && StringUtil.isEmpty(matcher.getPrefix())) {
return;
}
@@ -80,13 +76,13 @@ public class ClassLiteralGetter extends CompletionProvider<JavaSmartCompletionPa
}
}
private static void addClassLiteralLookupElement(@Nullable final PsiType type, final CompletionResultSet resultSet, final PsiFile context) {
private static void addClassLiteralLookupElement(@Nullable final PsiType type, final Consumer<LookupElement> resultSet, final PsiFile context) {
if (type instanceof PsiClassType &&
PsiUtil.resolveClassInType(type) != null &&
!((PsiClassType)type).hasParameters() &&
!(((PsiClassType)type).resolve() instanceof PsiTypeParameter)) {
try {
resultSet.addElement(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new ClassLiteralLookupElement((PsiClassType)type, context)));
resultSet.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(new ClassLiteralLookupElement((PsiClassType)type, context)));
}
catch (IncorrectOperationException e) {
LOG.error(e);
@@ -15,10 +15,9 @@
*/
package com.intellij.psi.filters.getters;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.completion.JavaMethodCallElement;
import com.intellij.codeInsight.completion.SmartCompletionDecorator;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.psi.*;
import com.intellij.psi.filters.TrueFilter;
@@ -27,6 +26,7 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
/**
@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable;
*/
public class MembersGetter {
public static void addMembers(PsiElement position, PsiType expectedType, CompletionResultSet results) {
public static void addMembers(PsiElement position, PsiType expectedType, Consumer<LookupElement> results) {
final PsiClass psiClass = PsiUtil.resolveClassInType(expectedType);
processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType);
@@ -47,7 +47,7 @@ public class MembersGetter {
}
}
private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, CompletionResultSet results) {
private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, Consumer<LookupElement> results) {
PsiElement parent = position.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
return;
@@ -99,7 +99,7 @@ public class MembersGetter {
return null;
}
private static void processMembers(final PsiElement context, final CompletionResultSet results, @Nullable final PsiClass where,
private static void processMembers(final PsiElement context, final Consumer<LookupElement> results, @Nullable final PsiClass where,
final boolean acceptMethods, PsiType expectedType) {
if (where == null) return;
@@ -132,7 +132,7 @@ public class MembersGetter {
}
final PsiType itemType = ((TypedLookupItem)item).getType();
if (itemType != null && expectedType.isAssignableFrom(itemType)) {
results.addElement(item);
results.consume(item);
}
}
}
@@ -213,6 +213,10 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
if (aClass.isEnum()) {
createParenSpace(true, false);
}
else if (myRole2 == ChildRole.RBRACE && mySettings.KEEP_SIMPLE_CLASSES_IN_ONE_LINE) {
int spaces = mySettings.SPACE_WITHIN_BRACES ? 1 : 0;
myResult = Spacing.createSpacing(spaces, spaces, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
}
else if (aClass instanceof PsiAnonymousClass) {
if (myRole2 == ChildRole.CLASS_INITIALIZER && isTheOnlyClassMember(myChild2)) {
myResult = Spacing.createSpacing(0, 0, 0,
@@ -185,35 +185,30 @@ public class PsiImplUtil {
if (list != null && !list.processDeclarations(processor, state, null, place)) return false;
}
if (lastParent instanceof PsiCodeBlock) {
final PsiParameterList parameterList = method.getParameterList();
if (processDeclarationsInParameterList(parameterList, processor, state)) return false;
final PsiParameter[] parameters = method.getParameterList().getParameters();
for (PsiParameter parameter : parameters) {
if (!processor.execute(parameter, state)) return false;
}
}
return true;
}
public static boolean processDeclarationsInTryStatement(@NotNull final PsiTryStatement statement,
public static boolean processDeclarationsInResourceList(@NotNull final PsiResourceList resourceList,
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent) {
if (lastParent instanceof PsiCodeBlock) {
final PsiParameterList parameterList = statement.getResourceList();
if (parameterList != null && processDeclarationsInParameterList(parameterList, processor, state)) return false;
final List<PsiResource> resources = resourceList.getResources();
for (PsiResource resource : resources) {
final PsiElement resourceElement = resource.getResourceElement();
if (resourceElement instanceof PsiLocalVariable &&
!resourceElement.equals(lastParent) &&
!processor.execute(resourceElement, state)) return false;
}
return true;
}
private static boolean processDeclarationsInParameterList(@NotNull final PsiParameterList parameterList,
@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state) {
final PsiParameter[] parameters = parameterList.getParameters();
for (PsiParameter parameter : parameters) {
if (!processor.execute(parameter, state)) return true;
}
return false;
}
public static boolean hasTypeParameters(@NotNull PsiTypeParameterListOwner owner) {
final PsiTypeParameterList typeParameterList = owner.getTypeParameterList();
return typeParameterList != null && typeParameterList.getTypeParameters().length != 0;
@@ -233,7 +228,7 @@ public class PsiImplUtil {
types[i] = typeElements[i].getType();
}
if (types.length == 1 && types[0] instanceof PsiDiamondType) {
return ((PsiDiamondType)types[0]).getInferredTypes();
return ((PsiDiamondType)types[0]).resolveInferredTypes().getTypes();
}
return types;
}
@@ -60,14 +60,14 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
private static final JavaParserUtil.ParserWrapper PARAMETER = new JavaParserUtil.ParserWrapper() {
@Override
public void parse(final PsiBuilder builder) {
DeclarationParser.parseParameter(builder, true, false, false);
DeclarationParser.parseParameter(builder, true, false);
}
};
private static final JavaParserUtil.ParserWrapper RESOURCE = new JavaParserUtil.ParserWrapper() {
@Override
public void parse(final PsiBuilder builder) {
DeclarationParser.parseParameter(builder, true, false, true);
DeclarationParser.parseResource(builder);
}
};
@@ -169,6 +169,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiAnnotation createAnnotationFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ANNOTATION, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -179,16 +180,19 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiDocTag createDocTagFromText(@NotNull final String text) throws IncorrectOperationException {
return createDocCommentFromText(join("/**\n", text, "\n */")).getTags()[0];
}
@NotNull
@Override
public PsiDocTag createDocTagFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
return createDocTagFromText(text);
}
@NotNull
@Override
public PsiDocComment createDocCommentFromText(@NotNull final String text) throws IncorrectOperationException {
final PsiMethod method = createMethodFromText(join(text, "void m();"), null);
final PsiDocComment comment = method.getDocComment();
@@ -197,11 +201,13 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiDocComment createDocCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
return createDocCommentFromText(text);
}
@NotNull
@Override
public PsiClass createClassFromText(@NotNull final String body, final PsiElement context) throws IncorrectOperationException {
final PsiJavaFile aFile = createDummyJavaFile(join("class _Dummy_ { ", body, " }"));
final PsiClass[] classes = aFile.getClasses();
@@ -212,6 +218,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiField createFieldFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -222,6 +229,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context, final LanguageLevel level) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, DECLARATION, false, level), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -232,17 +240,16 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public final PsiMethod createMethodFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final LanguageLevel level = LanguageLevelProjectExtension.getInstance(myManager.getProject()).getLanguageLevel();
return createMethodFromText(text, context, level);
}
@NotNull
@Override
public PsiParameter createParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final boolean resource = context instanceof PsiParameterList &&
context.getParent() instanceof PsiTryStatement;
final JavaParserUtil.ParserWrapper wrapper = resource ? RESOURCE : PARAMETER;
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, wrapper, false), context);
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, PARAMETER, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiParameter)) {
throw new IncorrectOperationException("Incorrect parameter \"" + text + "\".");
@@ -251,11 +258,24 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiResource createResourceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, RESOURCE, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiResource)) {
throw new IncorrectOperationException("Incorrect resource \"" + text + "\".");
}
return (PsiResource)element;
}
@NotNull
@Override
public PsiType createTypeFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
return createTypeInner(text, context, false);
}
@NotNull
@Override
public PsiTypeElement createTypeElementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final boolean multiCatch = context instanceof PsiParameter &&
context.getParent() instanceof PsiCatchSection &&
@@ -281,6 +301,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiJavaCodeReferenceElement createReferenceFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final boolean isStaticImport = context instanceof PsiImportStaticStatement &&
!((PsiImportStaticStatement)context).isOnDemand();
@@ -294,6 +315,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiCodeBlock createCodeBlockFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, CODE_BLOCK, true), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -304,6 +326,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiStatement createStatementFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, STATEMENT, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -314,6 +337,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiExpression createExpressionFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, EXPRESSION, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -330,6 +354,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiTypeParameter createTypeParameterFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, TYPE_PARAMETER, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -340,6 +365,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiComment createCommentFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final PsiJavaFile aFile = createDummyJavaFile(text);
for (PsiElement aChildren : aFile.getChildren()) {
@@ -357,6 +383,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiEnumConstant createEnumConstantFromText(@NotNull final String text, final PsiElement context) throws IncorrectOperationException {
final DummyHolder holder = DummyHolderFactory.createHolder(myManager, new JavaDummyElement(text, ENUM_CONSTANT, false), context);
final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
@@ -367,6 +394,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
}
@NotNull
@Override
public PsiCatchSection createCatchSection(@NotNull final PsiClassType exceptionType, @NotNull final String exceptionName,
final PsiElement context) throws IncorrectOperationException {
final String text = join("catch (", exceptionType.getCanonicalText(), " ", exceptionName, ") {}");
@@ -406,6 +434,7 @@ public class PsiJavaParserFacadeImpl extends PsiParserFacadeImpl implements PsiJ
psiCatchSection.getCatchBlock().replace(codeBlockFromText);
}
@Override
public PsiType createPrimitiveType(@NotNull final String text, @NotNull final PsiAnnotation[] annotations) throws IncorrectOperationException {
final PsiPrimitiveType primitiveType = getPrimitiveType(text);
if (primitiveType == null) {
@@ -177,7 +177,7 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
final List<PsiType> substituted = ContainerUtil.map(disjunctionType.getDisjunctions(), new Function<PsiType, PsiType>() {
@Override public PsiType fun(PsiType psiType) { return psiType.accept(SubstitutionVisitorBase.this); }
});
return new PsiDisjunctionType(substituted, disjunctionType.getManager());
return disjunctionType.newDisjunctionType(substituted);
}
}
@@ -755,7 +755,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
}
else {
while (superParent != null) {
if (superParent instanceof PsiCodeBlock || superParent instanceof PsiVariable) {
if (superParent instanceof PsiCodeBlock || superParent instanceof PsiLocalVariable) {
smartCompletion = false;
break;
}
@@ -763,8 +763,6 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
}
}
if (!smartCompletion && !isCodeFragmentType(getTreeParent().getElementType()) && !(getParent() instanceof PsiAnnotation)) {
/*filter.addFilter(ElementClassFilter.CLASS);
filter.addFilter(ElementClassFilter.PACKAGE);*/
filter.addFilter(new AndFilter(ElementClassFilter.METHOD, new NotFilter(new ConstructorFilter())));
filter.addFilter(ElementClassFilter.VARIABLE);
}
@@ -82,7 +82,7 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
super(node);
}
public boolean hasModifierProperty(@NotNull String name){
public boolean hasModifierProperty(@NotNull String name) {
final PsiModifierListStub stub = getStub();
if (stub != null) {
int flag = NAME_TO_MODIFIER_FLAG_MAP.get(name);
@@ -93,34 +93,34 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
IElementType type = NAME_TO_KEYWORD_TYPE_MAP.get(name);
PsiElement parent = getParent();
if (parent instanceof PsiClass){
PsiElement pparent = parent.getParent();
if (pparent instanceof PsiClass && ((PsiClass)pparent).isInterface()){
if (type == JavaTokenType.PUBLIC_KEYWORD){
if (parent instanceof PsiClass) {
PsiElement grandParent = parent.getParent();
if (grandParent instanceof PsiClass && ((PsiClass)grandParent).isInterface()) {
if (type == JavaTokenType.PUBLIC_KEYWORD) {
return true;
}
if (type == null){ // package local
if (type == null) { // package local
return false;
}
if (type == JavaTokenType.STATIC_KEYWORD){
if (type == JavaTokenType.STATIC_KEYWORD) {
return true;
}
}
if (((PsiClass)parent).isInterface()){
if (type == JavaTokenType.ABSTRACT_KEYWORD){
if (((PsiClass)parent).isInterface()) {
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
return true;
}
// nested interface is implicitly static
if (pparent instanceof PsiClass) {
if (type == JavaTokenType.STATIC_KEYWORD){
if (grandParent instanceof PsiClass) {
if (type == JavaTokenType.STATIC_KEYWORD) {
return true;
}
}
}
if (((PsiClass)parent).isEnum()){
if (((PsiClass)parent).isEnum()) {
if (type == JavaTokenType.STATIC_KEYWORD) {
if (!(pparent instanceof PsiFile)) return true;
if (!(grandParent instanceof PsiFile)) return true;
}
else if (type == JavaTokenType.FINAL_KEYWORD) {
final PsiField[] fields = ((PsiClass)parent).getFields();
@@ -138,37 +138,37 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
}
}
}
else if (parent instanceof PsiMethod){
else if (parent instanceof PsiMethod) {
PsiClass aClass = ((PsiMethod)parent).getContainingClass();
if (aClass != null && aClass.isInterface()){
if (type == JavaTokenType.PUBLIC_KEYWORD){
if (aClass != null && aClass.isInterface()) {
if (type == JavaTokenType.PUBLIC_KEYWORD) {
return true;
}
if (type == null){ // package local
if (type == null) { // package local
return false;
}
if (type == JavaTokenType.ABSTRACT_KEYWORD){
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
return true;
}
}
}
else if (parent instanceof PsiField){
else if (parent instanceof PsiField) {
if (parent instanceof PsiEnumConstant) {
return type == JavaTokenType.PUBLIC_KEYWORD || type == JavaTokenType.STATIC_KEYWORD || type == JavaTokenType.FINAL_KEYWORD;
}
else {
PsiClass aClass = ((PsiField)parent).getContainingClass();
if (aClass != null && aClass.isInterface()){
if (type == JavaTokenType.PUBLIC_KEYWORD){
if (aClass != null && aClass.isInterface()) {
if (type == JavaTokenType.PUBLIC_KEYWORD) {
return true;
}
if (type == null){ // package local
if (type == null) { // package local
return false;
}
if (type == JavaTokenType.STATIC_KEYWORD){
if (type == JavaTokenType.STATIC_KEYWORD) {
return true;
}
if (type == JavaTokenType.FINAL_KEYWORD){
if (type == JavaTokenType.FINAL_KEYWORD) {
return true;
}
}
@@ -177,9 +177,15 @@ public class PsiModifierListImpl extends JavaStubPsiElement<PsiModifierListStub>
else if (parent instanceof PsiParameter) {
if (type == JavaTokenType.FINAL_KEYWORD && ((PsiParameter)parent).getType() instanceof PsiDisjunctionType) return true;
}
else if (parent instanceof PsiLocalVariable) {
PsiElement grandParent = parent.getParent();
if (type == JavaTokenType.FINAL_KEYWORD && grandParent instanceof PsiResource) return true;
}
if (type == null){ // package local
return !hasModifierProperty(PsiModifier.PUBLIC) && !hasModifierProperty(PsiModifier.PRIVATE) && !hasModifierProperty(PsiModifier.PROTECTED);
if (type == null) { // package local
return !hasModifierProperty(PsiModifier.PUBLIC) &&
!hasModifierProperty(PsiModifier.PRIVATE) &&
!hasModifierProperty(PsiModifier.PROTECTED);
}
return getNode().findChildByType(type) != null;
@@ -403,8 +403,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
final boolean forCompletion) {
PsiTypeParameterListOwner owner = typeParameter.getOwner();
Pair<PsiType, ConstraintType> substitution = null;
if (owner instanceof PsiMethod && parent instanceof PsiMethodCallExpression) {
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)parent;
if (owner instanceof PsiMethod && parent instanceof PsiCallExpression) {
PsiCallExpression methodCall = (PsiCallExpression)parent;
substitution = inferMethodTypeParameterFromParent(methodCall.getParent(), methodCall, typeParameter, substitutor, forCompletion);
}
return substitution;
@@ -604,7 +604,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
private static Pair<PsiType, ConstraintType> inferMethodTypeParameterFromParent(PsiElement parent,
PsiMethodCallExpression methodCall,
PsiCallExpression methodCall,
final PsiTypeParameter typeParameter,
PsiSubstitutor substitutor,
final boolean forCompletion) {
@@ -701,13 +701,13 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
return result;
}
private static final ThreadLocal<List<PsiMethodCallExpression>> myBlockedForInferenceMethodCalls = new ThreadLocal<List<PsiMethodCallExpression>>() {
protected List<PsiMethodCallExpression> initialValue() {
return new ArrayList<PsiMethodCallExpression>(2);
private static final ThreadLocal<List<PsiCallExpression>> myBlockedForInferenceMethodCalls = new ThreadLocal<List<PsiCallExpression>>() {
protected List<PsiCallExpression> initialValue() {
return new ArrayList<PsiCallExpression>(2);
}
};
private static Pair<PsiType, ConstraintType> inferTypeForCompletionFromCallContext(final PsiMethodCallExpression innerMethodCall,
private static Pair<PsiType, ConstraintType> inferTypeForCompletionFromCallContext(final PsiCallExpression innerMethodCall,
final PsiExpressionList expressionList,
final PsiCallExpression contextCall,
final PsiTypeParameter typeParameter) {
@@ -127,9 +127,11 @@ public interface JavaElementType {
IElementType THROW_STATEMENT = new JavaCompositeElementType("THROW_STATEMENT", PsiThrowStatementImpl.class);
IElementType SYNCHRONIZED_STATEMENT = new JavaCompositeElementType("SYNCHRONIZED_STATEMENT", PsiSynchronizedStatementImpl.class);
IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class);
IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class);
IElementType RESOURCE = new JavaCompositeElementType("RESOURCE", PsiResourceImpl.class);
IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class);
IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class);
IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class);
IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class);
IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class);
IElementType NAME_VALUE_PAIR = new JavaCompositeElementType("NAME_VALUE_PAIR", PsiNameValuePairImpl.class, true);
IElementType ANNOTATION_PARAMETER_LIST = new JavaCompositeElementType("ANNOTATION_PARAMETER_LIST", PsiAnnotationParameterListImpl.class, true);
@@ -49,7 +49,7 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Set;
public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLocalVariable, PsiVariableEx, Constants {
public class PsiLocalVariableImpl extends CompositePsiElement implements PsiScopedLocalVariable, PsiVariableEx, Constants {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiLocalVariableImpl");
private volatile String myCachedName = null;
@@ -94,7 +94,7 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
@NotNull
public PsiTypeElement getTypeElement() {
ASTNode first = getTreeParent().findChildByType(LOCAL_VARIABLE);
return (PsiTypeElement)SourceTreeToPsiMap.treeElementToPsi(first.findChildByType(TYPE));
return SourceTreeToPsiMap.treeToPsiNotNull(first.findChildByType(TYPE));
}
public PsiModifierList getModifierList() {
@@ -105,7 +105,8 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
}
public boolean hasModifierProperty(@NotNull String name) {
return getModifierList().hasModifierProperty(name);
final PsiModifierList modifierList = getModifierList();
return modifierList != null && modifierList.hasModifierProperty(name);
}
public PsiExpression getInitializer() {
@@ -278,6 +279,21 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
return "PsiLocalVariable:" + getName();
}
@NotNull
public PsiElement[] getDeclarationScope() {
final PsiElement parentElement = getParent();
if (parentElement instanceof PsiDeclarationStatement) {
return new PsiElement[]{parentElement.getParent()};
}
else if (parentElement instanceof PsiResource) {
final PsiResourceList resourceList = (PsiResourceList)parentElement.getParent();
final PsiTryStatement tryStatement = (PsiTryStatement)resourceList.getParent();
final PsiCodeBlock tryBlock = tryStatement.getTryBlock();
return tryBlock != null ? new PsiElement[]{resourceList, tryBlock} : new PsiElement[]{resourceList};
}
return new PsiElement[]{parentElement.getParent()};
}
@NotNull
public SearchScope getUseScope() {
if (JspPsiUtil.isInJspFile(this)) {
@@ -304,9 +320,9 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
}
}
PsiElement parentElement = getParent();
if (parentElement instanceof PsiDeclarationStatement) {
return new LocalSearchScope(parentElement.getParent());
final PsiElement parentElement = getParent();
if (parentElement instanceof PsiDeclarationStatement || parentElement instanceof PsiResource) {
return new LocalSearchScope(getDeclarationScope());
}
else {
return getManager().getFileManager().getUseScope(this);
@@ -317,6 +333,7 @@ public class PsiLocalVariableImpl extends CompositePsiElement implements PsiLoca
final RowIcon baseIcon = createLayeredIcon(Icons.VARIABLE_ICON, ElementPresentationUtil.getFlags(this, false));
return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
}
public PsiType getTypeNoResolve() {
return getType();
}
@@ -0,0 +1,74 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import org.jetbrains.annotations.NotNull;
public class PsiResourceImpl extends CompositePsiElement implements PsiResource {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiResourceImpl");
public PsiResourceImpl() {
super(JavaElementType.RESOURCE);
}
@NotNull
@Override
public PsiElement getResourceElement() {
final PsiElement element = getFirstChild();
assert element != null : this;
return element;
}
@Override
public PsiType getType() {
final PsiElement element = getResourceElement();
if (element instanceof PsiLocalVariable) {
return ((PsiLocalVariable)element).getType();
}
else if (element instanceof PsiExpression) {
return ((PsiExpression)element).getType();
}
LOG.error("Unexpected resource type: " + LogUtil.objectAndClass(element));
return null;
}
@Override
public void accept(@NotNull final PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitResource(this);
}
else {
visitor.visitElement(this);
}
}
public String getName() {
final PsiElement element = getFirstChild();
if (element instanceof PsiLocalVariable) return ((PsiLocalVariable)element).getName();
if (element instanceof PsiAssignmentExpression) return ((PsiAssignmentExpression)element).getLExpression().toString();
return "";
}
@Override
public String toString() {
return "PsiResource:" + getName();
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source.tree.java;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class PsiResourceListImpl extends CompositePsiElement implements PsiResourceList {
public PsiResourceListImpl() {
super(JavaElementType.RESOURCE_LIST);
}
@NotNull
@Override
public List<PsiResource> getResources() {
return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResource.class);
}
@Override
public void accept(@NotNull final PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitResourceList(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public boolean processDeclarations(@NotNull final PsiScopeProcessor processor,
@NotNull final ResolveState state,
final PsiElement lastParent,
@NotNull final PsiElement place) {
return PsiImplUtil.processDeclarationsInResourceList(this, processor, state, lastParent);
}
@Override
public String toString() {
return "PsiResourceList:" + getText();
}
}
@@ -93,8 +93,8 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt
}
@Override
public PsiParameterList getResourceList() {
return PsiTreeUtil.findChildOfType(this, PsiParameterList.class);
public PsiResourceList getResourceList() {
return PsiTreeUtil.findChildOfType(this, PsiResourceList.class);
}
public ASTNode findChildByRole(int role) {
@@ -164,7 +164,12 @@ public class PsiTryStatementImpl extends CompositePsiElement implements PsiTrySt
@NotNull final ResolveState state,
final PsiElement lastParent,
@NotNull final PsiElement place) {
return PsiImplUtil.processDeclarationsInTryStatement(this, processor, state, lastParent);
final PsiResourceList resourceList = getResourceList();
if (resourceList != null && lastParent instanceof PsiCodeBlock && lastParent == getTryBlock()) {
return PsiImplUtil.processDeclarationsInResourceList(resourceList, processor, state, lastParent);
}
return true;
}
public String toString() {
@@ -26,11 +26,13 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -131,6 +133,11 @@ class VariableInplaceIntroducer extends VariableInplaceRenamer {
return super.createLookupItems(lookupItems, name);
}
@Override
protected TextRange preserveSelectedRange(SelectionModel selectionModel) {
return null;
}
@Override
protected void moveOffsetAfter(boolean success) {
try {
@@ -37,6 +37,12 @@ public class JavadocTypedHandlerTest {
doTest("<t\nag><caret>", null);
}
@Test
public void tagWithAttribute() {
doTest("<a href='www'><caret>", "a");
//TODO den implement
}
private static void doTest(String text, String expected) {
StringBuilder normalized = new StringBuilder();
int offset = text.indexOf(CARET_MARKER);
@@ -0,0 +1,6 @@
class A {
final boolean aboo;
A() {
abo<caret>
}
}
@@ -0,0 +1,6 @@
class A {
final boolean aboo;
A() {
aboo<caret>
}
}
@@ -0,0 +1,9 @@
public class ConstConfig {
{
switch (a) {
case Foooo: {}
def<caret>
}
}
}
@@ -0,0 +1,9 @@
public class ConstConfig {
{
switch (a) {
case Foooo: {}
default:<caret>
}
}
}
@@ -0,0 +1,7 @@
public class ConstConfig {
public static boolean testMode = false;
{
if (test<caret>x)
}
}
@@ -0,0 +1,7 @@
public class ConstConfig {
public static boolean testMode = false;
{
if (!testMode<caret>x)
}
}
@@ -0,0 +1,4 @@
class A {
private lo<caret> localizedStringManager;
}
@@ -0,0 +1,4 @@
class A {
private long <caret>localizedStringManager;
}
@@ -0,0 +1,5 @@
class A {
A() {
fin<caret>this.toString();
}
}
@@ -2,6 +2,7 @@ public class Aaaaaaa {
private final String aaa;
Aaaaaaa(String aabbb) {
aaa = "";
aaa = true ? null : aa<caret>
}
@@ -2,6 +2,7 @@ public class Aaaaaaa {
private final String aaa;
Aaaaaaa(Object aabbb) {
aaa = "";
aaa = true ? null : aa<caret>
}
@@ -0,0 +1,15 @@
class Goo {
int boo() {}
int doo() {}
int foo() {}
}
class Foooo {
Goo g;
int foo() {
return g.<caret>
}
}
@@ -0,0 +1,8 @@
class A {
public abstract void zoo(int y);
{
Object x;
zoo((Integer) <caret>x);
}
}
@@ -0,0 +1,8 @@
class A {
public abstract void zoo(int y);
{
Object x;
zoo((<caret>x);
}
}
@@ -0,0 +1,8 @@
class A {
public abstract void zoo(int y);
{
Object x;
zoo((Integer) <caret>x);
}
}
@@ -0,0 +1,8 @@
class A {
public abstract void zoo(int y);
{
Object x;
zoo((<caret>) x);
}
}
@@ -0,0 +1,8 @@
class A {
public abstract void zoo(int y);
{
Object x;
zoo((Integer) <caret>x);
}
}

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