diff options
Diffstat (limited to 'java/java-psi-impl/src/com')
23 files changed, 406 insertions, 244 deletions
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java index 9f5ecb109fd5..5e008afb4797 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java @@ -45,7 +45,6 @@ import com.intellij.psi.util.*; import com.intellij.util.Function; import com.intellij.util.ObjectUtils; import com.intellij.util.text.CharArrayUtil; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -701,7 +700,7 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem else if (element instanceof PsiComment) { return settings.isCollapseEndOfLineComments(); } - else if (isLiteralExpression(element) + else if (ParameterNameFoldingManager.isLiteralExpression(element) && element.getParent() instanceof PsiExpressionList && (element.getParent().getParent() instanceof PsiCallExpression || element.getParent().getParent() instanceof PsiAnonymousClass)) { @@ -760,55 +759,8 @@ public abstract class JavaFoldingBuilderBase extends CustomFoldingBuilder implem if (quick || !JavaCodeFoldingSettings.getInstance().isInlineParameterNamesForLiteralCallArguments()) { return; } - PsiExpressionList callArgumentsList = expression.getArgumentList(); - if (callArgumentsList == null) { - return; - } - - PsiExpression[] callArguments = callArgumentsList.getExpressions(); - if (callArguments.length > 1) { - PsiParameter[] parameters = null; - boolean isResolved = false; - - for (int i = 0; i < callArguments.length; i++) { - PsiExpression callArgument = callArguments[i]; - - if (callArgument.getType() != null && isLiteralExpression(callArgument)) { - if (!isResolved) { - PsiMethod method = expression.resolveMethod(); - isResolved = true; - if (method == null) { - return; - } - parameters = method.getParameterList().getParameters(); - if (parameters.length != callArguments.length) { - return; - } - } - - PsiParameter methodParam = parameters[i]; - if (TypeConversionUtil.isAssignable(methodParam.getType(), callArgument.getType())) { - TextRange range = callArgument.getTextRange(); - String placeholderText = methodParam.getName() + ": " + callArgument.getText(); - foldElements.add(new NamedFoldingDescriptor(callArgument, range.getStartOffset(), range.getEndOffset(), null, placeholderText)); - } - } - } - } - } - - @Contract("null -> false") - private static boolean isLiteralExpression(@Nullable PsiElement callArgument) { - if (callArgument instanceof PsiLiteralExpression) - return true; - - if (callArgument instanceof PsiPrefixExpression) { - PsiPrefixExpression expr = (PsiPrefixExpression)callArgument; - IElementType tokenType = expr.getOperationTokenType(); - return JavaTokenType.MINUS.equals(tokenType) && expr.getOperand() instanceof PsiLiteralExpression; - } - - return false; + ParameterNameFoldingManager manager = new ParameterNameFoldingManager(expression); + foldElements.addAll(manager.buildDescriptors()); } private boolean addClosureFolding(final PsiClass aClass, final Document document, final List<FoldingDescriptor> foldElements, diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java new file mode 100644 index 000000000000..aca4357f7e49 --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/ParameterNameFoldingManager.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * 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.folding.impl; + +import com.intellij.lang.folding.FoldingDescriptor; +import com.intellij.lang.folding.NamedFoldingDescriptor; +import com.intellij.openapi.util.Couple; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ParameterNameFoldingManager { + private static final int MIN_NAME_LENGTH_THRESHOLD = 3; + private static final int MIN_ARGS_TO_FOLD = 2; + + private static final List<Couple<String>> COMMONLY_USED_PARAMETER_PAIR = ContainerUtil.newArrayList( + Couple.of("begin", "end"), + Couple.of("start", "end"), + Couple.of("first", "last"), + Couple.of("first", "second"), + Couple.of("from", "to"), + Couple.of("key", "value") + ); + + private final PsiCallExpression myCallExpression; + + private PsiExpression[] myCallArguments; + private PsiParameter[] myParameters; + + public ParameterNameFoldingManager(@NotNull PsiCallExpression callExpression) { + myCallExpression = callExpression; + } + + public static boolean isLiteralExpression(@Nullable PsiElement callArgument) { + if (callArgument instanceof PsiLiteralExpression) + return true; + + if (callArgument instanceof PsiPrefixExpression) { + PsiPrefixExpression expr = (PsiPrefixExpression)callArgument; + IElementType tokenType = expr.getOperationTokenType(); + return JavaTokenType.MINUS.equals(tokenType) && expr.getOperand() instanceof PsiLiteralExpression; + } + + return false; + } + + @Nullable + public PsiExpression[] getArguments(@NotNull PsiCallExpression call) { + PsiExpressionList callArgumentsList = call.getArgumentList(); + return callArgumentsList != null ? callArgumentsList.getExpressions() : null; + } + + @NotNull + public List<FoldingDescriptor> buildDescriptors() { + myCallArguments = getArguments(myCallExpression); + + if (myCallArguments != null && myCallArguments.length >= MIN_ARGS_TO_FOLD && hasLiteralExpression(myCallArguments)) { + PsiMethod method = myCallExpression.resolveMethod(); + + if (method != null) { + myParameters = method.getParameterList().getParameters(); + if (myParameters.length == myCallArguments.length) { + return buildDescriptorsForLiteralArguments(); + } + } + } + + return ContainerUtil.emptyList(); + } + + @NotNull + private List<FoldingDescriptor> buildDescriptorsForLiteralArguments() { + List<FoldingDescriptor> descriptors = ContainerUtil.newArrayList(); + + int i = 0; + while (i < myCallArguments.length) { + if (i + 1 < myCallArguments.length && isCommonlyNamedParameterPair(i, i + 1)) { + i += 2; + continue; + } + + if (shouldInlineParameterName(i)) { + descriptors.add(createFoldingDescriptor(myCallArguments[i], myParameters[i])); + } + i++; + } + + return descriptors; + } + + @NotNull + private static NamedFoldingDescriptor createFoldingDescriptor(@NotNull PsiExpression callArgument, @NotNull PsiParameter methodParam) { + TextRange range = callArgument.getTextRange(); + String placeholderText = methodParam.getName() + ": " + callArgument.getText(); + return new NamedFoldingDescriptor(callArgument, range.getStartOffset(), range.getEndOffset(), null, placeholderText); + } + + private boolean isCommonlyNamedParameterPair(int first, int second) { + assert first < myParameters.length && second < myParameters.length; + + String firstParamName = myParameters[first].getName(); + String secondParamName = myParameters[second].getName(); + if (firstParamName == null || secondParamName == null) return false; + + for (Couple<String> knownPair : COMMONLY_USED_PARAMETER_PAIR) { + if (StringUtil.containsIgnoreCase(firstParamName, knownPair.first) + && StringUtil.containsIgnoreCase(secondParamName, knownPair.second)) { + return true; + } + } + + return false; + } + + private boolean shouldInlineParameterName(int paramIndex) { + PsiExpression argument = myCallArguments[paramIndex]; + if (isLiteralExpression(argument) && argument.getType() != null) { + PsiParameter parameter = myParameters[paramIndex]; + String paramName = parameter.getName(); + if (paramName != null && paramName.length() >= MIN_NAME_LENGTH_THRESHOLD) { + return TypeConversionUtil.isAssignable(parameter.getType(), argument.getType()); + } + } + return false; + } + + private static boolean hasLiteralExpression(@NotNull PsiExpression[] arguments) { + for (PsiExpression argument : arguments) { + if (isLiteralExpression(argument)) return true; + } + return false; + } +} diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java index 0052dd5bb8b9..f2b9583c49b0 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.javadoc; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.ExternalAnnotationsManager; +import com.intellij.codeInsight.InferredAnnotationsManager; import com.intellij.codeInsight.documentation.DocumentationManagerUtil; import com.intellij.lang.ASTNode; import com.intellij.lang.LangBundle; @@ -217,6 +218,7 @@ public class JavaDocInfoGenerator { LOG.debug(text); } + text = StringUtil.replaceIgnoreCase(text, "<p/>", "<p></p>"); return StringUtil.replace(text, "/>", ">"); } @@ -321,7 +323,7 @@ public class JavaDocInfoGenerator { } private static boolean generateClassSignature(StringBuilder buffer, PsiClass aClass, boolean generateLink) { - generateAnnotations(buffer, aClass, generateLink); + generateAnnotations(buffer, aClass, generateLink, true); String modifiers = PsiFormatUtil.formatModifiers(aClass, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY); if (!modifiers.isEmpty()) { buffer.append(modifiers); @@ -487,7 +489,7 @@ public class JavaDocInfoGenerator { } private static void generateFieldSignature(StringBuilder buffer, PsiField field, boolean generateLink) { - generateAnnotations(buffer, field, generateLink); + generateAnnotations(buffer, field, generateLink, true); String modifiers = PsiFormatUtil.formatModifiers(field, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY); if (!modifiers.isEmpty()) { buffer.append(modifiers); @@ -695,30 +697,38 @@ public class JavaDocInfoGenerator { } } - private static void generateAnnotations(@NonNls @NotNull StringBuilder buffer, @NotNull PsiModifierListOwner owner, boolean generateLink) { + private static void generateAnnotations(@NonNls @NotNull StringBuilder buffer, + @NotNull PsiModifierListOwner owner, + boolean generateLink, + boolean splitAnnotations) { final PsiModifierList ownerModifierList = owner.getModifierList(); if (ownerModifierList == null) return; - generateAnnotations(buffer, owner, ownerModifierList.getAnnotations(), false, generateLink); - final PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner); - if (externalAnnotations != null) { - generateAnnotations(buffer, owner, externalAnnotations, true, generateLink); + generateAnnotations(buffer, owner, ownerModifierList.getAnnotations(), false, generateLink, splitAnnotations); + PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner); + if (externalAnnotations == null) { + externalAnnotations = new PsiAnnotation[]{}; } + PsiAnnotation[] inferredAnnotations = InferredAnnotationsManager.getInstance(owner.getProject()).findInferredAnnotations(owner); + externalAnnotations = ArrayUtil.mergeArrays(externalAnnotations, inferredAnnotations, PsiAnnotation.ARRAY_FACTORY); + generateAnnotations(buffer, owner, externalAnnotations, true, generateLink, splitAnnotations); } private static void generateAnnotations(StringBuilder buffer, PsiModifierListOwner owner, PsiAnnotation[] annotations, boolean external, - boolean generateLink) { + boolean generateLink, boolean splitAnnotations) { PsiManager manager = owner.getManager(); for (PsiAnnotation annotation : annotations) { final PsiJavaCodeReferenceElement nameReferenceElement = annotation.getNameReferenceElement(); if (nameReferenceElement == null) continue; final PsiElement resolved = nameReferenceElement.resolve(); + boolean inferred = AnnotationUtil.isInferredAnnotation(annotation); if (resolved instanceof PsiClass) { final PsiClass annotationType = (PsiClass)resolved; if (AnnotationUtil.isAnnotated(annotationType, "java.lang.annotation.Documented", false)) { + if (inferred) buffer.append("<i>"); final PsiClassType type = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(annotationType, PsiSubstitutor.EMPTY); buffer.append("@"); generateType(buffer, type, owner, generateLink); @@ -736,24 +746,27 @@ public class JavaDocInfoGenerator { } final PsiAnnotationMemberValue value = pair.getValue(); if (value != null) { - buffer.append(value.getText()); + buffer.append(XmlStringUtil.escapeString(value.getText())); } } buffer.append(")"); } + if (inferred) buffer.append("</i>"); buffer.append(" "); } } else if (external) { - buffer.append(annotation.getText()); + if (inferred) buffer.append("<i>"); + buffer.append(XmlStringUtil.escapeString(annotation.getText())); buffer.append(" "); + if (inferred) buffer.append("</i>"); } else { buffer.append("<font color=red>"); - buffer.append(annotation.getText()); + buffer.append(XmlStringUtil.escapeString(annotation.getText())); buffer.append("</font>"); buffer.append(" "); } - buffer.append("\n"); + if (splitAnnotations) buffer.append("\n"); } } @@ -767,7 +780,7 @@ public class JavaDocInfoGenerator { buffer.append(modifiers); buffer.append(" "); } - generateAnnotations(buffer, parameter, true); + generateAnnotations(buffer, parameter, true, true); generateType(buffer, parameter.getType(), parameter); buffer.append(" "); buffer.append("<b>"); @@ -843,7 +856,7 @@ public class JavaDocInfoGenerator { } private static void generateMethodSignature(StringBuilder buffer, PsiMethod method, boolean generateLink) { - generateAnnotations(buffer, method, generateLink); + generateAnnotations(buffer, method, generateLink, true); String modifiers = PsiFormatUtil.formatModifiers(method, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY); int indent = 0; if (!modifiers.isEmpty()) { @@ -876,7 +889,7 @@ public class JavaDocInfoGenerator { PsiParameter[] parms = method.getParameterList().getParameters(); for (int i = 0; i < parms.length; i++) { PsiParameter parm = parms[i]; - generateAnnotations(buffer, parm, generateLink); + generateAnnotations(buffer, parm, generateLink, false); generateType(buffer, parm.getType(), method, generateLink); buffer.append(" "); if (parm.getName() != null) { diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 0377048d0acb..36d024726bbf 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -46,6 +46,8 @@ public class DeclarationParser { JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.THROWS_KEYWORD); private static final TokenSet PARAM_LIST_STOPPERS = TokenSet.create( JavaTokenType.RPARENTH, JavaTokenType.LBRACE, JavaTokenType.ARROW); + private static final TokenSet TYPE_START = TokenSet.orSet( + ElementType.PRIMITIVE_TYPE_BIT_SET, TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.AT)); private static final String WHITESPACES = "\n\r \t"; private static final String LINE_ENDS = "\n\r"; @@ -278,56 +280,64 @@ public class DeclarationParser { return modList; } - PsiBuilder.Marker type; - if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(builder.getTokenType())) { - type = parseTypeNotNull(builder); - } - else if (builder.getTokenType() == JavaTokenType.IDENTIFIER) { - final PsiBuilder.Marker idPos = builder.mark(); - type = parseTypeNotNull(builder); - if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor - if (context == Context.CODE_BLOCK) { - declaration.rollbackTo(); - return null; - } - idPos.rollbackTo(); - if (typeParams == null) { - emptyElement(builder, JavaElementType.TYPE_PARAMETER_LIST); - } - builder.advanceLexer(); - if (builder.getTokenType() != JavaTokenType.LPARENTH) { - declaration.rollbackTo(); - return null; - } - return parseMethodFromLeftParenth(builder, declaration, false, true); - } - idPos.drop(); - } - else if (builder.getTokenType() == JavaTokenType.LBRACE) { + if (builder.getTokenType() == JavaTokenType.LBRACE) { if (context == Context.CODE_BLOCK) { error(builder, JavaErrorMessages.message("expected.identifier.or.type"), typeParams); declaration.drop(); return modList; } - final PsiBuilder.Marker codeBlock = myParser.getStatementParser().parseCodeBlock(builder); + PsiBuilder.Marker codeBlock = myParser.getStatementParser().parseCodeBlock(builder); assert codeBlock != null : builder.getOriginalText(); if (typeParams != null) { - final PsiBuilder.Marker error = typeParams.precede(); + PsiBuilder.Marker error = typeParams.precede(); error.errorBefore(JavaErrorMessages.message("unexpected.token"), codeBlock); } + done(declaration, JavaElementType.CLASS_INITIALIZER); return declaration; } - else { - final PsiBuilder.Marker error; - if (typeParams != null) { - error = typeParams.precede(); + + PsiBuilder.Marker type = null; + + if (TYPE_START.contains(builder.getTokenType())) { + PsiBuilder.Marker pos = builder.mark(); + + type = myParser.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD); + + if (type == null) { + pos.rollbackTo(); + } + else if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor + if (context == Context.CODE_BLOCK) { + declaration.rollbackTo(); + return null; + } + + pos.rollbackTo(); + + if (typeParams == null) { + emptyElement(builder, JavaElementType.TYPE_PARAMETER_LIST); + } + parseAnnotations(builder); + builder.advanceLexer(); + + if (builder.getTokenType() == JavaTokenType.LPARENTH) { + return parseMethodFromLeftParenth(builder, declaration, false, true); + } + else { + declaration.rollbackTo(); + return null; + } } else { - error = builder.mark(); + pos.drop(); } + } + + if (type == null) { + PsiBuilder.Marker error = typeParams != null ? typeParams.precede() : builder.mark(); error.error(JavaErrorMessages.message("expected.identifier.or.type")); declaration.drop(); return modList; @@ -364,13 +374,6 @@ public class DeclarationParser { } @NotNull - private PsiBuilder.Marker parseTypeNotNull(final PsiBuilder builder) { - final PsiBuilder.Marker type = myParser.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD); - assert type != null : builder.getOriginalText(); - return type; - } - - @NotNull public Pair<PsiBuilder.Marker, Boolean> parseModifierList(final PsiBuilder builder) { return parseModifierList(builder, ElementType.MODIFIER_BIT_SET); } diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 42a41d51c6fb..e18b1b5b5dab 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -277,8 +277,8 @@ public class ReferenceParser { error(builder, JavaErrorMessages.message("expected.identifier")); } else { - final IElementType tokenType = builder.getTokenType(); - if (WILDCARD_KEYWORD_SET.contains(tokenType) && tokenType != null) { + IElementType tokenType = builder.getTokenType(); + if (WILDCARD_KEYWORD_SET.contains(tokenType)) { parseReferenceList(builder, tokenType, null, JavaTokenType.AND); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java index 543c8a653651..f958555a3c45 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/InheritanceImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiModificationTracker; -import com.intellij.util.containers.ConcurrentHashMap; +import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.containers.HashSet; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; @@ -41,14 +41,14 @@ public class InheritanceImplUtil { if (baseClass instanceof PsiAnonymousClass) return false; if (!checkDeep) return isInheritor(candidateClass, baseClass, false, null); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(candidateClass.getQualifiedName())) return false; - if (CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) return true; + if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(candidateClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(candidateClass.getQualifiedName())) return false; + if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseClass.getName()) && CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName())) return true; Map<PsiClass, Boolean> map = CachedValuesManager. getCachedValue(candidateClass, new CachedValueProvider<Map<PsiClass, Boolean>>() { @Nullable @Override public Result<Map<PsiClass, Boolean>> compute() { - final Map<PsiClass, Boolean> map = new ConcurrentHashMap<PsiClass, Boolean>(); + final Map<PsiClass, Boolean> map = new ConcurrentWeakHashMap<PsiClass, Boolean>(); return Result.create(map, candidateClass, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT); } }); @@ -82,7 +82,7 @@ public class InheritanceImplUtil { } @NonNls final String baseName = baseClass.getName(); - if ("Object".equals(baseName)) { + if (CommonClassNames.JAVA_LANG_OBJECT_SHORT.equals(baseName)) { PsiClass objectClass = JavaPsiFacade.getInstance(manager.getProject()).findClass(CommonClassNames.JAVA_LANG_OBJECT, candidateClass.getResolveScope()); if (manager.areElementsEquivalent(baseClass, objectClass)) { if (manager.areElementsEquivalent(candidateClass, objectClass)) return false; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java index 674ccbe1f03f..19da149c99b8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaConstantExpressionEvaluator.java @@ -105,11 +105,11 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking return myMapFactory.create(); } - public static Object computeConstantExpression(PsiExpression expression, @Nullable Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow) { + public static Object computeConstantExpression(@Nullable PsiExpression expression, @Nullable Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow) { return computeConstantExpression(expression, visitedVars, throwExceptionOnOverflow, null); } - public static Object computeConstantExpression(PsiExpression expression, @Nullable Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow, + public static Object computeConstantExpression(@Nullable PsiExpression expression, @Nullable Set<PsiVariable> visitedVars, boolean throwExceptionOnOverflow, final PsiConstantEvaluationHelper.AuxEvaluator auxEvaluator) { if (expression == null) return null; @@ -131,7 +131,7 @@ public class JavaConstantExpressionEvaluator extends JavaRecursiveElementWalking return cached == NO_VALUE ? null : cached; } - public static Object computeConstantExpression(PsiExpression expression, boolean throwExceptionOnOverflow) { + public static Object computeConstantExpression(@Nullable PsiExpression expression, boolean throwExceptionOnOverflow) { return computeConstantExpression(expression, null, throwExceptionOnOverflow); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java index 46cceffcb6ad..bd5f75ece27f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java @@ -32,6 +32,7 @@ import com.intellij.util.cls.ClsFormatException; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.StringRef; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.text.CharacterIterator; @@ -259,7 +260,8 @@ public class SignatureParsing { return variance; } - public static String parseTypeString(CharacterIterator signature) throws ClsFormatException { + @NotNull + public static String parseTypeString(@NotNull CharacterIterator signature) throws ClsFormatException { int arrayDimensions = 0; while (signature.current() == '[') { arrayDimensions++; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaImportStatementElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaImportStatementElementType.java index 7c9af30f1d9b..93e359e6778a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaImportStatementElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/JavaImportStatementElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ import com.intellij.psi.impl.java.stubs.impl.PsiImportStatementStubImpl; import com.intellij.psi.impl.source.PsiImportStatementImpl; import com.intellij.psi.impl.source.PsiImportStaticStatementImpl; import com.intellij.psi.impl.source.tree.JavaElementType; -import com.intellij.psi.impl.source.tree.SourceUtil; +import com.intellij.psi.impl.source.tree.JavaSourceUtil; import com.intellij.psi.impl.source.tree.java.ImportStaticStatementElement; import com.intellij.psi.stubs.IndexSink; import com.intellij.psi.stubs.StubElement; @@ -68,7 +68,7 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType for (LighterASTNode child : tree.getChildren(node)) { IElementType type = child.getTokenType(); if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) { - refText = SourceUtil.getReferenceText(tree, child); + refText = JavaSourceUtil.getReferenceText(tree, child); } else if (type == JavaTokenType.ASTERISK) { isOnDemand = true; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightStubBuilder.java index ff8c80db3729..3413fda3a3fe 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightStubBuilder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/JavaLightStubBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ public class JavaLightStubBuilder extends LightStubBuilder { if (pkg != null) { LighterASTNode ref = LightTreeUtil.firstChildOfType(tree, pkg, JavaElementType.JAVA_CODE_REFERENCE); if (ref != null) { - refText = SourceUtil.getReferenceText(tree, ref); + refText = JavaSourceUtil.getReferenceText(tree, ref); } } return new PsiJavaFileStubImpl((PsiJavaFile)file, StringRef.fromString(refText), false); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 55b760031646..807b42d60383 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -587,7 +587,15 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme if (parameterList != null) { text += parameterList.getText(); } - PsiJavaCodeReferenceElement ref = facade.getParserFacade().createReferenceFromText(text, getParent()); + + PsiJavaCodeReferenceElement ref; + try { + ref = facade.getParserFacade().createReferenceFromText(text, getParent()); + } + catch (IncorrectOperationException e) { + throw new IncorrectOperationException(e.getMessage() + " [qname=" + qName + " class=" + aClass + ";" + aClass.getClass().getName() + "]"); + } + ((PsiJavaCodeReferenceElementImpl)ref).setAnnotations(annotations); getTreeParent().replaceChildInternal(this, (TreeElement)ref.getNode()); @@ -743,7 +751,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme private String getNormalizedText() { String whiteSpaceAndComments = myCachedNormalizedText; if (whiteSpaceAndComments == null) { - myCachedNormalizedText = whiteSpaceAndComments = SourceUtil.getReferenceText(this); + myCachedNormalizedText = whiteSpaceAndComments = JavaSourceUtil.getReferenceText(this); } return whiteSpaceAndComments; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java index a2e5593478eb..3e081a738caf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/ClassResolverProcessor.java @@ -38,6 +38,7 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi @NotNull private final PsiFile myContainingFile; private final PsiElement myPlace; + private final PsiResolveHelper myResolveHelper; private PsiClass myAccessClass = null; private List<ClassCandidateInfo> myCandidates = null; private boolean myHasAccessibleCandidate; @@ -67,6 +68,7 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi } } } + myResolveHelper = JavaPsiFacade.getInstance(containingFile.getProject()).getResolveHelper(); } @NotNull @@ -252,8 +254,7 @@ public class ClassResolverProcessor extends BaseScopeProcessor implements NameHi } private boolean checkAccessibility(final PsiClass aClass) { - JavaPsiFacade facade = JavaPsiFacade.getInstance(aClass.getProject()); - return facade.getResolveHelper().isAccessible(aClass, myPlace, myAccessClass); + return myResolveHelper.isAccessible(aClass, myPlace, myAccessClass); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index f16231ac8d26..6098199c591c 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -379,7 +379,7 @@ public class InferenceSession { PsiType returnType = method.getReturnType(); if (!PsiType.VOID.equals(returnType) && returnType != null) { PsiType targetType = getTargetType(context); - if (targetType != null) { + if (targetType != null && !PsiType.VOID.equals(targetType)) { registerReturnTypeConstraints(PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType), targetType); } } @@ -970,7 +970,8 @@ public class InferenceSession { addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, PsiSubstitutor.EMPTY, varargs), pType)); } } - else if (parameters.length + 1 == functionalMethodParameters.length && !varargs || !isStatic && varargs && functionalMethodParameters.length > 0) { //instance methods + else if (parameters.length + 1 == functionalMethodParameters.length && !varargs || + !isStatic && varargs && functionalMethodParameters.length > 0 && PsiMethodReferenceUtil.hasReceiver(reference, method)) { //instance methods initBounds(containingClass.getTypeParameters()); final PsiType pType = signature.getParameterTypes()[0]; @@ -1020,13 +1021,13 @@ public class InferenceSession { */ public static boolean isMoreSpecific(PsiMethod m1, PsiMethod m2, - PsiSubstitutor siteSubstitutor2, PsiExpression[] args, PsiElement context, boolean varargs) { - final PsiTypeParameter[] typeParameters = m2.getTypeParameters(); - - final InferenceSession session = new InferenceSession(typeParameters, siteSubstitutor2, m2.getManager(), context); + final InferenceSession session = new InferenceSession(PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, m2.getManager(), context); + for (PsiTypeParameter param : PsiUtil.typeParametersIterable(m2)) { + session.initBounds(param); + } final PsiParameter[] parameters1 = m1.getParameterList().getParameters(); final PsiParameter[] parameters2 = m2.getParameterList().getParameters(); @@ -1036,8 +1037,8 @@ public class InferenceSession { final int paramsLength = !varargs ? parameters1.length : parameters1.length - 1; for (int i = 0; i < paramsLength; i++) { - PsiType sType = getParameterType(parameters1, i, siteSubstitutor2, false); - PsiType tType = getParameterType(parameters2, i, siteSubstitutor2, varargs); + PsiType sType = getParameterType(parameters1, i, PsiSubstitutor.EMPTY, false); + PsiType tType = getParameterType(parameters2, i, PsiSubstitutor.EMPTY, varargs); if (session.isProperType(sType) && session.isProperType(tType)) { if (!TypeConversionUtil.isAssignable(tType, sType)) { return false; @@ -1054,8 +1055,8 @@ public class InferenceSession { } if (varargs) { - PsiType sType = getParameterType(parameters1, paramsLength, siteSubstitutor2, true); - PsiType tType = getParameterType(parameters2, paramsLength, siteSubstitutor2, true); + PsiType sType = getParameterType(parameters1, paramsLength, PsiSubstitutor.EMPTY, true); + PsiType tType = getParameterType(parameters2, paramsLength, PsiSubstitutor.EMPTY, true); session.addConstraint(new StrictSubtypingConstraint(tType, sType)); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java index 175f083ce319..18d0c49e79d4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java @@ -21,6 +21,7 @@ import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfacePa import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; import com.intellij.psi.infos.MethodCandidateInfo; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -60,6 +61,10 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm final PsiType interfaceMethodReturnType = interfaceMethod.getReturnType(); final PsiType returnType = substitutor.substitute(interfaceMethodReturnType); final PsiType[] typeParameters = myExpression.getTypeParameters(); + + final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression); + PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor(); + if (!myExpression.isExact()) { for (PsiParameter parameter : targetParameters) { if (!session.isProperType(substitutor.substitute(parameter.getType()))) { @@ -70,11 +75,9 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm final PsiMember applicableMember = myExpression.getPotentiallyApplicableMember(); LOG.assertTrue(applicableMember != null); - final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression); final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass(); final PsiClass containingClass = qualifierResolveResult.getContainingClass(); - PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor(); psiSubstitutor = applicableMemberContainingClass == null || containingClass == null || myExpression.isConstructor() ? psiSubstitutor : TypeConversionUtil.getSuperClassSubstitutor(applicableMemberContainingClass, containingClass, psiSubstitutor); @@ -143,6 +146,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm final PsiType referencedMethodReturnType; final PsiClass containingClass = method.getContainingClass(); LOG.assertTrue(containingClass != null, method); + + PsiClass qContainingClass = qualifierResolveResult.getContainingClass(); + if (qContainingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) { + psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, PsiSubstitutor.EMPTY); + LOG.assertTrue(psiSubstitutor != null); + } + if (method.isConstructor()) { referencedMethodReturnType = JavaPsiFacade.getElementFactory(method.getProject()).createType(containingClass, PsiSubstitutor.EMPTY); } @@ -179,7 +189,6 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm } int idx = 0; - PsiSubstitutor psiSubstitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter param : method.getTypeParameters()) { if (idx < typeParameters.length) { psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 4fbbad26964d..8d42dbeb4f90 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -84,8 +84,8 @@ public interface JavaElementType { IElementType PARAMETER_LIST = JavaStubElementTypes.PARAMETER_LIST; IElementType EXTENDS_BOUND_LIST = JavaStubElementTypes.EXTENDS_BOUND_LIST; IElementType THROWS_LIST = JavaStubElementTypes.THROWS_LIST; - IElementType LITERAL_EXPRESSION = new JavaCompositeElementType("LITERAL_EXPRESSION", PsiLiteralExpressionImpl.class); + IElementType LITERAL_EXPRESSION = new JavaCompositeElementType("LITERAL_EXPRESSION", PsiLiteralExpressionImpl.class); IElementType IMPORT_STATIC_REFERENCE = new JavaCompositeElementType("IMPORT_STATIC_REFERENCE", PsiImportStaticReferenceElementImpl.class); IElementType TYPE = new JavaCompositeElementType("TYPE", PsiTypeElementImpl.class); IElementType DIAMOND_TYPE = new JavaCompositeElementType("DIAMOND_TYPE", PsiDiamondTypeElementImpl.class); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java index 8cf5b5bfbdd2..e2af7b08df0d 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaSourceUtil.java @@ -15,13 +15,28 @@ */ package com.intellij.psi.impl.source.tree; +import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; +import com.intellij.lang.LighterAST; +import com.intellij.lang.LighterASTNode; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.impl.source.DummyHolder; import com.intellij.psi.impl.source.SourceJavaCodeReference; +import com.intellij.psi.impl.source.SourceTreeToPsiMap; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; import com.intellij.util.CharTable; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; public class JavaSourceUtil { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.JavaSourceUtil"); + + private static final TokenSet REF_FILTER = TokenSet.orSet( + ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET, TokenSet.create(JavaElementType.ANNOTATION)); + private JavaSourceUtil() { } public static void fullyQualifyReference(@NotNull CompositeElement reference, @NotNull PsiClass targetClass) { @@ -61,4 +76,70 @@ public class JavaSourceUtil { } } } + + @NotNull + public static String getReferenceText(@NotNull PsiJavaCodeReferenceElement ref) { + final StringBuilder buffer = new StringBuilder(); + + ((TreeElement)ref.getNode()).acceptTree(new RecursiveTreeElementWalkingVisitor() { + @Override + public void visitLeaf(LeafElement leaf) { + if (!REF_FILTER.contains(leaf.getElementType())) { + String leafText = leaf.getText(); + if (buffer.length() > 0 && !leafText.isEmpty() && Character.isJavaIdentifierPart(leafText.charAt(0))) { + char lastInBuffer = buffer.charAt(buffer.length() - 1); + if (lastInBuffer == '?' || Character.isJavaIdentifierPart(lastInBuffer)) { + buffer.append(" "); + } + } + + buffer.append(leafText); + } + } + + @Override + public void visitComposite(CompositeElement composite) { + if (!REF_FILTER.contains(composite.getElementType())) { + super.visitComposite(composite); + } + } + }); + + return buffer.toString(); + } + + @NotNull + public static String getReferenceText(@NotNull LighterAST tree, @NotNull LighterASTNode node) { + return LightTreeUtil.toFilteredString(tree, node, REF_FILTER); + } + + public static TreeElement addParenthToReplacedChild(@NotNull IElementType parenthType, + @NotNull TreeElement newChild, + @NotNull PsiManager manager) { + CompositeElement parenthExpr = ASTFactory.composite(parenthType); + + TreeElement dummyExpr = (TreeElement)newChild.clone(); + final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(newChild); + new DummyHolder(manager, parenthExpr, null, charTableByTree); + parenthExpr.putUserData(CharTable.CHAR_TABLE_KEY, charTableByTree); + parenthExpr.rawAddChildren(ASTFactory.leaf(JavaTokenType.LPARENTH, "(")); + parenthExpr.rawAddChildren(dummyExpr); + parenthExpr.rawAddChildren(ASTFactory.leaf(JavaTokenType.RPARENTH, ")")); + + try { + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); + PsiElement formatted = codeStyleManager.reformat(SourceTreeToPsiMap.treeToPsiNotNull(parenthExpr)); + parenthExpr = (CompositeElement)SourceTreeToPsiMap.psiToTreeNotNull(formatted); + } + catch (IncorrectOperationException e) { + LOG.error(e); // should not happen + } + + newChild.putUserData(CharTable.CHAR_TABLE_KEY, SharedImplUtil.findCharTableByTree(newChild)); + dummyExpr.getTreeParent().replaceChild(dummyExpr, newChild); + + // TODO remove explicit caches drop since this should be ok if we will use ChangeUtil for the modification + TreeUtil.clearCaches(TreeUtil.getFileElement(parenthExpr)); + return parenthExpr; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java index 93e9f60c890e..554580828c0b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,94 +15,29 @@ */ package com.intellij.psi.impl.source.tree; -import com.intellij.lang.ASTFactory; import com.intellij.lang.LighterAST; import com.intellij.lang.LighterASTNode; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiJavaCodeReferenceElement; import com.intellij.psi.PsiManager; -import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.impl.source.DummyHolder; -import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.TokenSet; -import com.intellij.util.CharTable; -import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; +/** @deprecated use {@link JavaSourceUtil} (to be removed in IDEA 15) */ +@SuppressWarnings("UnusedDeclaration") public class SourceUtil { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.SourceUtil"); - - private static final TokenSet REF_FILTER = TokenSet.orSet( - ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET, TokenSet.create(JavaElementType.ANNOTATION)); - private SourceUtil() { } @NotNull public static String getReferenceText(@NotNull PsiJavaCodeReferenceElement ref) { - final StringBuilder buffer = new StringBuilder(); - - ((TreeElement)ref.getNode()).acceptTree(new RecursiveTreeElementWalkingVisitor() { - @Override - public void visitLeaf(LeafElement leaf) { - if (!REF_FILTER.contains(leaf.getElementType())) { - String leafText = leaf.getText(); - if (buffer.length() > 0 && !leafText.isEmpty() && Character.isJavaIdentifierPart(leafText.charAt(0))) { - char lastInBuffer = buffer.charAt(buffer.length() - 1); - if (lastInBuffer == '?' || Character.isJavaIdentifierPart(lastInBuffer)) { - buffer.append(" "); - } - } - - buffer.append(leafText); - } - } - - @Override - public void visitComposite(CompositeElement composite) { - if (!REF_FILTER.contains(composite.getElementType())) { - super.visitComposite(composite); - } - } - }); - - return buffer.toString(); + return JavaSourceUtil.getReferenceText(ref); } @NotNull public static String getReferenceText(@NotNull LighterAST tree, @NotNull LighterASTNode node) { - return LightTreeUtil.toFilteredString(tree, node, REF_FILTER); + return JavaSourceUtil.getReferenceText(tree, node); } - public static TreeElement addParenthToReplacedChild(@NotNull IElementType parenthType, - @NotNull TreeElement newChild, - @NotNull PsiManager manager) { - CompositeElement parenthExpr = ASTFactory.composite(parenthType); - - TreeElement dummyExpr = (TreeElement)newChild.clone(); - final CharTable charTableByTree = SharedImplUtil.findCharTableByTree(newChild); - new DummyHolder(manager, parenthExpr, null, charTableByTree); - parenthExpr.putUserData(CharTable.CHAR_TABLE_KEY, charTableByTree); - parenthExpr.rawAddChildren(ASTFactory.leaf(JavaTokenType.LPARENTH, "(")); - parenthExpr.rawAddChildren(dummyExpr); - parenthExpr.rawAddChildren(ASTFactory.leaf(JavaTokenType.RPARENTH, ")")); - - try { - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(manager.getProject()); - PsiElement formatted = codeStyleManager.reformat(SourceTreeToPsiMap.treeToPsiNotNull(parenthExpr)); - parenthExpr = (CompositeElement)SourceTreeToPsiMap.psiToTreeNotNull(formatted); - } - catch (IncorrectOperationException e) { - LOG.error(e); // should not happen - } - - newChild.putUserData(CharTable.CHAR_TABLE_KEY, SharedImplUtil.findCharTableByTree(newChild)); - dummyExpr.getTreeParent().replaceChild(dummyExpr, newChild); - - // TODO remove explicit caches drop since this should be ok if we will use ChangeUtil for the modification - TreeUtil.clearCaches(TreeUtil.getFileElement(parenthExpr)); - return parenthExpr; + public static TreeElement addParenthToReplacedChild(@NotNull IElementType parenthType, @NotNull TreeElement newChild, @NotNull PsiManager manager) { + return JavaSourceUtil.addParenthToReplacedChild(parenthType, newChild, manager); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java index 1d8693efc55c..e0b122e95592 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ExpressionPsiElement.java @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; @@ -24,13 +20,11 @@ import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; +/** + * @author max + */ public class ExpressionPsiElement extends CompositePsiElement { - private final int myHC = CompositePsiElement.ourHC++; - - @Override - public final int hashCode() { - return myHC; - } + @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod") private final int myHC = CompositePsiElement.ourHC++; public ExpressionPsiElement(final IElementType type) { super(type); @@ -42,9 +36,14 @@ public class ExpressionPsiElement extends CompositePsiElement { ElementType.EXPRESSION_BIT_SET.contains(newElement.getElementType())) { boolean needParenth = ReplaceExpressionUtil.isNeedParenthesis(child, newElement); if (needParenth) { - newElement = SourceUtil.addParenthToReplacedChild(JavaElementType.PARENTH_EXPRESSION, newElement, getManager()); + newElement = JavaSourceUtil.addParenthToReplacedChild(JavaElementType.PARENTH_EXPRESSION, newElement, getManager()); } } super.replaceChildInternal(child, newElement); } + + @Override + public final int hashCode() { + return myHC; + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodElement.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodElement.java index 31fb4bca8833..1edd7cbaec76 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodElement.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/MethodElement.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,14 +41,15 @@ public class MethodElement extends CompositeElement implements Constants { @Override public int getTextOffset() { - return findChildByRole(ChildRole.NAME).getStartOffset(); + ASTNode name = findChildByType(IDENTIFIER); + return name != null ? name.getStartOffset() : this.getStartOffset(); } @Override public TreeElement addInternal(TreeElement first, ASTNode last, ASTNode anchor, Boolean before) { - if (first == last && first.getElementType() == JavaElementType.CODE_BLOCK){ - ASTNode semicolon = findChildByRole(ChildRole.CLOSING_SEMICOLON); - if (semicolon != null){ + if (first == last && first.getElementType() == JavaElementType.CODE_BLOCK) { + ASTNode semicolon = TreeUtil.findChildBackward(this, SEMICOLON); + if (semicolon != null) { deleteChildInternal(semicolon); } } @@ -64,7 +65,7 @@ public class MethodElement extends CompositeElement implements Constants { @Override public void deleteChildInternal(@NotNull ASTNode child) { - if (child.getElementType() == CODE_BLOCK){ + if (child.getElementType() == CODE_BLOCK) { final ASTNode prevWS = TreeUtil.prevLeaf(child); if (prevWS != null && prevWS.getElementType() == TokenType.WHITE_SPACE) { removeChild(prevWS); @@ -80,9 +81,9 @@ public class MethodElement extends CompositeElement implements Constants { } @Override - public ASTNode findChildByRole(int role){ + public ASTNode findChildByRole(int role) { LOG.assertTrue(ChildRole.isUnique(role)); - switch(role){ + switch (role) { default: return null; @@ -161,5 +162,4 @@ public class MethodElement extends CompositeElement implements Constants { protected boolean isVisibilitySupported() { return true; } - } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 2209efe4141b..95171ba30bc9 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -434,7 +434,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase return true; } - final PsiSubstitutor subst = result.getSubstitutor(); + PsiSubstitutor subst = result.getSubstitutor(); PsiType methodReturnType = null; PsiClass containingClass = null; @@ -451,6 +451,12 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase return false; } + PsiClass qContainingClass = PsiMethodReferenceUtil.getQualifierResolveResult(this).getContainingClass(); + if (qContainingClass != null && containingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) { + subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst); + LOG.assertTrue(subst != null); + } + methodReturnType = subst.substitute(returnType); } else if (resolve instanceof PsiClass) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPackageStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPackageStatementImpl.java index 5a42715590ef..29d072970560 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPackageStatementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiPackageStatementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +38,7 @@ public class PsiPackageStatementImpl extends CompositePsiElement implements PsiP @Override public String getPackageName() { PsiJavaCodeReferenceElement ref = getPackageReference(); - return ref == null ? null : SourceUtil.getReferenceText(ref); + return ref == null ? null : JavaSourceUtil.getReferenceText(ref); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java index 02ffaa6f3c20..8dd43933c660 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java @@ -761,7 +761,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple private String getCachedNormalizedText() { String whiteSpaceAndComments = myCachedNormalizedText; if (whiteSpaceAndComments == null) { - myCachedNormalizedText = whiteSpaceAndComments = SourceUtil.getReferenceText(this); + myCachedNormalizedText = whiteSpaceAndComments = JavaSourceUtil.getReferenceText(this); } return whiteSpaceAndComments; } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index f136c843aa87..59083c625f82 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -550,10 +550,10 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel); - boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2, siteSubstitutor1); + boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2); final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel); - boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1, siteSubstitutor2); + boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1); if (!myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { final boolean typeArgsApplicable12 = GenericsUtil.isTypeArgumentsApplicable(typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21); @@ -604,9 +604,9 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ if (toCompareFunctional) { final boolean applicable12ignoreFunctionalType = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, - calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null, null); + calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null); final boolean applicable21ignoreFunctionalType = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, - calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null, null); + calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null); if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) { Specifics specifics = null; @@ -694,12 +694,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ @NotNull LanguageLevel languageLevel, boolean varargsPosition, @NotNull PsiSubstitutor methodSubstitutor1, - PsiMethod method2, - PsiSubstitutor siteSubstitutor1) { + PsiMethod method2) { if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && method2 != null && method1.getTypeParameters().length > 0 && myArgumentsList instanceof PsiExpressionList) { final PsiElement parent = myArgumentsList.getParent(); if (parent instanceof PsiCallExpression && ((PsiCallExpression)parent).getTypeArguments().length == 0) { - return InferenceSession.isMoreSpecific(method2, method1, siteSubstitutor1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition); + return InferenceSession.isMoreSpecific(method2, method1, ((PsiExpressionList)myArgumentsList).getExpressions(), myArgumentsList, varargsPosition); } } final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method1, methodSubstitutor1, types2AtSite, languageLevel, false, varargsPosition); |