diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2013-02-27 09:41:48 -0800 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2013-02-27 09:41:48 -0800 |
commit | 1d526b16d476792ca7ce47616d55833115e8d6ab (patch) | |
tree | 650fb03af01ff04097d1d59939518cc71be029cb /java/java-impl/src/com/intellij | |
parent | 9edc8f6b58f71ec510ba36b838f115718d9a174d (diff) | |
download | idea-1d526b16d476792ca7ce47616d55833115e8d6ab.tar.gz |
Snapshot of commit 329607d9ebcedf2bb0ad81265354366db7dc3f9c
from branch master of git://git.jetbrains.org/idea/community.git
Change-Id: I3b27d82897504da1b66169b67c7771e0f551c973
Diffstat (limited to 'java/java-impl/src/com/intellij')
88 files changed, 3305 insertions, 873 deletions
diff --git a/java/java-impl/src/com/intellij/analysis/AnalysisScopeRule.java b/java/java-impl/src/com/intellij/analysis/AnalysisScopeRule.java index bf6f2da56695..4b85d51d0631 100644 --- a/java/java-impl/src/com/intellij/analysis/AnalysisScopeRule.java +++ b/java/java-impl/src/com/intellij/analysis/AnalysisScopeRule.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.LangDataKeys; import com.intellij.openapi.module.Module; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.PsiManager; import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; @@ -39,8 +40,9 @@ public class AnalysisScopeRule implements GetDataRule { Object psiTarget = dataProvider.getData(LangDataKeys.PSI_ELEMENT.getName()); if (psiTarget instanceof PsiPackage) { PsiPackage pack = (PsiPackage)psiTarget; - if (!pack.getManager().isInProject(pack)) return null; - PsiDirectory[] dirs = pack.getDirectories(GlobalSearchScope.projectScope(pack.getProject())); + PsiManager manager = pack.getManager(); + if (!manager.isInProject(pack)) return null; + PsiDirectory[] dirs = pack.getDirectories(GlobalSearchScope.projectScope(manager.getProject())); if (dirs.length == 0) return null; return new JavaAnalysisScope(pack, (Module)dataProvider.getData(LangDataKeys.MODULE.getName())); } diff --git a/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java b/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java new file mode 100644 index 000000000000..b9be30108002 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/ConditionCheckManager.java @@ -0,0 +1,239 @@ +/* + * Copyright 2000-2013 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; + +import com.intellij.openapi.components.*; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a> + * Creation Date: 8/3/12 + */ +@State( + name = "ConditionCheckManager", + storages = {@Storage(id = "dir", file = StoragePathMacros.PROJECT_CONFIG_DIR + "/checker.xml", scheme = StorageScheme.DIRECTORY_BASED)} +) +public class ConditionCheckManager implements PersistentStateComponent<ConditionCheckManager.State> { + @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) private State state; + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheckManager"); + + private List<ConditionChecker> myIsNullCheckMethods = new ArrayList<ConditionChecker>(); + private List<ConditionChecker> myIsNotNullCheckMethods = new ArrayList<ConditionChecker>(); + + private List<ConditionChecker> myAssertIsNullMethods = new ArrayList<ConditionChecker>(); + private List<ConditionChecker> myAssertIsNotNullMethods = new ArrayList<ConditionChecker>(); + + private List<ConditionChecker> myAssertTrueMethods = new ArrayList<ConditionChecker>(); + private List<ConditionChecker> myAssertFalseMethods = new ArrayList<ConditionChecker>(); + + public static ConditionCheckManager getInstance(Project project) { + return ServiceManager.getService(project, ConditionCheckManager.class); + } + + public void setIsNullCheckMethods(List<ConditionChecker> methodConditionChecks) { + myIsNullCheckMethods.clear(); + myIsNullCheckMethods.addAll(methodConditionChecks); + } + + public void setIsNotNullCheckMethods(List<ConditionChecker> methodConditionChecks) { + myIsNotNullCheckMethods.clear(); + myIsNotNullCheckMethods.addAll(methodConditionChecks); + } + + public void setAssertIsNullMethods(List<ConditionChecker> methodConditionChecks) { + myAssertIsNullMethods.clear(); + myAssertIsNullMethods.addAll(methodConditionChecks); + } + + public void setAssertIsNotNullMethods(List<ConditionChecker> methodConditionChecks) { + myAssertIsNotNullMethods.clear(); + myAssertIsNotNullMethods.addAll(methodConditionChecks); + } + + public void setAssertTrueMethods(List<ConditionChecker> psiMethodWrappers) { + myAssertTrueMethods.clear(); + myAssertTrueMethods.addAll(psiMethodWrappers); + } + + public void setAssertFalseMethods(List<ConditionChecker> psiMethodWrappers) { + myAssertFalseMethods.clear(); + myAssertFalseMethods.addAll(psiMethodWrappers); + } + + public List<ConditionChecker> getIsNullCheckMethods() { + return myIsNullCheckMethods; + } + + public List<ConditionChecker> getIsNotNullCheckMethods() { + return myIsNotNullCheckMethods; + } + + public List<ConditionChecker> getAssertIsNullMethods() { + return myAssertIsNullMethods; + } + + public List<ConditionChecker> getAssertIsNotNullMethods() { + return myAssertIsNotNullMethods; + } + + public List<ConditionChecker> getAssertFalseMethods() { + return myAssertFalseMethods; + } + + public List<ConditionChecker> getAssertTrueMethods() { + return myAssertTrueMethods; + } + + public static class State { + public List<String> myIsNullCheckMethods = new ArrayList<String>(); + public List<String> myIsNotNullCheckMethods = new ArrayList<String>(); + public List<String> myAssertIsNullMethods = new ArrayList<String>(); + public List<String> myAssertIsNotNullMethods = new ArrayList<String>(); + public List<String> myAssertTrueMethods = new ArrayList<String>(); + public List<String> myAssertFalseMethods = new ArrayList<String>(); + } + + @Override + public State getState() { + State state = new State(); + + loadMethodChecksToState(state.myIsNullCheckMethods, myIsNullCheckMethods); + loadMethodChecksToState(state.myIsNotNullCheckMethods, myIsNotNullCheckMethods); + loadMethodChecksToState(state.myAssertIsNullMethods, myAssertIsNullMethods); + loadMethodChecksToState(state.myAssertIsNotNullMethods, myAssertIsNotNullMethods); + loadMethodChecksToState(state.myAssertTrueMethods, myAssertTrueMethods); + loadMethodChecksToState(state.myAssertFalseMethods, myAssertFalseMethods); + + return state; + } + + private static void loadMethodChecksToState(List<String> listToLoadTo, List<ConditionChecker> listToLoadFrom) { + for (ConditionChecker checker : listToLoadFrom) { + listToLoadTo.add(checker.toString()); + } + } + + @Override + public void loadState(State state) { + this.state = state; + loadMethods(myIsNullCheckMethods, state.myIsNullCheckMethods, ConditionChecker.Type.IS_NULL_METHOD); + loadMethods(myIsNotNullCheckMethods, state.myIsNotNullCheckMethods, ConditionChecker.Type.IS_NOT_NULL_METHOD); + loadMethods(myAssertIsNullMethods, state.myAssertIsNullMethods, ConditionChecker.Type.ASSERT_IS_NULL_METHOD); + loadMethods(myAssertIsNotNullMethods, state.myAssertIsNotNullMethods, ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD); + loadMethods(myAssertTrueMethods, state.myAssertTrueMethods, ConditionChecker.Type.ASSERT_TRUE_METHOD); + loadMethods(myAssertFalseMethods, state.myAssertFalseMethods, ConditionChecker.Type.ASSERT_FALSE_METHOD); + } + + public void loadMethods(List<ConditionChecker> listToLoadTo, List<String> listToLoadFrom, ConditionChecker.Type type){ + listToLoadTo.clear(); + for (String setting : listToLoadFrom) { + try { + listToLoadTo.add(new ConditionChecker.FromConfigBuilder(setting, type).build()); + } catch (Exception e) { + LOG.error("Problem occurred while attempting to load Condition Check from configuration file. " + e.getMessage()); + } + } + } + + public static boolean isMethod(@NotNull PsiMethod psiMethod, List<ConditionChecker> checkers) { + for (ConditionChecker checker : checkers) { + if (checker.matchesPsiMethod(psiMethod)) { + return true; + } + } + return false; + } + + public static boolean isCheck(PsiMethod psiMethod) { + ConditionCheckManager manager = getInstance(psiMethod.getProject()); + return isMethod(psiMethod, manager.getIsNullCheckMethods()) || + isMethod(psiMethod, manager.getIsNotNullCheckMethods()) || + isMethod(psiMethod, manager.getAssertIsNullMethods()) || + isMethod(psiMethod, manager.getAssertIsNotNullMethods()) || + isAssertTrueCheckMethod(psiMethod) || + isAssertFalseCheckMethod(psiMethod); + } + + public static boolean isNullCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNullCheckMethods()); + } + + public static boolean isNotNullCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods()); + } + + public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNullMethods()); + } + + public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods()); + } + + public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertTrueMethods()); + } + + public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod) { + return methodMatches(psiMethod, getInstance(psiMethod.getProject()).getAssertFalseMethods()); + } + + public static boolean isNullCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNullCheckMethods()); + } + + public static boolean isNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getIsNotNullCheckMethods()); + } + + public static boolean isAssertIsNullCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNullMethods()); + } + + public static boolean isAssertIsNotNullCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertIsNotNullMethods()); + } + + public static boolean isAssertTrueCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertTrueMethods()); + } + + public static boolean isAssertFalseCheckMethod(PsiMethod psiMethod, int paramIndex) { + return methodMatches(psiMethod, paramIndex, getInstance(psiMethod.getProject()).getAssertFalseMethods()); + } + + public static boolean methodMatches(PsiMethod psiMethod, List<ConditionChecker> checkers) { + for (ConditionChecker checker : checkers) { + if (checker.matchesPsiMethod(psiMethod)) + return true; + } + return false; + } + + public static boolean methodMatches(PsiMethod psiMethod, int paramIndex, List<ConditionChecker> checkers) { + for (ConditionChecker checker : checkers) { + if (checker.matchesPsiMethod(psiMethod, paramIndex)) + return true; + } + return false; + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/ConditionChecker.java b/java/java-impl/src/com/intellij/codeInsight/ConditionChecker.java new file mode 100644 index 000000000000..de3871d0e61b --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/ConditionChecker.java @@ -0,0 +1,431 @@ +/* + * Copyright 2000-2013 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; + +import com.intellij.openapi.diagnostic.*; +import com.intellij.psi.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.util.*; + + +/** + * Used by Constant Condition Inspection to identify methods which perform some type of Validation on the parameters passed into them. + * For example given the following method + * <pre> + * {@code + * class Foo { + * static boolean validateNotNull(Object o) { + * if (o == null) return false; + * else return true; + * } + * } + * } + * + * The corresponding ConditionCheck would be <p/> + * myConditionCheckType=Type.IS_NOT_NULL_METHOD + * myClassName=Foo + * myMethodName=validateNotNull + * myPsiParameter=o + * + * The following block of code would produce a Inspection Warning that o is always true + * + * <pre> + * {@code + * if (Value.isNotNull(o)) { + * if(o != null) {} + * } + * } + * </pre> + * + * @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a> + * Creation Date: 8/14/12 + */ +public class ConditionChecker implements Serializable { + private final @NotNull Type myConditionCheckType; + + public enum Type { + IS_NULL_METHOD("IsNull Method"), + IS_NOT_NULL_METHOD("IsNotNull Method"), + ASSERT_IS_NULL_METHOD("Assert IsNull Method"), + ASSERT_IS_NOT_NULL_METHOD("Assert IsNotNull Method"), + ASSERT_TRUE_METHOD("Assert True Method"), + ASSERT_FALSE_METHOD("Assert False Method"); + private final String myStringRepresentation; + + Type(String stringRepresentation) { + myStringRepresentation = stringRepresentation; + } + + @Override + public String toString() { + return myStringRepresentation; + } + } + + private final @NotNull String myClassName; + private final @NotNull String myMethodName; + private final @NotNull List<String> myParameterClassList; + private final int myCheckedParameterIndex; + private final String myFullName; + + private ConditionChecker(@NotNull String className, + @NotNull String methodName, + @NotNull List<String> parameterClassList, + int checkedParameterIndex, + @NotNull Type type, + @NotNull String fullName) { + checkState(!className.isEmpty(), "Class Name is blank"); + checkState(!methodName.isEmpty(), "Method Name is blank"); + checkState(!parameterClassList.isEmpty(), "Parameter Class List is empty"); + checkState(checkedParameterIndex >= 0, "CheckedParameterIndex must be greater than or equal to zero"); + checkState(parameterClassList.size() >= checkedParameterIndex, "CheckedParameterIndex is greater than Parameter Class List's size"); + checkState(!fullName.isEmpty(), "Method Name is blank"); + + myConditionCheckType = type; + myClassName = className; + myMethodName = methodName; + myParameterClassList = parameterClassList; + myCheckedParameterIndex = checkedParameterIndex; + myFullName = fullName; + } + + private static void checkState(boolean condition, String errorMsg) { + if (!condition) throw new IllegalArgumentException(errorMsg); + } + + public static String getFullyQualifiedName(PsiParameter psiParameter) { + PsiTypeElement typeElement = psiParameter.getTypeElement(); + if (typeElement == null) throw new RuntimeException("Parameter has null typeElement " + psiParameter.getName()); + + PsiType psiType = typeElement.getType(); + + return psiType.getCanonicalText(); + } + + public boolean matchesPsiMethod(PsiMethod psiMethod) { + if (!myMethodName.equals(psiMethod.getName())) return false; + + PsiClass containingClass = psiMethod.getContainingClass(); + if (containingClass == null) return false; + + String qualifiedName = containingClass.getQualifiedName(); + if (qualifiedName == null) return false; + + if (!myClassName.equals(qualifiedName)) return false; + + PsiParameterList psiParameterList = psiMethod.getParameterList(); + if (myParameterClassList.size() != psiParameterList.getParameters().length) return false; + + for (int i = 0; i < psiParameterList.getParameters().length; i++) { + PsiParameter psiParameter = psiParameterList.getParameters()[i]; + PsiTypeElement psiTypeElement = psiParameter.getTypeElement(); + if (psiTypeElement == null) return false; + + PsiType psiType = psiTypeElement.getType(); + String parameterCanonicalText = psiType.getCanonicalText(); + String myParameterCanonicalText = myParameterClassList.get(i); + if (!myParameterCanonicalText.equals(parameterCanonicalText)) return false; + } + + return true; + } + + public boolean matchesPsiMethod(PsiMethod psiMethod, int paramIndex) { + if (matchesPsiMethod(psiMethod) && paramIndex == myCheckedParameterIndex) return true; + + return false; + } + + public boolean overlaps(ConditionChecker otherChecker) { + if (myClassName.equals(otherChecker.myClassName) && + myMethodName.equals(otherChecker.myMethodName) && + myParameterClassList.equals(otherChecker.myParameterClassList) && + myCheckedParameterIndex == otherChecker.myCheckedParameterIndex) { + return true; + } + + return false; + } + + @NotNull + public Type getConditionCheckType() { + return myConditionCheckType; + } + + @NotNull + public String getClassName() { + return myClassName; + } + + @NotNull + public String getMethodName() { + return myMethodName; + } + + public int getCheckedParameterIndex() { + return myCheckedParameterIndex; + } + + public String getFullName() { + return myFullName; + } + + /** + * In addition to normal duties, this controls the manner in which the ConditionCheck appears in the ConditionCheckDialog.MethodsPanel + */ + @Override + public String toString() { + return myFullName; + } + + private static class Builder { + + static String initFullName(String className, + String methodName, + List<String> parameterClasses, + List<String> parameterNames, + int checkedParameterIndex) { + String s = className + "." + methodName + "("; + int index = 0; + for (String parameterClass : parameterClasses) { + String parameterClassAndName = parameterClass + " " + parameterNames.get(index); + if (index == checkedParameterIndex) parameterClassAndName = "*" + parameterClassAndName + "*"; + + s += parameterClassAndName + ", "; + index++; + } + s = s.substring(0, s.length() - 2); + s += ")"; + return s; + } + } + + static class FromConfigBuilder extends Builder { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheck.FromConfigBuilder"); + private final @NotNull String serializedRepresentation; + private final @NotNull Type type; + + FromConfigBuilder(@NotNull String serializedRepresentation, @NotNull Type type) { + this.serializedRepresentation = serializedRepresentation; + this.type = type; + } + + private String parseClassAndMethodName() { + if (!serializedRepresentation.contains("(")) { + throw new IllegalArgumentException("Name should contain a opening parenthesis. " + serializedRepresentation); + } + else if (!serializedRepresentation.contains(")")) { + throw new IllegalArgumentException("Name should contain a closing parenthesis. " + serializedRepresentation); + } + else if (serializedRepresentation.indexOf("(", serializedRepresentation.indexOf("(") + 1) > -1) { + throw new IllegalArgumentException("Name should only contain one opening parenthesis. " + serializedRepresentation); + } + else if (serializedRepresentation.indexOf(")", serializedRepresentation.indexOf(")") + 1) > -1) { + throw new IllegalArgumentException("Name should only contain one closing parenthesis. " + serializedRepresentation); + } + else if (serializedRepresentation.indexOf(")") < serializedRepresentation.indexOf("(")) { + throw new IllegalArgumentException("Opening parenthesis should precede closing parenthesis. " + serializedRepresentation); + } + + String classAndMethodName = serializedRepresentation.substring(0, serializedRepresentation.indexOf("(")); + if (!classAndMethodName.contains(".")) { + throw new IllegalArgumentException( + "Name should contain a dot between the class name and method name (before the opening parenthesis). " + + serializedRepresentation); + } + return classAndMethodName; + } + + @Nullable + public ConditionChecker build() { + try { + String classAndMethodName = parseClassAndMethodName(); + + String className = classAndMethodName.substring(0, classAndMethodName.lastIndexOf(".")); + String methodName = classAndMethodName.substring(classAndMethodName.lastIndexOf(".") + 1); + + String allParametersSubString = + serializedRepresentation.substring(serializedRepresentation.indexOf("(") + 1, serializedRepresentation.lastIndexOf(")")).trim(); + if (allParametersSubString.isEmpty()) { + throw new IllegalArgumentException( + "Name should contain 1+ parameter (between opening and closing parenthesis). " + serializedRepresentation); + } + else if (allParametersSubString.contains("*") && allParametersSubString.indexOf("*") == allParametersSubString.lastIndexOf("*")) { + throw new IllegalArgumentException("Selected Parameter should be surrounded by asterisks. " + serializedRepresentation); + } + + List<String> parameterClasses = new ArrayList<String>(); + List<String> parameterNames = new ArrayList<String>(); + int checkParameterIndex = -1; + int index = 0; + for (String parameterClassAndName : allParametersSubString.split(",")) { + parameterClassAndName = parameterClassAndName.trim(); + if (parameterClassAndName.startsWith("*") && parameterClassAndName.endsWith("*")) { + checkParameterIndex = index; + parameterClassAndName = parameterClassAndName.substring(1, parameterClassAndName.length() - 1); + } + + String[] parameterClassAndNameSplit = parameterClassAndName.split(" "); + String parameterClass = parameterClassAndNameSplit[0]; + String parameterName = parameterClassAndNameSplit[1]; + parameterClasses.add(parameterClass); + parameterNames.add(parameterName); + index++; + } + String fullName = initFullName(className, methodName, parameterClasses, parameterNames, checkParameterIndex); + return new ConditionChecker(className, methodName, parameterClasses, checkParameterIndex, type, fullName); + } + catch (Exception e) { + LOG.error("An Exception occurred while attempting to build ConditionCheck for Serialized String '" + + serializedRepresentation + + "' and Type '" + + type + + "'", e); + return null; + } + } + } + + public static class FromPsiBuilder extends Builder { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.ConditionCheck.FromPsiBuilder"); + private final @NotNull PsiMethod psiMethod; + private final @NotNull PsiParameter psiParameter; + private final @NotNull Type type; + + public FromPsiBuilder(@NotNull PsiMethod psiMethod, @NotNull PsiParameter psiParameter, @NotNull Type type) { + this.psiMethod = psiMethod; + this.psiParameter = psiParameter; + this.type = type; + } + + private static void validatePsiMethodHasContainingClass(PsiMethod psiMethod) { + PsiElement psiElement = psiMethod.getContainingClass(); + if (!(psiElement instanceof PsiClass)) { + throw new IllegalArgumentException("PsiMethod " + psiMethod + " can not have a null containing class."); + } + } + + private static void validatePsiMethodReturnTypeForNonAsserts(PsiMethod psiMethod, Type type) { + PsiType returnType = psiMethod.getReturnType(); + if (isAssert(type)) return; + + if (returnType == null) throw new IllegalArgumentException("PsiMethod " + psiMethod + " has a null return type PsiType."); + + if (returnType != PsiType.BOOLEAN && !returnType.getCanonicalText().equals(Boolean.class.toString())) { + throw new IllegalArgumentException("PsiMethod " + psiMethod + " must have a null return type PsiType of boolean or Boolean."); + } + } + + private static void validatePsiParameterExistsInPsiMethod(PsiMethod psiMethod, PsiParameter psiParameter) { + boolean parameterFound = false; + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (PsiParameter parameter : parameters) { + if (psiParameter.equals(parameter)) { + parameterFound = true; + break; + } + } + + if (!parameterFound) { + throw new IllegalArgumentException("PsiMethod " + psiMethod + " must have parameter " + getFullyQualifiedName(psiParameter)); + } + } + + private static boolean isAssert(Type type) { + return type == Type.ASSERT_IS_NULL_METHOD || + type == Type.ASSERT_IS_NOT_NULL_METHOD || + type == Type.ASSERT_TRUE_METHOD || + type == Type.ASSERT_FALSE_METHOD; + } + + private static String initClassNameFromPsiMethod(PsiMethod psiMethod) { + PsiElement psiElement = psiMethod.getContainingClass(); + PsiClass psiClass = (PsiClass)psiElement; + if (psiClass == null) throw new IllegalStateException("PsiClass is null"); + + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null || qualifiedName.isEmpty()) throw new IllegalStateException("Qualified Name is Blank"); + return qualifiedName; + } + + private static String initMethodNameFromPsiMethod(PsiMethod psiMethod) { + return psiMethod.getName(); + } + + private static List<String> initParameterClassListFromPsiMethod(PsiMethod psiMethod) { + List<String> parameterClasses = new ArrayList<String>(); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (PsiParameter param : parameters) { + PsiTypeElement typeElement = param.getTypeElement(); + if (typeElement == null) throw new RuntimeException("Parameter has null typeElement " + param.getName()); + + PsiType psiType = typeElement.getType(); + + parameterClasses.add(psiType.getCanonicalText()); + } + return parameterClasses; + } + + private static List<String> initParameterNameListFromPsiMethod(PsiMethod psiMethod) { + List<String> parameterNames = new ArrayList<String>(); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (PsiParameter param : parameters) { + parameterNames.add(param.getName()); + } + return parameterNames; + } + + private static int initCheckedParameterIndex(PsiMethod psiMethod, PsiParameter psiParameterToFind) { + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (int i = 0; i < parameters.length; i++) { + PsiParameter param = parameters[i]; + if (param.equals(psiParameterToFind)) return i; + } + throw new IllegalStateException(); + } + + private void validateConstructorArgs(PsiMethod psiMethod, PsiParameter psiParameter) { + validatePsiMethodHasContainingClass(psiMethod); + validatePsiMethodReturnTypeForNonAsserts(psiMethod, type); + validatePsiParameterExistsInPsiMethod(psiMethod, psiParameter); + } + + @Nullable + public ConditionChecker build() { + try { + validateConstructorArgs(psiMethod, psiParameter); + + String className = initClassNameFromPsiMethod(psiMethod); + String methodName = initMethodNameFromPsiMethod(psiMethod); + List<String> parameterClassList = initParameterClassListFromPsiMethod(psiMethod); + List<String> parameterNameList = initParameterNameListFromPsiMethod(psiMethod); + int checkedParameterIndex = initCheckedParameterIndex(psiMethod, psiParameter); + String fullName = initFullName(className, methodName, parameterClassList, parameterNameList, checkedParameterIndex); + return new ConditionChecker(className, methodName, parameterClassList, checkedParameterIndex, type, fullName); + } + catch (Exception e) { + LOG.error("An Exception occurred while attempting to build ConditionCheck for PsiMethod '" + psiMethod + + "' PsiParameter='" + psiParameter + "' " + + "' and Type '" + + type + + "'", e); + return null; + } + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInsight/TailTypes.java b/java/java-impl/src/com/intellij/codeInsight/TailTypes.java index 43def9006a28..923dd8213019 100644 --- a/java/java-impl/src/com/intellij/codeInsight/TailTypes.java +++ b/java/java-impl/src/com/intellij/codeInsight/TailTypes.java @@ -118,24 +118,10 @@ public class TailTypes { return styleSettings.SPACE_WITHIN_IF_PARENTHESES; } }; - public static final TailType FINALLY_LBRACE = new BracesTailType() { - @Override - protected boolean isSpaceBeforeLBrace(final CommonCodeStyleSettings styleSettings, final Editor editor, final int tailOffset) { - return styleSettings.SPACE_BEFORE_FINALLY_LBRACE; - } - }; - public static final TailType TRY_LBRACE = new BracesTailType() { - @Override - protected boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, int tailOffset) { - return styleSettings.SPACE_BEFORE_TRY_LBRACE; - } - }; - public static final TailType DO_LBRACE = new BracesTailType() { - @Override - protected boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, int tailOffset) { - return styleSettings.SPACE_BEFORE_DO_LBRACE; - } - }; + private static final TailType BRACES = new BracesTailType(); + public static final TailType FINALLY_LBRACE = BRACES; + public static final TailType TRY_LBRACE = BRACES; + public static final TailType DO_LBRACE = BRACES; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ClassByNameMerger.java b/java/java-impl/src/com/intellij/codeInsight/completion/ClassByNameMerger.java index c17677ef3476..5496bb1afd5e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ClassByNameMerger.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ClassByNameMerger.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.util.Consumer; @@ -28,8 +29,8 @@ public class ClassByNameMerger implements Consumer<LookupElement> { private final boolean myShouldMerge; private final CompletionResultSet myResult; - public ClassByNameMerger(boolean shouldMerge, CompletionResultSet result) { - myShouldMerge = shouldMerge; + public ClassByNameMerger(CompletionParameters parameters, CompletionResultSet result) { + myShouldMerge = parameters.getInvocationCount() == 0 && CodeInsightSettings.getInstance().SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS; myResult = result; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java index 6d0b45fff5c4..eb19c574c872 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaChainLookupElement.java @@ -15,10 +15,7 @@ */ package com.intellij.codeInsight.completion; -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.codeInsight.lookup.LookupElementDecorator; -import com.intellij.codeInsight.lookup.LookupElementPresentation; -import com.intellij.codeInsight.lookup.TypedLookupItem; +import com.intellij.codeInsight.lookup.*; import com.intellij.diagnostic.LogMessageEx; import com.intellij.diagnostic.errordialog.Attachment; import com.intellij.openapi.diagnostic.Logger; @@ -97,8 +94,9 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement final String qualifierText = myQualifier.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null ? "(" + name + ")" : name; presentation.setItemText(qualifierText + "." + presentation.getItemText()); - if (getQualifierObject() instanceof PsiClass) { - presentation.setTailText(StringUtil.notNullize(presentation.getTailText()) + qualifierPresentation.getTailText()); + if (myQualifier instanceof LookupItem && getQualifierObject() instanceof PsiClass) { + String locationString = JavaPsiClassReferenceElement.getLocationString((LookupItem)myQualifier); + presentation.setTailText(StringUtil.notNullize(presentation.getTailText()) + locationString); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java index efc621014690..b8a5c34c3b11 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCharFilter.java @@ -32,9 +32,7 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; -import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; public class JavaCharFilter extends CharFilter { @@ -43,45 +41,6 @@ public class JavaCharFilter extends CharFilter { return psiElement != null && psiElement.getParent() instanceof PsiLiteralExpression; } - public static boolean isNonImportedClassEntered(LookupImpl lookup, boolean orPackage) { - if (lookup.isSelectionTouched()) return false; - - CompletionProcess process = CompletionService.getCompletionService().getCurrentCompletion(); - if (process != null && !process.isAutopopupCompletion()) return false; - - LookupElement item = lookup.getCurrentItem(); - if (item == null) return false; - - PsiFile file = lookup.getPsiFile(); - if (file == null) return false; - - final String prefix = lookup.itemPattern(item); - for (PsiClass aClass : PsiShortNamesCache.getInstance(file.getProject()).getClassesByName(prefix, file.getResolveScope())) { - if (!isObfuscated(aClass) && PsiUtil.isAccessible(aClass, file, null)) { - return true; - } - } - - if (orPackage && prefix.length() > 1 && JavaPsiFacade.getInstance(file.getProject()).findPackage(prefix) != null) { - return true; - } - - return false; - } - - private static boolean isObfuscated(PsiClass psiClass) { - if (!(psiClass instanceof PsiCompiledElement)) { - return false; - } - - String name = psiClass.getName(); - if (name == null) { - return false; - } - - return name.length() <= 2 && Character.isLowerCase(name.charAt(0)); - } - @Override public Result acceptChar(char c, final int prefixLength, final Lookup lookup) { if (!lookup.getPsiFile().getLanguage().isKindOf(JavaLanguage.INSTANCE)) { @@ -116,11 +75,7 @@ public class JavaCharFilter extends CharFilter { return Result.HIDE_LOOKUP; } - if ((c == '[' || c == '<' || c == '.' || c == ' ' || c == '(' || c == ',') && - isNonImportedClassEntered((LookupImpl)lookup, c == '.')) { - return Result.HIDE_LOOKUP; - } - + if (c == '[') return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '<' && o instanceof PsiClass) return Result.SELECT_ITEM_AND_FINISH_LOOKUP; if (c == '(') { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java index d7ec101eb9f8..b0309da46d85 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionStatistician.java @@ -21,6 +21,10 @@ import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.psi.*; import com.intellij.psi.statistics.JavaStatisticsManager; import com.intellij.psi.statistics.StatisticsInfo; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.util.containers.ContainerUtil; + +import java.util.List; /** * @author peter @@ -48,18 +52,21 @@ public class JavaCompletionStatistician extends CompletionStatistician{ return new StatisticsInfo(JavaStatisticsManager.getAfterNewKey(expectedType), key2); } - if (o instanceof PsiMethod) { - o = RecursionWeigher.findDeepestSuper((PsiMethod)o); - } - PsiClass containingClass = ((PsiMember)o).getContainingClass(); if (containingClass != null) { - if (o instanceof PsiMethod && "getClass".equals(((PsiMethod) o).getName()) && - CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) { - return StatisticsInfo.EMPTY; + String context = JavaStatisticsManager.getMemberUseKey2(containingClass); + + if (o instanceof PsiMethod) { + String memberValue = JavaStatisticsManager.getMemberUseKey2(RecursionWeigher.findDeepestSuper((PsiMethod)o)); + + List<StatisticsInfo> superMethodInfos = ContainerUtil.newArrayList(new StatisticsInfo(context, memberValue)); + for (PsiClass superClass : InheritanceUtil.getSuperClasses(containingClass)) { + superMethodInfos.add(new StatisticsInfo(JavaStatisticsManager.getMemberUseKey2(superClass), memberValue)); + } + return StatisticsInfo.createComposite(superMethodInfos); } - return new StatisticsInfo(JavaStatisticsManager.getMemberUseKey2(containingClass), key2); + return new StatisticsInfo(context, key2); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 7f819c5360fb..053fc7220065 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -517,7 +517,7 @@ public class JavaCompletionUtil { } private static LookupElement highlight(LookupElement decorator) { - return PrioritizedLookupElement.withGrouping( + return PrioritizedLookupElement.withExplicitProximity( LookupElementDecorator.withRenderer(decorator, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() { @Override public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java index 4a1ac632a868..1a21b65af873 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java @@ -24,7 +24,6 @@ import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PsiJavaPatterns; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; @@ -366,46 +365,36 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor { final boolean staticContext, final PsiType varType, final PsiElement element) { - class Change implements Runnable { - private String[] result; + final List<String> propertyHandlers = new ArrayList<String>(); - @Override - public void run() { - final List<String> propertyHandlers = new ArrayList<String>(); - final PsiField[] fields = psiClass.getFields(); + for (final PsiField field : psiClass.getFields()) { + if (field == element) continue; - for (final PsiField field : fields) { - if (field == element) continue; + assert field.isValid() : "invalid field: " + field; + PsiType fieldType = field.getType(); + assert fieldType.isValid() : "invalid field type: " + field + "; " + fieldType + " of " + fieldType.getClass(); - assert field.isValid() : "invalid field: " + field; - PsiType fieldType = field.getType(); - assert fieldType.isValid() : "invalid field type: " + field + "; " + fieldType + " of " + fieldType.getClass(); + final PsiModifierList modifierList = field.getModifierList(); + if (staticContext && (modifierList != null && !modifierList.hasModifierProperty(PsiModifier.STATIC))) continue; - final PsiModifierList modifierList = field.getModifierList(); - if (staticContext && (modifierList != null && !modifierList.hasModifierProperty(PsiModifier.STATIC))) continue; - - if (fieldType.equals(varType)) { - final String getterName = PropertyUtil.suggestGetterName(field.getProject(), field); - if ((psiClass.findMethodsByName(getterName, true).length == 0 || - psiClass.findMethodBySignature(PropertyUtil.generateGetterPrototype(field), true) == null)) { - propertyHandlers.add(getterName); - } - } + if (fieldType.equals(varType)) { + final String getterName = PropertyUtil.suggestGetterName(field.getProject(), field); + if ((psiClass.findMethodsByName(getterName, true).length == 0 || + psiClass.findMethodBySignature(PropertyUtil.generateGetterPrototype(field), true) == null)) { + propertyHandlers.add(getterName); + } + } - if (PsiType.VOID.equals(varType)) { - final String setterName = PropertyUtil.suggestSetterName(field.getProject(), field); - if ((psiClass.findMethodsByName(setterName, true).length == 0 || - psiClass.findMethodBySignature(PropertyUtil.generateSetterPrototype(field), true) == null)) { - propertyHandlers.add(setterName); - } - } + if (PsiType.VOID.equals(varType)) { + final String setterName = PropertyUtil.suggestSetterName(field.getProject(), field); + if ((psiClass.findMethodsByName(setterName, true).length == 0 || + psiClass.findMethodBySignature(PropertyUtil.generateSetterPrototype(field), true) == null)) { + propertyHandlers.add(setterName); } - result = ArrayUtil.toStringArray(propertyHandlers); } } - final Change result = new Change(); - CodeStyleManager.getInstance(element.getProject()).performActionWithFormatterDisabled(result); - return result.result; + + return ArrayUtil.toStringArray(propertyHandlers); } private static void addLookupItems(Set<LookupElement> lookupElements, @Nullable final SuggestedNameInfo callback, PrefixMatcher matcher, Project project, String... strings) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index 8e604a247d33..d860c328b4af 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -154,7 +154,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor { } private static void suggestNonImportedClasses(CompletionParameters parameters, CompletionResultSet result) { - final ClassByNameMerger merger = new ClassByNameMerger(parameters.getInvocationCount() == 0, result); + final ClassByNameMerger merger = new ClassByNameMerger(parameters, result); JavaClassNameCompletionContributor.addAllClasses(parameters, true, result.getPrefixMatcher(), new Consumer<LookupElement>() { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java index 349cb7b47890..c1bfeda87531 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java @@ -152,7 +152,7 @@ public class JavaPsiClassReferenceElement extends LookupItem<Object> { presentation.setStrikeout(strikeout); presentation.setItemTextBold(bold); - String tailText = StringUtil.notNullize((String) item.getAttribute(LookupItem.TAIL_TEXT_ATTR)); + String tailText = getLocationString(item); PsiSubstitutor substitutor = (PsiSubstitutor)item.getAttribute(LookupItem.SUBSTITUTOR); if (item instanceof PsiTypeLookupItem) { @@ -173,6 +173,10 @@ public class JavaPsiClassReferenceElement extends LookupItem<Object> { presentation.setTailText(tailText, true); } + public static String getLocationString(LookupItem item) { + return StringUtil.notNullize((String)item.getAttribute(LookupItem.TAIL_TEXT_ATTR)); + } + private static String getName(final PsiClass psiClass, final LookupItem<?> item, boolean diamond) { if (item instanceof JavaPsiClassReferenceElement) { String forced = ((JavaPsiClassReferenceElement)item).getForcedPresentableName(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/simple/BracesTailType.java b/java/java-impl/src/com/intellij/codeInsight/completion/simple/BracesTailType.java index 485836e48eb4..8e8703a58c4a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/simple/BracesTailType.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/simple/BracesTailType.java @@ -23,22 +23,31 @@ import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.IdeActions; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionManager; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.util.text.CharArrayUtil; /** * @author peter */ -public abstract class BracesTailType extends TailType { - - protected abstract boolean isSpaceBeforeLBrace(CommonCodeStyleSettings styleSettings, Editor editor, final int tailOffset); +public class BracesTailType extends TailType { @Override public int processTail(final Editor editor, int tailOffset) { - final CommonCodeStyleSettings styleSettings = getLocalCodeStyleSettings(editor, tailOffset); - if (isSpaceBeforeLBrace(styleSettings, editor, tailOffset)) { - tailOffset = insertChar(editor, tailOffset, ' '); + int startOffset = tailOffset; + + CharSequence seq = editor.getDocument().getCharsSequence(); + int nextNonWs = CharArrayUtil.shiftForward(seq, tailOffset, " \t"); + if (nextNonWs < seq.length() && seq.charAt(nextNonWs) == '{') { + tailOffset = nextNonWs + 1; + } else { + tailOffset = insertChar(editor, startOffset, '{'); } - tailOffset = insertChar(editor, tailOffset, '{'); + + tailOffset = reformatBrace(editor, tailOffset, startOffset); + if (EnterAfterUnmatchedBraceHandler.isAfterUnmatchedLBrace(editor, tailOffset, getFileType(editor))) { new EnterHandler(EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ENTER)) .executeWriteAction(editor, DataManager.getInstance().getDataContext(editor.getContentComponent())); @@ -47,4 +56,16 @@ public abstract class BracesTailType extends TailType { return tailOffset; } + private static int reformatBrace(Editor editor, int tailOffset, int startOffset) { + Project project = editor.getProject(); + if (project != null) { + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + if (psiFile != null) { + editor.getCaretModel().moveToOffset(tailOffset); + CodeStyleManager.getInstance(project).reformatText(psiFile, startOffset, tailOffset); + tailOffset = editor.getCaretModel().getOffset(); + } + } + return tailOffset; + } }
\ No newline at end of file diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java index 26d89542658d..b3ef7ca2afce 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java @@ -32,7 +32,6 @@ import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ImageLoader; import com.intellij.util.PlatformUtils; -import com.intellij.util.io.URLUtil; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -41,7 +40,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; import java.io.IOException; -import java.net.URL; import java.util.*; /** @@ -236,7 +234,7 @@ public class IconLineMarkerProvider implements LineMarkerProvider { } private ImageIcon loadIcon(VirtualFile file, int scale) throws IOException { - return new ImageIcon(ImageLoader.loadFromStream(URLUtil.openStream(new URL(file.getUrl())), scale)); + return new ImageIcon(ImageLoader.loadFromStream(file.getInputStream(), scale)); } private static boolean isIconClassType(PsiType type) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java index 6d9370a71315..47e56b27c6e2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaColorProvider.java @@ -113,7 +113,7 @@ public class JavaColorProvider implements ElementColorProvider { switch (type) { case INT: case INT_BOOL: - replaceInt(expr[0], color.getRGB()); + replaceInt(expr[0], color.getRGB(), true); return; case INT_x3: case INT_x4: @@ -139,11 +139,16 @@ public class JavaColorProvider implements ElementColorProvider { } } } - + private static void replaceInt(PsiExpression expr, int newValue) { + replaceInt(expr, newValue, false); + } + + private static void replaceInt(PsiExpression expr, int newValue, boolean hex) { PsiElementFactory factory = JavaPsiFacade.getElementFactory(expr.getProject()); if (getInt(expr) != newValue) { - expr.replace(factory.createExpressionFromText(String.valueOf(newValue), null)); + String text = hex ? "0x" + Integer.toHexString(newValue & 0x00ffffff).toUpperCase() : Integer.toString(newValue); + expr.replace(factory.createExpressionFromText(text, null)); } } private static void replaceFloat(PsiExpression expr, float newValue) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java index 41ef28129f3b..1c2187626754 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java @@ -395,8 +395,8 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { return UnusedSymbolLocalInspection.isInjected(element); } - public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @Nullable String message, @NotNull final HighlightInfoType highlightInfoType) { - HighlightInfo info = HighlightInfo.createHighlightInfo(highlightInfoType, element, message); + public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @NotNull String message, @NotNull final HighlightInfoType highlightInfoType) { + HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create(); UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME); for (UnusedDeclarationFixProvider provider : fixProviders) { IntentionAction[] fixes = provider.getQuickFixes(element); @@ -465,10 +465,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) { return false; } - if (field instanceof PsiEnumConstant && isEnumValuesMethodUsed(field, progress, helper)) { - return false; - } - return true; + return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(field, progress, helper); } private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) { @@ -615,7 +612,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { return false; } - private static boolean weAreSureThereAreNoUsages(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) { + private static boolean weAreSureThereAreNoUsages(@NotNull PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) { if (!helper.shouldCheckUsages(member)) return false; String name = member.getName(); @@ -779,7 +776,10 @@ public class PostHighlightingPass extends TextEditorHighlightingPass { } private HighlightInfo registerRedundantImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) { - HighlightInfo info = HighlightInfo.createHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT, importStatement, InspectionsBundle.message("unused.import.statement")); + String description = InspectionsBundle.message("unused.import.statement"); + HighlightInfo info = + HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description) + .create(); QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey); QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java index 63416fa26746..68c4e1f5a0bc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java @@ -59,13 +59,16 @@ public class AnnotationsHighlightUtil { if (method == null) { if (pair.getName() != null) { final String description = JavaErrorMessages.message("annotation.unknown.method", ref.getCanonicalText()); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, ref.getElement(), description); + PsiElement element = ref.getElement(); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(element).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new CreateAnnotationMethodFromUsageFix(pair)); return highlightInfo; } else { String description = JavaErrorMessages.message("annotation.missing.method", ref.getCanonicalText()); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref.getElement(), description); + PsiElement element = ref.getElement(); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } } else { @@ -89,7 +92,7 @@ public class AnnotationsHighlightUtil { if (Comparing.equal(attribute.getName(), name)) { String description = JavaErrorMessages.message("annotation.duplicate.attribute", name == null ? PsiAnnotation.DEFAULT_REFERENCED_METHOD_NAME : name); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, pair, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(pair).descriptionAndTooltip(description).create(); } } @@ -107,7 +110,7 @@ public class AnnotationsHighlightUtil { if (expectedType instanceof PsiClassType && expectedType.equalsToText(CommonClassNames.JAVA_LANG_CLASS)) { if (!(value instanceof PsiClassObjectAccessExpression)) { String description = JavaErrorMessages.message("annotation.non.class.literal.attribute.value"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(value).descriptionAndTooltip(description).create(); } } @@ -130,14 +133,14 @@ public class AnnotationsHighlightUtil { String description = JavaErrorMessages.message("annotation.incompatible.types", formatReference(nameRef), HighlightUtil.formatType(expectedType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(value).descriptionAndTooltip(description).create(); } - else if (value instanceof PsiArrayInitializerMemberValue) { + if (value instanceof PsiArrayInitializerMemberValue) { if (expectedType instanceof PsiArrayType) return null; String description = JavaErrorMessages.message("annotation.illegal.array.initializer", HighlightUtil.formatType(expectedType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(value).descriptionAndTooltip(description).create(); } - else if (value instanceof PsiExpression) { + if (value instanceof PsiExpression) { PsiExpression expr = (PsiExpression)value; PsiType type = expr.getType(); if (type != null && TypeConversionUtil.areTypesAssignmentCompatible(expectedType, expr) || @@ -148,7 +151,7 @@ public class AnnotationsHighlightUtil { String description = JavaErrorMessages.message("annotation.incompatible.types", HighlightUtil.formatType(type), HighlightUtil.formatType(expectedType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(value).descriptionAndTooltip(description).create(); } LOG.error("Unknown annotation member value: " + value); @@ -174,7 +177,8 @@ public class AnnotationsHighlightUtil { if (nameRef == null) continue; PsiElement aClass = nameRef.resolve(); if (resolved.equals(aClass)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, JavaErrorMessages.message("annotation.duplicate.annotation")); + String description = JavaErrorMessages.message("annotation.duplicate.annotation"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } } @@ -220,7 +224,7 @@ public class AnnotationsHighlightUtil { } String description = JavaErrorMessages.message("annotation.missing.attribute", buff); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameRef).descriptionAndTooltip(description).create(); } } @@ -232,7 +236,8 @@ public class AnnotationsHighlightUtil { final PsiElement parent = expression.getParent(); if (PsiUtil.isAnnotationMethod(parent) || parent instanceof PsiNameValuePair || parent instanceof PsiArrayInitializerMemberValue) { if (!PsiUtil.isConstantExpression(expression)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("annotation.non.constant.attribute.value")); + String description = JavaErrorMessages.message("annotation.non.constant.attribute.value"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } } @@ -245,7 +250,8 @@ public class AnnotationsHighlightUtil { if (type.accept(AnnotationReturnTypeVisitor.INSTANCE).booleanValue()) { return null; } - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("annotation.invalid.annotation.member.type")); + String description = JavaErrorMessages.message("annotation.invalid.annotation.member.type"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } private static final ElementPattern<PsiElement> ANNOTATION_ALLOWED = psiElement().andOr( @@ -275,14 +281,16 @@ public class AnnotationsHighlightUtil { } String target = JavaErrorMessages.message("annotation.target." + elementTypeFields[0]); String description = JavaErrorMessages.message("annotation.not.applicable", nameRef.getText(), target); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameRef, description); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameRef).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation)); return highlightInfo; } if (!ANNOTATION_ALLOWED.accepts(annotation)) { String message = JavaErrorMessages.message("annotation.not.allowed.here"); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, annotation, message); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteNotApplicableAnnotationAction(annotation)); return highlightInfo; } @@ -313,7 +321,9 @@ public class AnnotationsHighlightUtil { String description = JavaErrorMessages.message("private.symbol", HighlightUtil.formatField((PsiField)resolve), HighlightUtil.formatClass((PsiClass)parent)); - infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, description); + HighlightInfo result = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); + infos[0] = result; } } }); @@ -328,7 +338,8 @@ public class AnnotationsHighlightUtil { if (nameReferenceElement != null) { PsiElement resolved = nameReferenceElement.resolve(); if (!(resolved instanceof PsiClass) || !((PsiClass)resolved).isAnnotationType()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, nameReferenceElement, JavaErrorMessages.message("annotation.annotation.type.expected")); + String description = JavaErrorMessages.message("annotation.annotation.type.expected"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(nameReferenceElement).descriptionAndTooltip(description).create(); } } return null; @@ -339,7 +350,8 @@ public class AnnotationsHighlightUtil { LOG.assertTrue(aClass.isAnnotationType()); PsiType type = typeElement.getType(); if (type instanceof PsiClassType && ((PsiClassType)type).resolve() == aClass) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("annotation.cyclic.element.type")); + String description = JavaErrorMessages.message("annotation.cyclic.element.type"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } return null; } @@ -349,12 +361,14 @@ public class AnnotationsHighlightUtil { if (PsiUtil.isAnnotationMethod(parent)) { PsiAnnotationMethod method = (PsiAnnotationMethod)parent; if (list == method.getThrowsList()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("annotation.members.may.not.have.throws.list")); + String description = JavaErrorMessages.message("annotation.members.may.not.have.throws.list"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).create(); } } else if (parent instanceof PsiClass && ((PsiClass)parent).isAnnotationType()) { if (PsiKeyword.EXTENDS.equals(list.getFirstChild().getText())) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("annotation.may.not.have.extends.list")); + String description = JavaErrorMessages.message("annotation.may.not.have.extends.list"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).create(); } } return null; @@ -368,10 +382,11 @@ public class AnnotationsHighlightUtil { } PsiFile file = statement.getContainingFile(); if (file != null && !PsiPackage.PACKAGE_INFO_FILE.equals(file.getName())) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - statement.getAnnotationList().getTextRange(), - JavaErrorMessages.message("invalid.package.annotation.containing.file")); - + String description = JavaErrorMessages.message("invalid.package.annotation.containing.file"); + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR); + builder.range(statement.getAnnotationList().getTextRange()); + builder.descriptionAndTooltip(description); + return builder.create(); } return null; } @@ -395,9 +410,8 @@ public class AnnotationsHighlightUtil { PsiElement target = ((PsiReferenceExpression) initializer).resolve(); if (target != null) { if (targets.contains(target)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - initializer, - JavaErrorMessages.message("repeated.annotation.target")); + String description = JavaErrorMessages.message("repeated.annotation.target"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(initializer).descriptionAndTooltip(description).create(); } targets.add(target); } @@ -409,7 +423,7 @@ public class AnnotationsHighlightUtil { public static HighlightInfo checkFunctionalInterface(PsiAnnotation annotation) { final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation); if (errorMessage != null) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, annotation, errorMessage); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create(); } return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 8c42592a468f..ebd37010a2aa 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -35,7 +35,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.SuperMethodsSearch; import com.intellij.psi.util.*; -import com.intellij.util.ArrayUtil; +import com.intellij.util.ArrayUtilRt; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.HashSet; @@ -68,17 +68,21 @@ public class GenericsHighlightUtil { PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes(); for (PsiClassType type : extendsTypes) { PsiType extendsType = substitutor.substitute(type); - if (substituted instanceof PsiWildcardType && - TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(((PsiWildcardType)substituted).getExtendsBound()))) { - PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound(); - if (extendsBound instanceof PsiClassType) { - PsiType[] parameters = ((PsiClassType)extendsBound).getParameters(); - if (parameters.length == 1) { - PsiType argType = parameters[0]; - if (argType instanceof PsiCapturedWildcardType) { - argType = ((PsiCapturedWildcardType)argType).getWildcard(); + if (substituted instanceof PsiWildcardType) { + if (!((PsiWildcardType)substituted).isExtends()) { + continue; + } + final PsiType extendsBound = ((PsiWildcardType)substituted).getExtendsBound(); + if (TypeConversionUtil.erasure(extendsType).equals(TypeConversionUtil.erasure(extendsBound))) { + if (extendsBound instanceof PsiClassType) { + PsiType[] parameters = ((PsiClassType)extendsBound).getParameters(); + if (parameters.length == 1) { + PsiType argType = parameters[0]; + if (argType instanceof PsiCapturedWildcardType) { + argType = ((PsiCapturedWildcardType)argType).getWildcard(); + } + if (argType instanceof PsiWildcardType && !((PsiWildcardType)argType).isBounded()) continue; } - if (argType instanceof PsiWildcardType && !((PsiWildcardType)argType).isBounded()) continue; } } } @@ -96,7 +100,7 @@ public class GenericsHighlightUtil { HighlightUtil.formatType(substituted) ); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, call, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(call).descriptionAndTooltip(description).create(); } } } @@ -125,14 +129,15 @@ public class GenericsHighlightUtil { if (referenceElements.length == 1 && referenceElements[0].getType() instanceof PsiDiamondType) { if (!typeParameterListOwner.hasTypeParameters()) { final String description = JavaErrorMessages.message("generics.diamond.not.applicable"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(referenceElements[0]).descriptionAndTooltip(description).create(); } inferenceResult = ((PsiDiamondType)referenceElements[0].getType()).resolveInferredTypes(); final String errorMessage = inferenceResult.getErrorMessage(); if (errorMessage != null) { final PsiType expectedType = detectExpectedType(referenceParameterList); if (!(inferenceResult.failedToInfer() && expectedType instanceof PsiClassType && ((PsiClassType)expectedType).isRaw())) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElements[0], errorMessage); + return HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(referenceElements[0]).descriptionAndTooltip(errorMessage).create(); } } } @@ -161,7 +166,8 @@ public class GenericsHighlightUtil { } if (description != null) { - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceParameterList, description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(referenceParameterList).descriptionAndTooltip(description).create(); if (registerIntentions) { PsiElement grandParent = referenceParameterList.getParent().getParent(); if (grandParent instanceof PsiTypeElement) { @@ -226,7 +232,7 @@ public class GenericsHighlightUtil { final PsiMethod method = ((PsiCallExpression)pParent).resolveMethod(); if (method != null) { final PsiExpression[] expressions = ((PsiCallExpression)pParent).getArgumentList().getExpressions(); - final int idx = ArrayUtil.find(expressions, newExpression); + final int idx = ArrayUtilRt.find(expressions, newExpression); if (idx > -1) { final PsiParameterList parameterList = method.getParameterList(); if (idx < parameterList.getParametersCount()) { @@ -245,18 +251,12 @@ public class GenericsHighlightUtil { final PsiType type, final PsiElement typeElement2Highlight, PsiReferenceParameterList referenceParameterList) { - final PsiClass referenceClass; - if (type instanceof PsiClassType) { - referenceClass = ((PsiClassType)type).resolve(); - } - else { - referenceClass = null; - } + final PsiClass referenceClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null; final PsiType psiType = substitutor.substitute(classParameter); if (psiType instanceof PsiClassType && !(PsiUtil.resolveClassInType(psiType) instanceof PsiTypeParameter)) { if (checkNotInBounds(type, psiType, referenceParameterList)) { final String description = "Actual type argument and inferred type contradict each other"; - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement2Highlight, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement2Highlight).descriptionAndTooltip(description).create(); } } @@ -274,9 +274,8 @@ public class GenericsHighlightUtil { referenceClass != null ? HighlightUtil.formatClass(referenceClass) : type.getPresentableText(), HighlightUtil.formatType(bound)); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - typeElement2Highlight, - description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement2Highlight).descriptionAndTooltip(description).create(); if (bound instanceof PsiClassType && referenceClass != null) { QuickFixAction .registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(referenceClass, (PsiClassType)bound, true), @@ -292,19 +291,17 @@ public class GenericsHighlightUtil { if (type instanceof PsiClassType) { return checkNotAssignable(bound, type, allowUncheckedConversions((PsiClassType)type, referenceParameterList)); } - else { - if (type instanceof PsiWildcardType) { - if (((PsiWildcardType)type).isExtends()) { - return checkExtendsWildcardCaptureFailure((PsiWildcardType)type, bound); - } - else if (((PsiWildcardType)type).isSuper()) { - return checkNotAssignable(bound, ((PsiWildcardType)type).getSuperBound(), false); - } + if (type instanceof PsiWildcardType) { + if (((PsiWildcardType)type).isExtends()) { + return checkExtendsWildcardCaptureFailure((PsiWildcardType)type, bound); } - else if (type instanceof PsiArrayType) { - return checkNotAssignable(bound, type, true); + else if (((PsiWildcardType)type).isSuper()) { + return checkNotAssignable(bound, ((PsiWildcardType)type).getSuperBound(), false); } } + else if (type instanceof PsiArrayType) { + return checkNotAssignable(bound, type, true); + } return false; } @@ -395,14 +392,14 @@ public class GenericsHighlightUtil { HighlightInfo errorResult = null; if (!extendFrom.isInterface() && referenceElements.length != 0 && element != referenceElements[0]) { String description = JavaErrorMessages.message("interface.expected"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, description); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); PsiClassType type = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(extendFrom, resolveResult.getSubstitutor()); QuickFixAction.registerQuickFixAction(errorResult, new MoveBoundClassToFrontFix(aClass, type), null); } else if (referenceElements.length != 0 && element != referenceElements[0] && referenceElements[0].resolve() instanceof PsiTypeParameter) { final String description = JavaErrorMessages.message("type.parameter.cannot.be.followed.by.other.bounds"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, description); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); PsiClassType type = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(extendFrom, resolveResult.getSubstitutor()); IntentionAction fix = QUICK_FIX_FACTORY.createExtendsListFix(aClass, type, false); @@ -452,7 +449,7 @@ public class GenericsHighlightUtil { HighlightUtil.formatClass(superClass), HighlightUtil.formatType(type1), HighlightUtil.formatType(type2)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } } } @@ -504,8 +501,8 @@ public class GenericsHighlightUtil { final String inheritUnrelatedDefaultsMessage = HighlightUtil.formatClass(aClass) + " inherits unrelated defaults for " + HighlightUtil.formatMethod(method) + " from types " + HighlightUtil.formatClass(containingClass) + " and " + HighlightUtil.formatClass(superContainingClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - classIdentifier, inheritUnrelatedDefaultsMessage); + return HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(inheritUnrelatedDefaultsMessage).create(); } if (!aClass.hasModifierProperty(PsiModifier.ABSTRACT)) { final String message = JavaErrorMessages.message( @@ -513,7 +510,7 @@ public class GenericsHighlightUtil { HighlightUtil.formatClass(superContainingClass), HighlightUtil.formatMethod(superMethod), HighlightUtil.formatClass(superContainingClass, false)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, classIdentifier, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(message).create(); } } } @@ -624,7 +621,7 @@ public class GenericsHighlightUtil { "generics.methods.have.same.erasure.hide" : "generics.methods.have.same.erasure.override"; String description = JavaErrorMessages.message(key, HighlightMethodUtil.createClashMethodMessage(method, superMethod, !sameClass)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } public static HighlightInfo checkTypeParameterInstantiation(PsiNewExpression expression) { @@ -635,7 +632,7 @@ public class GenericsHighlightUtil { if (element instanceof PsiTypeParameter) { String description = JavaErrorMessages.message("generics.type.parameter.cannot.be.instantiated", HighlightUtil.formatClass((PsiTypeParameter)element)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, classReference, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classReference).descriptionAndTooltip(description).create(); } return null; } @@ -652,22 +649,20 @@ public class GenericsHighlightUtil { PsiNewExpression newExpression = (PsiNewExpression)refParent; if (!(newExpression.getType() instanceof PsiArrayType)) { String description = JavaErrorMessages.message("wildcard.type.cannot.be.instantiated", HighlightUtil.formatType(type)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } else if (refParent instanceof PsiReferenceList) { PsiElement refPParent = refParent.getParent(); if (!(refPParent instanceof PsiTypeParameter) || refParent != ((PsiTypeParameter)refPParent).getExtendsList()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - typeElement, - JavaErrorMessages.message("generics.wildcard.not.expected")); + String description = JavaErrorMessages.message("generics.wildcard.not.expected"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } } else { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - typeElement, - JavaErrorMessages.message("generics.wildcards.may.be.used.only.as.reference.parameters")); + String description = JavaErrorMessages.message("generics.wildcards.may.be.used.only.as.reference.parameters"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } @@ -685,7 +680,8 @@ public class GenericsHighlightUtil { if (element == null) return null; String description = JavaErrorMessages.message("generics.type.argument.cannot.be.of.primitive.type"); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); PsiType toConvert = type; if (type instanceof PsiWildcardType) { toConvert = ((PsiWildcardType)type).getBound(); @@ -717,7 +713,7 @@ public class GenericsHighlightUtil { } return false; } - else if (lType instanceof PsiIntersectionType) { + if (lType instanceof PsiIntersectionType) { for (PsiType type : ((PsiIntersectionType)lType).getConjuncts()) { if (isRawToGeneric(type, rType)) return true; } @@ -801,10 +797,10 @@ public class GenericsHighlightUtil { if (operandClassType.isRaw()) return true; if (castClass.isInheritor(operandClass, true)) { PsiSubstitutor castSubstitutor = castResult.getSubstitutor(); + PsiElementFactory factory = JavaPsiFacade.getInstance(castClass.getProject()).getElementFactory(); for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(castClass)) { PsiSubstitutor modifiedSubstitutor = castSubstitutor.put(typeParameter, null); - PsiClassType otherType = - JavaPsiFacade.getInstance(typeParameter.getProject()).getElementFactory().createType(castClass, modifiedSubstitutor); + PsiClassType otherType = factory.createType(castClass, modifiedSubstitutor); if (TypeConversionUtil.isAssignable(operandType, otherType, false)) return true; } for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(operandClass)) { @@ -829,12 +825,12 @@ public class GenericsHighlightUtil { if (itemType == null) { String description = JavaErrorMessages.message("foreach.not.applicable", HighlightUtil.formatType(expression.getType())); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } final int start = parameter.getTextRange().getStartOffset(); final int end = expression.getTextRange().getEndOffset(); final PsiType parameterType = parameter.getType(); - HighlightInfo highlightInfo = HighlightUtil.checkAssignability(parameterType, itemType, null, new TextRange(start, end)); + HighlightInfo highlightInfo = HighlightUtil.checkAssignability(parameterType, itemType, null, new TextRange(start, end), 0); if (highlightInfo != null) { HighlightUtil.registerChangeVariableTypeFixes(parameter, itemType, highlightInfo); } @@ -922,7 +918,7 @@ public class GenericsHighlightUtil { HighlightMessageUtil.getSymbolName(resolved, result.getSubstitutor()) ); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expr, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip(description).create(); } @Nullable @@ -932,7 +928,7 @@ public class GenericsHighlightUtil { final PsiClass aClass = ((PsiClassType)type).resolve(); if (aClass != null && aClass.isEnum()) { String description = JavaErrorMessages.message("enum.types.cannot.be.instantiated"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } } return null; @@ -942,9 +938,8 @@ public class GenericsHighlightUtil { public static HighlightInfo checkGenericArrayCreation(PsiElement element, PsiType type) { if (type instanceof PsiArrayType) { if (!isReifiableType(((PsiArrayType)type).getComponentType())) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - element, - JavaErrorMessages.message("generic.array.creation")); + String description = JavaErrorMessages.message("generic.array.creation"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } } @@ -973,15 +968,16 @@ public class GenericsHighlightUtil { final PsiElement parent = parameterList.getParent(); if (parent instanceof PsiClass && ((PsiClass)parent).isEnum()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - parameterList, - JavaErrorMessages.message("generics.enum.may.not.have.type.parameters")); + String description = JavaErrorMessages.message("generics.enum.may.not.have.type.parameters"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameterList).descriptionAndTooltip(description).create(); } if (PsiUtil.isAnnotationMethod(parent)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parameterList, JavaErrorMessages.message("generics.annotation.members.may.not.have.type.parameters")); + String description = JavaErrorMessages.message("generics.annotation.members.may.not.have.type.parameters"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameterList).descriptionAndTooltip(description).create(); } - else if (parent instanceof PsiClass && ((PsiClass)parent).isAnnotationType()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parameterList, JavaErrorMessages.message("annotation.may.not.have.type.parameters")); + if (parent instanceof PsiClass && ((PsiClass)parent).isAnnotationType()) { + String description = JavaErrorMessages.message("annotation.may.not.have.type.parameters"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameterList).descriptionAndTooltip(description).create(); } for (int i = 0; i < typeParameters.length; i++) { @@ -992,7 +988,7 @@ public class GenericsHighlightUtil { String name2 = typeParameter2.getName(); if (Comparing.strEqual(name1, name2)) { String message = JavaErrorMessages.message("generics.duplicate.type.parameter", name1); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeParameter2, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeParameter2).descriptionAndTooltip(message).create(); } } } @@ -1009,7 +1005,7 @@ public class GenericsHighlightUtil { final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(typeElement.getType()); if (aClass instanceof PsiTypeParameter) { final String message = JavaErrorMessages.message("generics.cannot.catch.type.parameters"); - result.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, message)); + result.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(message).create()); } } @@ -1031,7 +1027,8 @@ public class GenericsHighlightUtil { private static HighlightInfo isIllegalForInstanceOf(PsiJavaCodeReferenceElement ref, final PsiTypeElement typeElement) { final PsiElement resolved = ref.resolve(); if (resolved instanceof PsiTypeParameter) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, JavaErrorMessages.message("generics.cannot.instanceof.type.parameters")); + String description = JavaErrorMessages.message("generics.cannot.instanceof.type.parameters"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).create(); } if (resolved instanceof PsiClass) { @@ -1041,7 +1038,8 @@ public class GenericsHighlightUtil { containingClass.getTypeParameters().length > 0 && !((PsiClass)resolved).hasModifierProperty(PsiModifier.STATIC) && ((PsiClass)resolved).getTypeParameters().length == 0) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof")); + String description = JavaErrorMessages.message("illegal.generic.type.for.instanceof"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } @@ -1049,7 +1047,8 @@ public class GenericsHighlightUtil { for (PsiType parameterType : parameters) { if (parameterType != null && !(parameterType instanceof PsiWildcardType && ((PsiWildcardType)parameterType).getBound() == null)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, JavaErrorMessages.message("illegal.generic.type.for.instanceof")); + String description = JavaErrorMessages.message("illegal.generic.type.for.instanceof"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } @@ -1060,7 +1059,8 @@ public class GenericsHighlightUtil { PsiType type = expression.getOperand().getType(); if (type instanceof PsiClassType) { return canSelectFrom((PsiClassType)type, expression.getOperand()); - } else if (type instanceof PsiArrayType) { + } + if (type instanceof PsiArrayType) { final PsiType arrayComponentType = type.getDeepComponentType(); if (arrayComponentType instanceof PsiClassType) { return canSelectFrom((PsiClassType)arrayComponentType, expression.getOperand()); @@ -1074,13 +1074,12 @@ public class GenericsHighlightUtil { private static HighlightInfo canSelectFrom(PsiClassType type, PsiTypeElement operand) { PsiClass aClass = type.resolve(); if (aClass instanceof PsiTypeParameter) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - operand, - JavaErrorMessages.message("cannot.select.dot.class.from.type.variable")); - } else if (type.getParameters().length > 0) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - operand, - "Cannot select from parameterized type"); + String description = JavaErrorMessages.message("cannot.select.dot.class.from.type.variable"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(operand).descriptionAndTooltip(description).create(); + } + if (type.getParameters().length > 0) { + return HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(operand).descriptionAndTooltip("Cannot select from parameterized type").create(); } return null; } @@ -1095,8 +1094,9 @@ public class GenericsHighlightUtil { try { MethodSignatureBackedByPsiMethod superMethod = SuperMethodsSearch.search(method, null, true, false).findFirst(); if (superMethod == null) { - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, overrideAnnotation, - JavaErrorMessages.message("method.does.not.override.super")); + String description = JavaErrorMessages.message("method.does.not.override.super"); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(overrideAnnotation).descriptionAndTooltip(description).create(); PullAsAbstractUpFix.registerQuickFix(highlightInfo, method); return highlightInfo; } @@ -1105,7 +1105,9 @@ public class GenericsHighlightUtil { if (languageLevel.equals(LanguageLevel.JDK_1_5) && superClass != null && superClass.isInterface()) { - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, overrideAnnotation, JavaErrorMessages.message("override.not.allowed.in.interfaces")); + String description = JavaErrorMessages.message("override.not.allowed.in.interfaces"); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(overrideAnnotation).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_6)); return info; } @@ -1125,10 +1127,12 @@ public class GenericsHighlightUtil { } try { if (!method.isVarArgs()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, safeVarargsAnnotation, "@SafeVarargs is not allowed on methods with fixed arity"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(safeVarargsAnnotation).descriptionAndTooltip( + "@SafeVarargs is not allowed on methods with fixed arity").create(); } if (!method.hasModifierProperty(PsiModifier.STATIC) && !method.hasModifierProperty(PsiModifier.FINAL) && !method.isConstructor()) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, safeVarargsAnnotation, "@SafeVarargs is not allowed on non-final instance methods"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(safeVarargsAnnotation).descriptionAndTooltip( + "@SafeVarargs is not allowed on non-final instance methods").create(); } final PsiParameter varParameter = method.getParameterList().getParameters()[method.getParameterList().getParametersCount() - 1]; @@ -1136,7 +1140,8 @@ public class GenericsHighlightUtil { for (PsiReference reference : ReferencesSearch.search(varParameter)) { final PsiElement element = reference.getElement(); if (element instanceof PsiExpression && !PsiUtil.isAccessedForReading((PsiExpression)element)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.WARNING, element, "@SafeVarargs do not suppress potentially unsafe operations"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(element).descriptionAndTooltip( + "@SafeVarargs do not suppress potentially unsafe operations").create(); } } @@ -1145,7 +1150,9 @@ public class GenericsHighlightUtil { final PsiEllipsisType ellipsisType = (PsiEllipsisType)varParameter.getType(); final PsiType componentType = ellipsisType.getComponentType(); if (isReifiableType(componentType)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.WARNING, varParameter.getTypeElement(), "@SafeVarargs is not applicable for reifiable types"); + PsiElement element = varParameter.getTypeElement(); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(element).descriptionAndTooltip( + "@SafeVarargs is not applicable for reifiable types").create(); } return null; } @@ -1265,7 +1272,7 @@ public class GenericsHighlightUtil { return; } } - PsiClassType type = JavaPsiFacade.getInstance(enumConstant.getProject()).getElementFactory().createType(containingClass); + PsiClassType type = JavaPsiFacade.getInstance(holder.getProject()).getElementFactory().createType(containingClass); HighlightMethodUtil.checkConstructorCall(type.resolveGenerics(), enumConstant, type, null, holder); } @@ -1280,7 +1287,7 @@ public class GenericsHighlightUtil { final PsiClass aClass = constructor.getContainingClass(); if (aClass != null && aClass.isEnum()) { final String message = JavaErrorMessages.message("call.to.super.is.not.allowed.in.enum.constructor"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expr, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip(message).create(); } } } @@ -1297,7 +1304,8 @@ public class GenericsHighlightUtil { if (info != null) return info; if (params[params.length - 1] != parameter) { - info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parameter, JavaErrorMessages.message("vararg.not.last.parameter")); + String description = JavaErrorMessages.message("vararg.not.last.parameter"); + info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new MakeVarargParameterLastFix(parameter)); return info; } @@ -1315,9 +1323,8 @@ public class GenericsHighlightUtil { if (list == null) { list = new ArrayList<HighlightInfo>(); } - list.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - child, - JavaErrorMessages.message("modifiers.for.enum.constants"))); + String description = JavaErrorMessages.message("modifiers.for.enum.constants"); + list.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(child).descriptionAndTooltip(description).create()); } } return list; @@ -1334,7 +1341,7 @@ public class GenericsHighlightUtil { final PsiElement grandParent = parent.getParent(); if (!(grandParent instanceof PsiMethodCallExpression) && !(parent instanceof PsiMethodReferenceExpression)) { final String message = JavaErrorMessages.message("generics.reference.parameters.not.allowed"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, refParamList, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refParamList).descriptionAndTooltip(message).create(); } } } @@ -1373,7 +1380,7 @@ public class GenericsHighlightUtil { ? JavaErrorMessages.message("generics.type.arguments.on.raw.type") : JavaErrorMessages.message("generics.type.arguments.on.raw.method"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, refParamList, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(refParamList).descriptionAndTooltip(message).create(); } } return null; @@ -1383,7 +1390,8 @@ public class GenericsHighlightUtil { HighlightInfo errorResult = null; if (Comparing.strEqual("java.lang.Enum", superClass.getQualifiedName())) { String message = JavaErrorMessages.message("classes.extends.enum"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, message); + errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(message).create(); } return errorResult; } @@ -1404,7 +1412,8 @@ public class GenericsHighlightUtil { } if (InheritanceUtil.isInheritorOrSelf((PsiClass)resolved, throwableClass, true)) { String message = JavaErrorMessages.message("generic.extend.exception"); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, referenceElement, message); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(referenceElement).descriptionAndTooltip(message).create(); PsiClassType classType = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType((PsiClass)resolved); QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(aClass, classType, false)); return highlightInfo; @@ -1417,9 +1426,9 @@ public class GenericsHighlightUtil { if (!aClass.isEnum()) return null; PsiElement parent = aClass.getParent(); if (!(parent instanceof PsiClass || parent instanceof PsiFile)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - HighlightNamesUtil.getClassDeclarationTextRange(aClass), - JavaErrorMessages.message("local.enum")); + String description = JavaErrorMessages.message("local.enum"); + TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } return null; } @@ -1432,7 +1441,7 @@ public class GenericsHighlightUtil { if (parameterList != null && parameterList.getTypeArguments().length > 0) { final String message = JavaErrorMessages.message("generics.select.static.class.from.parameterized.type", HighlightUtil.formatClass((PsiClass)resolved)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parameterList, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameterList).descriptionAndTooltip(message).create(); } } } @@ -1441,8 +1450,8 @@ public class GenericsHighlightUtil { public static HighlightInfo checkCannotInheritFromTypeParameter(final PsiClass superClass, final PsiJavaCodeReferenceElement toHighlight) { if (superClass instanceof PsiTypeParameter) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, toHighlight, - JavaErrorMessages.message("class.cannot.inherit.from.its.type.parameter")); + String description = JavaErrorMessages.message("class.cannot.inherit.from.its.type.parameter"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(toHighlight).descriptionAndTooltip(description).create(); } return null; } @@ -1462,7 +1471,8 @@ public class GenericsHighlightUtil { if (resolve instanceof PsiTypeParameterListOwner && ((PsiTypeParameterListOwner)resolve).hasTypeParameters() && !((PsiTypeParameterListOwner)resolve).hasModifierProperty(PsiModifier.STATIC)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parent, "Improper formed type; some type parameters are missing"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip( + "Improper formed type; some type parameters are missing").create(); } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index e0eaca96611e..4325010c490e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -85,7 +85,7 @@ public class HighlightClassUtil { } @Nullable - static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, TextRange textRange) { + static HighlightInfo checkClassWithAbstractMethods(PsiClass aClass, TextRange range) { PsiMethod abstractMethod = ClassUtil.getAnyAbstractMethod(aClass); if (abstractMethod == null || abstractMethod.getContainingClass() == null) { @@ -98,7 +98,7 @@ public class HighlightClassUtil { methodName, HighlightUtil.formatClass(abstractMethod.getContainingClass(), false)); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create(); if (ClassUtil.getAnyMethodToImplement(aClass) != null) { QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementMethodsFix(aClass)); } @@ -126,9 +126,10 @@ public class HighlightClassUtil { String message = JavaErrorMessages.message("abstract.cannot.be.instantiated", baseClassName); PsiElement parent = highlightElement.getParent(); if (parent instanceof PsiNewExpression) { - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parent, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(message).create(); } else { - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, highlightElement, message); + errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(highlightElement).descriptionAndTooltip(message).create(); } final PsiMethod anyAbstractMethod = ClassUtil.getAnyAbstractMethod(aClass); if (!aClass.isInterface() && anyAbstractMethod == null) { @@ -182,7 +183,7 @@ public class HighlightClassUtil { String message = JavaErrorMessages.message("duplicate.class.in.other.file", dupFileName); TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(message).create(); } @Nullable @@ -207,7 +208,8 @@ public class HighlightClassUtil { // , or a compile-time error occurs. // However, a local class declaration may be shadowed (?6.3.1) // anywhere inside a class declaration nested within the local class declaration's scope. - if (element instanceof PsiMethod || element instanceof PsiClass || (element instanceof PsiCodeBlock && element.getParent() instanceof PsiClassInitializer)) { + if (element instanceof PsiMethod || element instanceof PsiClass || + element instanceof PsiCodeBlock && element.getParent() instanceof PsiClassInitializer) { checkSiblings = false; } } @@ -223,7 +225,7 @@ public class HighlightClassUtil { if (duplicateFound) { String message = JavaErrorMessages.message("duplicate.class", name); TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(message).create(); } return null; } @@ -249,7 +251,7 @@ public class HighlightClassUtil { if (virtualFile != null && !aClass.getName().equals(virtualFile.getNameWithoutExtension())) { String message = JavaErrorMessages.message("public.class.should.be.named.after.file", aClass.getName()); TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(psiModifierList, PsiModifier.PUBLIC, false, false); QuickFixAction.registerQuickFixAction(errorResult, fix); PsiClass[] classes = file.getClasses(); @@ -276,7 +278,7 @@ public class HighlightClassUtil { if (CommonClassNames.DEFAULT_PACKAGE.equals(name)) { String message = JavaErrorMessages.message("class.clashes.with.package", name); TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create(); } PsiElement file = aClass.getParent(); @@ -288,7 +290,7 @@ public class HighlightClassUtil { if (subDirectory != null && simpleName.equals(subDirectory.getName())) { String message = JavaErrorMessages.message("class.clashes.with.package", name); TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create(); } } } @@ -308,16 +310,16 @@ public class HighlightClassUtil { } String message = JavaErrorMessages.message("static.declaration.in.inner.class"); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, keyword, message); + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); - QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(field, PsiModifier.STATIC, false, false)); + QuickFixAction.registerQuickFixAction(result, QUICK_FIX_FACTORY.createModifierListFix(field, PsiModifier.STATIC, false, false)); PsiClass aClass = field.getContainingClass(); if (aClass != null) { - QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.STATIC, true, false)); + QuickFixAction.registerQuickFixAction(result, QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.STATIC, true, false)); } - return errorResult; + return result; } @Nullable @@ -328,12 +330,12 @@ public class HighlightClassUtil { PsiMethod method = (PsiMethod)keyword.getParent().getParent(); if (PsiUtilCore.hasErrorElementChild(method)) return null; String message = JavaErrorMessages.message("static.declaration.in.inner.class"); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, keyword, message); + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); IntentionAction fix1 = QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.STATIC, false, false); - QuickFixAction.registerQuickFixAction(errorResult, fix1); + QuickFixAction.registerQuickFixAction(result, fix1); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix((PsiClass)keyword.getParent().getParent().getParent(), PsiModifier.STATIC, true, false); - QuickFixAction.registerQuickFixAction(errorResult, fix); - return errorResult; + QuickFixAction.registerQuickFixAction(result, fix); + return result; } @Nullable @@ -344,13 +346,13 @@ public class HighlightClassUtil { PsiClassInitializer initializer = (PsiClassInitializer)keyword.getParent().getParent(); if (PsiUtilCore.hasErrorElementChild(initializer)) return null; String message = JavaErrorMessages.message("static.declaration.in.inner.class"); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, keyword, message); + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); IntentionAction fix1 = QUICK_FIX_FACTORY.createModifierListFix(initializer, PsiModifier.STATIC, false, false); - QuickFixAction.registerQuickFixAction(errorResult, fix1); + QuickFixAction.registerQuickFixAction(result, fix1); PsiClass owner = (PsiClass)keyword.getParent().getParent().getParent(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(owner, PsiModifier.STATIC, true, false); - QuickFixAction.registerQuickFixAction(errorResult, fix); - return errorResult; + QuickFixAction.registerQuickFixAction(result, fix); + return result; } private static PsiElement getEnclosingStaticClass(PsiKeyword keyword, Class<?> parentClass) { @@ -360,7 +362,7 @@ public class HighlightClassUtil { .parent(PsiMatchers.hasClass(parentClass)) .parent(PsiMatchers.hasClass(PsiClass.class)) .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false)) - .parent(PsiMatchers.hasClass(new Class[]{PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class})) + .parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class)) .getElement(); } @@ -372,12 +374,12 @@ public class HighlightClassUtil { .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, true)) .parent(PsiMatchers.hasClass(PsiClass.class)) .dot(PsiMatchers.hasModifier(PsiModifier.STATIC, false)) - .parent(PsiMatchers.hasClass(new Class[]{PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class})) + .parent(PsiMatchers.hasClass(PsiClass.class, PsiDeclarationStatement.class, PsiNewExpression.class, PsiEnumConstant.class)) .getElement() == null) { return null; } PsiClass aClass = (PsiClass)keyword.getParent(); - if (PsiUtilCore.hasErrorElementChild(aClass) || (aClass.getQualifiedName() == null && !aClass.isInterface())) return null; + if (PsiUtilCore.hasErrorElementChild(aClass) || aClass.getQualifiedName() == null && !aClass.isInterface()) return null; // highlight 'static' keyword if any, or class or interface if not PsiElement context = null; PsiModifierList modifierList = aClass.getModifierList(); @@ -388,12 +390,12 @@ public class HighlightClassUtil { break; } } - TextRange textRange = context == null ? null : context.getTextRange(); - if (textRange == null) { - textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); + TextRange range = context == null ? null : context.getTextRange(); + if (range == null) { + range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); } String message = JavaErrorMessages.message("static.declaration.in.inner.class"); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create(); if (context != keyword) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.STATIC, false, false); QuickFixAction.registerQuickFixAction(errorResult, fix); @@ -423,7 +425,8 @@ public class HighlightClassUtil { if (aClass.isEnum()) { boolean isExtends = list.equals(aClass.getExtendsList()); if (isExtends) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("extends.after.enum")); + String description = JavaErrorMessages.message("extends.after.enum"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).create(); } } } @@ -437,13 +440,14 @@ public class HighlightClassUtil { if (aClass.isInterface()) { boolean isImplements = list.equals(aClass.getImplementsList()); if (isImplements) { - final HighlightInfo highlightInfo = - HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, JavaErrorMessages.message("implements.after.interface")); + String description = JavaErrorMessages.message("implements.after.interface"); + HighlightInfo result = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).create(); final PsiClassType[] referencedTypes = list.getReferencedTypes(); if (referencedTypes.length > 0) { - QuickFixAction.registerQuickFixAction(highlightInfo, new ChangeExtendsToImplementsFix(aClass, referencedTypes[0])); + QuickFixAction.registerQuickFixAction(result, new ChangeExtendsToImplementsFix(aClass, referencedTypes[0])); } - return highlightInfo; + return result; } } } @@ -463,7 +467,7 @@ public class HighlightClassUtil { PsiClass extendFrom = (PsiClass)resolveResult.getElement(); if (extendFrom.isInterface() != mustBeInterface) { String message = JavaErrorMessages.message(mustBeInterface ? "interface.expected" : "no.interface.expected"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(message).create(); PsiClassType type = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(ref); QuickFixAction.registerQuickFixAction(errorResult, new ChangeExtendsToImplementsFix(aClass, type)); @@ -476,7 +480,8 @@ public class HighlightClassUtil { HighlightInfo errorResult = null; if (superClass.hasModifierProperty(PsiModifier.FINAL) || superClass.isEnum()) { String message = JavaErrorMessages.message("inheritance.from.final.class", superClass.getQualifiedName()); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, message); + errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(message).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(superClass, PsiModifier.FINAL, false, false); QuickFixAction.registerQuickFixAction(errorResult, fix); } @@ -523,7 +528,7 @@ public class HighlightClassUtil { public static HighlightInfo checkBaseClassDefaultConstructorProblem(PsiClass aClass, RefCountHolder refCountHolder, PsiResolveHelper resolveHelper, - TextRange textRange, + TextRange range, @NotNull PsiClassType[] handledExceptions) { PsiClass baseClass = aClass.getSuperClass(); if (baseClass == null) return null; @@ -538,7 +543,7 @@ public class HighlightClassUtil { // it is an error if base ctr throws exceptions String description = checkDefaultConstructorThrowsException(constructor, handledExceptions); if (description != null) { - final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new CreateConstructorMatchingSuperFix(aClass)); return info; } @@ -552,7 +557,7 @@ public class HighlightClassUtil { String description = JavaErrorMessages.message("no.default.constructor.available", HighlightUtil.formatClass(baseClass)); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new CreateConstructorMatchingSuperFix(aClass)); return info; @@ -561,8 +566,9 @@ public class HighlightClassUtil { @Nullable static HighlightInfo checkInterfaceCannotBeLocal(PsiClass aClass) { if (PsiUtil.isLocalClass(aClass)) { - TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, JavaErrorMessages.message("interface.cannot.be.local")); + TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); + String description = JavaErrorMessages.message("interface.cannot.be.local"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); } return null; } @@ -572,8 +578,8 @@ public class HighlightClassUtil { PsiClass circularClass = getCircularClass(aClass, new HashSet<PsiClass>()); if (circularClass != null) { String description = JavaErrorMessages.message("cyclic.inheritance", HighlightUtil.formatClass(circularClass)); - TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); } return null; } @@ -620,7 +626,7 @@ public class HighlightClassUtil { } if (dupCount > 1) { String description = JavaErrorMessages.message("duplicate.class", HighlightUtil.formatClass(aClass)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } return null; } @@ -640,9 +646,7 @@ public class HighlightClassUtil { PsiElement resolved = importStatement.resolve(); if (resolved instanceof PsiClass && !resolved.equals(aClass) && Comparing.equal(aClass.getName(), ((PsiClass)resolved).getName(), true)) { String description = JavaErrorMessages.message("class.already.imported", HighlightUtil.formatClass(aClass, false)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - elementToHighlight, - description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description).create(); } } return null; @@ -658,9 +662,8 @@ public class HighlightClassUtil { if (!aClass.isInterface() && referencedTypes.length > 1 && aClass.getExtendsList() == list) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - list, - JavaErrorMessages.message("class.cannot.extend.multiple.classes")); + String description = JavaErrorMessages.message("class.cannot.extend.multiple.classes"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).create(); } return null; @@ -669,7 +672,8 @@ public class HighlightClassUtil { @Nullable public static HighlightInfo checkThingNotAllowedInInterface(PsiElement element, PsiClass aClass) { if (aClass == null || !aClass.isInterface()) return null; - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, JavaErrorMessages.message("not.allowed.in.interface")); + String description = JavaErrorMessages.message("not.allowed.in.interface"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } @Nullable @@ -678,9 +682,9 @@ public class HighlightClassUtil { if (qualifier == null) return null; PsiType type = expression.getType(); if (type instanceof PsiArrayType) { - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - expression, - JavaErrorMessages.message("invalid.qualified.new")); + String description = JavaErrorMessages.message("invalid.qualified.new"); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new RemoveNewQualifierFix(expression, null)); return info; } @@ -688,9 +692,8 @@ public class HighlightClassUtil { HighlightInfo info = null; if (aClass != null) { if (aClass.hasModifierProperty(PsiModifier.STATIC)) { - info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - expression, - JavaErrorMessages.message("qualified.new.of.static.class")); + String description = JavaErrorMessages.message("qualified.new.of.static.class"); + info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); if (!aClass.isEnum()) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.STATIC, false, false); QuickFixAction.registerQuickFixAction(info, fix); @@ -699,9 +702,8 @@ public class HighlightClassUtil { } else if (aClass instanceof PsiAnonymousClass) { final PsiClass baseClass = PsiUtil.resolveClassInType(((PsiAnonymousClass)aClass).getBaseClassType()); if (baseClass != null && baseClass.isInterface()) { - info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - expression, - "Anonymous class implements interface; cannot have qualifier for new"); + info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip("Anonymous class implements interface; cannot have qualifier for new").create(); } } QuickFixAction.registerQuickFixAction(info, new RemoveNewQualifierFix(expression, aClass)); @@ -741,7 +743,8 @@ public class HighlightClassUtil { return null; } if (!(resolved instanceof PsiClass)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, JavaErrorMessages.message("class.name.expected")); + String description = JavaErrorMessages.message("class.name.expected"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(extendRef).descriptionAndTooltip(description).create(); } final HighlightInfo[] infos = new HighlightInfo[1]; extendRef.accept(new JavaRecursiveElementWalkingVisitor() { @@ -762,7 +765,7 @@ public class HighlightClassUtil { String description = JavaErrorMessages.message("private.symbol", HighlightUtil.formatClass(base), HighlightUtil.formatClass(baseClass)); - infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, description); + infos[0] = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(extendRef).descriptionAndTooltip(description).create(); return; } @@ -772,7 +775,7 @@ public class HighlightClassUtil { if (resolve == resolved && baseClass != null && !PsiTreeUtil.isAncestor(baseClass, extendRef, true) && !hasEnclosingInstanceInScope(baseClass, extendRef, true, true) && !qualifiedNewCalledInConstructors(aClass, baseClass)) { String description = JavaErrorMessages.message("no.enclosing.instance.in.scope", HighlightUtil.formatClass(baseClass)); - infos[0] = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, extendRef, description); + infos[0] = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(extendRef).descriptionAndTooltip(description).create(); } } } @@ -895,7 +898,8 @@ public class HighlightClassUtil { return HighlightUtil.checkAssignability(outerType, null, qualifier, qualifier); } } else { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, qualifier, "'" + HighlightUtil.formatClass(targetClass) + "' is not an inner class"); + String description = "'" + HighlightUtil.formatClass(targetClass) + "' is not an inner class"; + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description).create(); } } return null; @@ -908,14 +912,15 @@ public class HighlightClassUtil { PsiElement elementToHighlight) { if (outerClass != null && !PsiTreeUtil.isContextAncestor(outerClass, place, false)) { String description = JavaErrorMessages.message("is.not.an.enclosing.class", HighlightUtil.formatClass(outerClass)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description).create(); } PsiModifierListOwner staticParent = PsiUtil.getEnclosingStaticElement(place, outerClass); if (staticParent != null) { String element = outerClass == null ? "" : HighlightUtil.formatClass(outerClass) + "." + (place instanceof PsiSuperExpression ? PsiKeyword.SUPER : PsiKeyword.THIS); String description = JavaErrorMessages.message("cannot.be.referenced.from.static.context", element); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, elementToHighlight, description); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description).create(); // make context not static or referenced class static IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(staticParent, PsiModifier.STATIC, false, false); QuickFixAction.registerQuickFixAction(highlightInfo, fix); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index 47fa9a8a2f1c..1c3d5e0defd9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -65,10 +65,9 @@ public class HighlightControlFlowUtil { final PsiElement context = rBrace == null ? body.getLastChild() : rBrace; - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - context, - JavaErrorMessages.message("missing.return.statement")); + String description = JavaErrorMessages.message("missing.return.statement"); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(description).create(); final PsiElement parent = body.getParent(); if (parent instanceof PsiMethod) { final PsiMethod method = (PsiMethod)parent; @@ -103,10 +102,8 @@ public class HighlightControlFlowUtil { final ControlFlow controlFlow = getControlFlowNoConstantEvaluate(codeBlock); final PsiElement unreachableStatement = ControlFlowUtil.getUnreachableStatement(controlFlow); if (unreachableStatement != null) { - return HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - unreachableStatement, - JavaErrorMessages.message("unreachable.statement")); + String description = JavaErrorMessages.message("unreachable.statement"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(unreachableStatement).descriptionAndTooltip(description).create(); } } catch (AnalysisCanceledException e) { @@ -291,7 +288,7 @@ public class HighlightControlFlowUtil { String description = JavaErrorMessages.message("variable.not.initialized", field.getName()); TextRange range = HighlightNamesUtil.getFieldDeclarationTextRange(field); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range.getStartOffset(), range.getEndOffset(), description); + HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field)); QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new InitializeFinalFieldInConstructorFix(field)); final PsiClass containingClass = field.getContainingClass(); @@ -435,10 +432,8 @@ public class HighlightControlFlowUtil { if (codeBlockProblems.contains(expression)) { final String name = expression.getElement().getText(); String description = JavaErrorMessages.message("variable.not.initialized", name); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - expression, - description); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new AddVariableInitializerFix(variable)); return highlightInfo; } @@ -561,10 +556,8 @@ public class HighlightControlFlowUtil { if (alreadyAssigned) { String description = JavaErrorMessages.message("variable.already.assigned", variable.getName()); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - expression, - description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false); QuickFixAction.registerQuickFixAction(highlightInfo, fix); QuickFixAction.registerQuickFixAction(highlightInfo, new DeferFinalAssignmentFix(variable, expression)); @@ -595,10 +588,8 @@ public class HighlightControlFlowUtil { 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( - HighlightInfoType.ERROR, - expression, - description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix((PsiVariable)resolved, PsiModifier.FINAL, false, false); QuickFixAction.registerQuickFixAction(highlightInfo, fix); return highlightInfo; @@ -636,10 +627,8 @@ public class HighlightControlFlowUtil { if (!canWriteToFinal(variable, expression, reference)) { final String name = variable.getName(); String description = JavaErrorMessages.message("assignment.to.final.variable", name); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - expression, - description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression); if (innerClass == null || variable instanceof PsiField) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false); @@ -705,19 +694,20 @@ public class HighlightControlFlowUtil { } final String description = JavaErrorMessages.message("variable.must.be.final", context.getText()); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new VariableAccessFromInnerClassFix(variable, innerClass)); return highlightInfo; - } else { - final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class); - if (lambdaExpression != null && !PsiTreeUtil.isAncestor(lambdaExpression, variable, true)) { - final PsiElement parent = variable.getParent(); - if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) { - return null; - } - if (!isEffectivelyFinal(variable, lambdaExpression, context)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, "Variable used in lambda expression should be effectively final"); - } + } + final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class); + if (lambdaExpression != null && !PsiTreeUtil.isAncestor(lambdaExpression, variable, true)) { + final PsiElement parent = variable.getParent(); + if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) { + return null; + } + if (!isEffectivelyFinal(variable, lambdaExpression, context)) { + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(context).descriptionAndTooltip( + "Variable used in lambda expression should be effectively final").create(); } } return null; @@ -802,10 +792,8 @@ public class HighlightControlFlowUtil { final ControlFlow controlFlow = getControlFlowNoConstantEvaluate(body); final int completionReasons = ControlFlowUtil.getCompletionReasons(controlFlow, 0, controlFlow.getSize()); if ((completionReasons & ControlFlowUtil.NORMAL_COMPLETION_REASON) == 0) { - return HighlightInfo.createHighlightInfo( - HighlightInfoType.ERROR, - body, - JavaErrorMessages.message("initializer.must.be.able.to.complete.normally")); + String description = JavaErrorMessages.message("initializer.must.be.able.to.complete.normally"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(body).descriptionAndTooltip(description).create(); } } catch (AnalysisCanceledException e) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index d7f106a4852b..f2afaa1b66e0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -87,7 +87,7 @@ public class HighlightMethodUtil { final boolean includeRealPositionInfo) { int superAccessLevel = PsiUtil.getAccessLevel(superMethod.getModifierList()); if (accessLevel < superAccessLevel) { - String message = JavaErrorMessages.message("weaker.privileges", + String description = JavaErrorMessages.message("weaker.privileges", createClashMethodMessage(method, superMethod, true), accessModifier, PsiUtil.getAccessModifier(superAccessLevel)); @@ -104,7 +104,7 @@ public class HighlightMethodUtil { else { textRange = TextRange.EMPTY_RANGE; } - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(method, PsiUtil.getAccessModifier(superAccessLevel), true, false); QuickFixAction.registerQuickFixAction(highlightInfo, fix); return highlightInfo; @@ -177,9 +177,9 @@ public class HighlightMethodUtil { PsiType substitutedSuperReturnType, PsiType returnType, String detailMessage) { - String message = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage); + String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage); TextRange textRange = includeRealPositionInfo ? methodToHighlight.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE; - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, substitutedSuperReturnType, false); QuickFixAction.registerQuickFixAction(errorResult, fix); QuickFixAction.registerQuickFixAction(errorResult, new SuperMethodReturnFix(superMethod, returnType)); @@ -202,14 +202,12 @@ public class HighlightMethodUtil { private static HighlightInfo checkSuperMethodIsFinal(PsiMethod method, PsiMethod superMethod) { // strange things happen when super method is from Object and method from interface if (superMethod.hasModifierProperty(PsiModifier.FINAL)) { - String message = JavaErrorMessages.message("final.method.override", + String description = JavaErrorMessages.message("final.method.override", HighlightUtil.formatMethod(method), HighlightUtil.formatMethod(superMethod), HighlightUtil.formatClass(superMethod.getContainingClass())); TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method); - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - textRange, - message); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(superMethod, PsiModifier.FINAL, false, true); QuickFixAction.registerQuickFixAction(errorResult, fix); return errorResult; @@ -256,7 +254,7 @@ public class HighlightMethodUtil { if (superContainingClass != null && !aClass.isInheritor(superContainingClass, true)) continue; } PsiClassType exception = checkedExceptions.get(index); - String message = JavaErrorMessages.message("overridden.method.does.not.throw", + String description = JavaErrorMessages.message("overridden.method.does.not.throw", createClashMethodMessage(method, superMethod, true), HighlightUtil.formatType(exception)); TextRange textRange; @@ -267,7 +265,7 @@ public class HighlightMethodUtil { else { textRange = TextRange.EMPTY_RANGE; } - HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createMethodThrowsFix(method, exception, false, false)); QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createMethodThrowsFix(superMethod, exception, true, true)); return errorResult; @@ -340,10 +338,9 @@ public class HighlightMethodUtil { String description = JavaErrorMessages.message("wrong.method.arguments", methodName, containerName, argTypes); String toolTip = parent instanceof PsiClass && !ApplicationManager.getApplication().isUnitTestMode() ? createMismatchedArgumentsHtmlTooltip(candidateInfo, list) : description; - highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, description, toolTip); + highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).description(description).escapedToolTip(toolTip).navigationShift(+1).create(); if (highlightInfo != null) { registerMethodCallIntentions(highlightInfo, methodCall, list, resolveHelper); - highlightInfo.navigationShift = +1; } } else { @@ -358,7 +355,9 @@ public class HighlightMethodUtil { } } else { - highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, methodCall, JavaErrorMessages.message("method.call.expected")); + String description = JavaErrorMessages.message("method.call.expected"); + highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(description).create(); if (resolved instanceof PsiClass) { QuickFixAction.registerQuickFixAction(highlightInfo, new InsertNewFix(methodCall, (PsiClass)resolved)); } @@ -397,7 +396,7 @@ public class HighlightMethodUtil { @Nullable static HighlightInfo checkAmbiguousMethodCall(final PsiReferenceExpression referenceToMethod, JavaResolveResult[] resolveResults, - final PsiExpressionList list, + @NotNull PsiExpressionList list, final PsiElement element, final JavaResolveResult resolveResult, final PsiMethodCallExpression methodCall, final PsiResolveHelper resolveHelper) { @@ -459,23 +458,24 @@ public class HighlightMethodUtil { } toolTip = XmlStringUtil.escapeString(description); } - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(highlightInfoType, elementToHighlight, description, toolTip); + HighlightInfo info = + HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description).escapedToolTip(toolTip).create(); if (methodCandidate2 == null) { - registerMethodCallIntentions(highlightInfo, methodCall, list, resolveHelper); + registerMethodCallIntentions(info, methodCall, list, resolveHelper); } if (!resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect() && methodCandidate2 != null) { - HighlightUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, highlightInfo, resolveResult.getCurrentFileResolveScope()); + HighlightUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, info, resolveResult.getCurrentFileResolveScope()); } if (element != null && !resolveResult.isStaticsScopeCorrect()) { - HighlightUtil.registerStaticProblemQuickFixAction(element, highlightInfo, referenceToMethod); + HighlightUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod); } TextRange fixRange = getFixRange(elementToHighlight); - CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, highlightInfo, fixRange); - PermuteArgumentsFix.registerFix(highlightInfo, methodCall, candidates, fixRange); - WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), highlightInfo); - ChangeParameterClassFix.registerQuickFixActions(methodCall, list, highlightInfo); - return highlightInfo; + CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, info, fixRange); + PermuteArgumentsFix.registerFix(info, methodCall, candidates, fixRange); + WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), info); + ChangeParameterClassFix.registerQuickFixActions(methodCall, list, info); + return info; } private static MethodCandidateInfo[] toMethodCandidates(JavaResolveResult[] resolveResults) { @@ -534,6 +534,7 @@ public class HighlightMethodUtil { } } + @NotNull private static String createAmbiguousMethodHtmlTooltip(MethodCandidateInfo[] methodCandidates) { return JavaErrorMessages.message("ambiguous.method.html.tooltip", Integer.valueOf(methodCandidates[0].getElement().getParameterList().getParametersCount() + 2), @@ -629,12 +630,9 @@ public class HighlightMethodUtil { String methodName, PsiSubstitutor substitutor, PsiClass aClass) { - if (Math.max(parameters.length, list.getExpressions().length) <= 2) { - return createShortMismatchedArgumentsHtmlTooltip(list, parameters, methodName, substitutor, aClass); - } - else { - return createLongMismatchedArgumentsHtmlTooltip(list, parameters, methodName, substitutor, aClass); - } + return Math.max(parameters.length, list.getExpressions().length) <= 2 + ? createShortMismatchedArgumentsHtmlTooltip(list, parameters, methodName, substitutor, aClass) + : createLongMismatchedArgumentsHtmlTooltip(list, parameters, methodName, substitutor, aClass); } @Language("HTML") @@ -712,7 +710,7 @@ public class HighlightMethodUtil { PsiType type = expression.getType(); boolean showShort = showShortType(i, parameters, expressions, substitutor); - @NonNls String mismatchColor = showShort ? null : (UIUtil.isUnderDarcula() ? "ff6464" : "red"); + @NonNls String mismatchColor = showShort ? null : UIUtil.isUnderDarcula() ? "ff6464" : "red"; ms += "<td> " + "<b><nobr>" + (i == 0 ? "(" : "") + "<font " + (showShort ? "" : "color=" + mismatchColor) + ">" + XmlStringUtil.escapeString(showShort ? type.getPresentableText() : HighlightUtil.formatType(type)) @@ -767,9 +765,8 @@ public class HighlightMethodUtil { int start = method.getModifierList().getTextRange().getStartOffset(); int end = method.getTextRange().getEndOffset(); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - start, end, - JavaErrorMessages.message("missing.method.body")); + String description = JavaErrorMessages.message("missing.method.body"); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(start, end).descriptionAndTooltip(description).create(); if (HighlightUtil.getIncompatibleModifier(PsiModifier.ABSTRACT, method.getModifierList()) == null) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.ABSTRACT, true, false); QuickFixAction.registerQuickFixAction(errorResult, fix); @@ -788,9 +785,9 @@ public class HighlightMethodUtil { && !aClass.hasModifierProperty(PsiModifier.ABSTRACT) && !aClass.isEnum() && !PsiUtilCore.hasErrorElementChild(method)) { - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - elementToHighlight, - JavaErrorMessages.message("abstract.method.in.non.abstract.class")); + String description = JavaErrorMessages.message("abstract.method.in.non.abstract.class"); + errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(description).create(); if (method.getBody() != null) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.ABSTRACT, false, false); QuickFixAction.registerQuickFixAction(errorResult, fix); @@ -811,8 +808,9 @@ public class HighlightMethodUtil { if (aClass != null) { String className = aClass instanceof PsiAnonymousClass ? null : aClass.getName(); if (className == null || !Comparing.strEqual(methodName, className)) { - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, method.getNameIdentifier(), - JavaErrorMessages.message("missing.return.type")); + PsiElement element = method.getNameIdentifier(); + String description = JavaErrorMessages.message("missing.return.type"); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); if (className != null) { QuickFixAction.registerQuickFixAction(errorResult, new RenameElementFix(method, className)); } @@ -841,11 +839,11 @@ public class HighlightMethodUtil { methodCount++; } if (methodCount > 1) { - String message = JavaErrorMessages.message("duplicate.method", + String description = JavaErrorMessages.message("duplicate.method", HighlightUtil.formatMethod(method), HighlightUtil.formatClass(aClass)); TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } return null; } @@ -858,35 +856,36 @@ public class HighlightMethodUtil { boolean isExtension = method.hasModifierProperty(PsiModifier.DEFAULT); boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC); - String message = null; + String description = null; if (hasNoBody) { if (isExtension) { - message = JavaErrorMessages.message("extension.method.should.have.a.body"); - } else if (isInterface && isStatic) { - message = "Static methods in interfaces should have a body"; + description = JavaErrorMessages.message("extension.method.should.have.a.body"); + } + else if (isInterface && isStatic) { + description = "Static methods in interfaces should have a body"; } } else if (isInterface) { if (!isExtension && !isStatic) { - message = JavaErrorMessages.message("interface.methods.cannot.have.body"); + description = JavaErrorMessages.message("interface.methods.cannot.have.body"); } else if (isExtension) { return HighlightUtil.checkExtensionMethodsFeature(method); } } else if (isExtension) { - message = JavaErrorMessages.message("extension.method.in.class"); + description = JavaErrorMessages.message("extension.method.in.class"); } else if (method.hasModifierProperty(PsiModifier.ABSTRACT)) { - message = JavaErrorMessages.message("abstract.methods.cannot.have.a.body"); + description = JavaErrorMessages.message("abstract.methods.cannot.have.a.body"); } else if (method.hasModifierProperty(PsiModifier.NATIVE)) { - message = JavaErrorMessages.message("native.methods.cannot.have.a.body"); + description = JavaErrorMessages.message("native.methods.cannot.have.a.body"); } - if (message == null) return null; + if (description == null) return null; TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); if (hasNoBody) { QuickFixAction.registerQuickFixAction(info, new DeleteMethodBodyFix(method)); } @@ -912,7 +911,8 @@ public class HighlightMethodUtil { } } String message = JavaErrorMessages.message("constructor.call.must.be.first.statement", expression.getText() + "()"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression.getParent(), message); + PsiElement element = expression.getParent(); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create(); } @@ -923,7 +923,7 @@ public class HighlightMethodUtil { PsiMethod method = methodCallExpression.resolveMethod(); if (method != null && method.hasModifierProperty(PsiModifier.ABSTRACT)) { String message = JavaErrorMessages.message("direct.abstract.method.access", HighlightUtil.formatMethod(method)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, methodCallExpression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCallExpression).descriptionAndTooltip(message).create(); } } return null; @@ -1010,13 +1010,13 @@ public class HighlightMethodUtil { ? "static.method.cannot.override.instance.method" : "instance.method.cannot.override.static.method"; - String message = JavaErrorMessages.message(messageKey, + String description = JavaErrorMessages.message(messageKey, HighlightUtil.formatMethod(method), HighlightUtil.formatClass(aClass), HighlightUtil.formatMethod(superMethod), HighlightUtil.formatClass(superClass)); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, message); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); if (!isSuperMethodStatic || HighlightUtil.getIncompatibleModifier(PsiModifier.STATIC, modifierList) == null) { IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.STATIC, isSuperMethodStatic, false); QuickFixAction.registerQuickFixAction(info, fix); @@ -1029,7 +1029,7 @@ public class HighlightMethodUtil { return info; } - if (isMethodStatic && isSuperMethodStatic) { + if (isMethodStatic) { int accessLevel = PsiUtil.getAccessLevel(modifierList); String accessModifier = PsiUtil.getAccessModifier(accessLevel); HighlightInfo info = isWeaker(method, modifierList, accessModifier, accessLevel, superMethod, true); @@ -1074,7 +1074,7 @@ public class HighlightMethodUtil { } static HighlightInfo checkOverrideEquivalentInheritedMethods(PsiClass aClass) { - String errorDescription = null; + String description = null; final Collection<HierarchicalMethodSignature> visibleSignatures = aClass.getVisibleSignatures(); PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper(); Ultimate: @@ -1101,13 +1101,13 @@ public class HighlightMethodUtil { highlightInfo = checkMethodIncompatibleReturnType(signature, superSignatures, false); } } - if (highlightInfo != null) errorDescription = highlightInfo.description; + if (highlightInfo != null) description = highlightInfo.description; if (method.hasModifierProperty(PsiModifier.STATIC)) { for (HierarchicalMethodSignature superSignature : superSignatures) { PsiMethod superMethod = superSignature.getMethod(); if (!superMethod.hasModifierProperty(PsiModifier.STATIC)) { - errorDescription = JavaErrorMessages.message("static.method.cannot.override.instance.method", + description = JavaErrorMessages.message("static.method.cannot.override.instance.method", HighlightUtil.formatMethod(method), HighlightUtil.formatClass(containingClass), HighlightUtil.formatMethod(superMethod), @@ -1118,26 +1118,24 @@ public class HighlightMethodUtil { continue; } - if (errorDescription == null) { + if (description == null) { highlightInfo = checkMethodIncompatibleThrows(signature, superSignatures, false, aClass); - if (highlightInfo != null) errorDescription = highlightInfo.description; + if (highlightInfo != null) description = highlightInfo.description; } - if (errorDescription == null) { + if (description == null) { highlightInfo = checkMethodWeakerPrivileges(signature, superSignatures, false); - if (highlightInfo != null) errorDescription = highlightInfo.description; + if (highlightInfo != null) description = highlightInfo.description; } - if (errorDescription != null) break; + if (description != null) break; } - if (errorDescription != null) { + if (description != null) { // show error info at the class level TextRange textRange = HighlightNamesUtil.getClassDeclarationTextRange(aClass); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - textRange, - errorDescription); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } return null; } @@ -1157,9 +1155,7 @@ public class HighlightMethodUtil { if (unhandled.isEmpty()) return null; String description = HighlightUtil.getUnhandledExceptionsDescriptor(unhandled); TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, - textRange, - description); + HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); for (PsiClassType exception : unhandled) { QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createMethodThrowsFix(method, exception, true, false)); } @@ -1170,7 +1166,8 @@ public class HighlightMethodUtil { static HighlightInfo checkRecursiveConstructorInvocation(PsiMethod method) { if (HighlightControlFlowUtil.isRecursivelyCalledConstructor(method)) { TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(method); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, JavaErrorMessages.message("recursive.constructor.invocation")); + String description = JavaErrorMessages.message("recursive.constructor.invocation"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } return null; } @@ -1215,7 +1212,7 @@ public class HighlightMethodUtil { if (list == null) return; PsiClass aClass = typeResolveResult.getElement(); if (aClass == null) return; - final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(constructorCall.getProject()).getResolveHelper(); + final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(holder.getProject()).getResolveHelper(); PsiClass accessObjectClass = null; if (constructorCall instanceof PsiNewExpression) { PsiExpression qualifier = ((PsiNewExpression)constructorCall).getQualifier(); @@ -1225,7 +1222,9 @@ public class HighlightMethodUtil { } if (classReference != null && !resolveHelper.isAccessible(aClass, constructorCall, accessObjectClass)) { String description = HighlightUtil.buildProblemWithAccessDescription(classReference, typeResolveResult); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, classReference.getReferenceNameElement(), description); + PsiElement element = classReference.getReferenceNameElement(); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); HighlightUtil.registerAccessQuickFixAction(aClass, classReference, info, null); holder.add(info); return; @@ -1238,12 +1237,11 @@ public class HighlightMethodUtil { String argTypes = buildArgTypesList(list); String description = JavaErrorMessages.message("wrong.constructor.arguments", constructorName+"()", argTypes); String tooltip = createMismatchedArgumentsHtmlTooltip(list, PsiParameter.EMPTY_ARRAY, constructorName, PsiSubstitutor.EMPTY, aClass); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, description, tooltip); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).description(description).escapedToolTip(tooltip).navigationShift(+1).create(); QuickFixAction.registerQuickFixAction(info, constructorCall.getTextRange(), new CreateConstructorFromCallFix(constructorCall)); if (classReference != null) { ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info,getFixRange(list)); } - info.navigationShift = +1; holder.add(info); return; } @@ -1252,8 +1250,8 @@ public class HighlightMethodUtil { } else if (aClass.isInterface() && constructorCall instanceof PsiNewExpression) { final PsiReferenceParameterList typeArgumentList = ((PsiNewExpression)constructorCall).getTypeArgumentList(); if (typeArgumentList.getTypeArguments().length > 0) { - holder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeArgumentList, - "Anonymous class implements interface; cannot have type arguments")); + holder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeArgumentList) + .descriptionAndTooltip("Anonymous class implements interface; cannot have type arguments").create()); } } } @@ -1282,14 +1280,13 @@ public class HighlightMethodUtil { String name = aClass.getName(); name += buildArgTypesList(list); String description = JavaErrorMessages.message("cannot.resolve.constructor", name); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, description, XmlStringUtil.escapeString(description)); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(description).navigationShift(+1).create(); QuickFixAction.registerQuickFixAction(info, constructorCall.getTextRange(), new CreateConstructorFromCallFix(constructorCall)); if (classReference != null) { ConstructorParametersFixer.registerFixActions(classReference, constructorCall, info,getFixRange(list)); PermuteArgumentsFix.registerFix(info, constructorCall, toMethodCandidates(results), getFixRange(list)); } WrapExpressionFix.registerWrapAction(results, list.getExpressions(), info); - info.navigationShift = +1; holder.add(info); ChangeStringLiteralToCharInMethodCallFix.registerFixes(constructors, constructorCall, info); } @@ -1305,7 +1302,7 @@ public class HighlightMethodUtil { String description = JavaErrorMessages.message("wrong.method.arguments", constructorName, containerName, argTypes); String toolTip = createMismatchedArgumentsHtmlTooltip(result, list); PsiElement infoElement = list.getTextLength() > 0 ? list : constructorCall; - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, infoElement, description, toolTip); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(infoElement).description(description).escapedToolTip(toolTip).navigationShift(+1).create(); if (info != null) { QuickFixAction.registerQuickFixAction(info, constructorCall.getTextRange(), new CreateConstructorFromCallFix(constructorCall)); if (classReference != null) { @@ -1317,22 +1314,19 @@ public class HighlightMethodUtil { ChangeParameterClassFix.registerQuickFixActions(constructorCall, list, info); QuickFixAction.registerQuickFixAction(info, getFixRange(list), new SurroundWithArrayFix(constructorCall)); } - info.navigationShift = +1; holder.add(info); ChangeStringLiteralToCharInMethodCallFix.registerFixes(constructors, constructorCall, info); } } else { - HighlightInfo highlightInfo; if (constructorCall instanceof PsiNewExpression) { - highlightInfo = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor, - ((PsiNewExpression)constructorCall).getTypeArgumentList(), - result.getSubstitutor(), false); + HighlightInfo highlightInfo = GenericsHighlightUtil.checkReferenceTypeArgumentList(constructor, + ((PsiNewExpression)constructorCall) + .getTypeArgumentList(), + result.getSubstitutor(), false); if (highlightInfo != null) { holder.add(highlightInfo); - return; } - } } } @@ -1341,8 +1335,8 @@ public class HighlightMethodUtil { private static HighlightInfo buildAccessProblem(@NotNull PsiJavaCodeReferenceElement classReference, JavaResolveResult result, PsiMember elementToFix) { String description = HighlightUtil.buildProblemWithAccessDescription(classReference, result); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, classReference, description); - info.navigationShift = +1; + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classReference).descriptionAndTooltip( + description).navigationShift(+1).create(); if (result.isStaticsScopeCorrect()) { HighlightUtil.registerAccessQuickFixAction(elementToFix, classReference, info, result.getCurrentFileResolveScope()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java index ea3345ae3da3..8bb1be302162 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java @@ -25,6 +25,7 @@ import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; @@ -44,6 +45,8 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public class HighlightNamesUtil { + private static final Logger LOG = Logger.getInstance("#" + HighlightNamesUtil.class.getName()); + @Nullable public static HighlightInfo highlightMethodName(@NotNull PsiMethod method, final PsiElement elementToHighlight, @@ -61,8 +64,11 @@ public class HighlightNamesUtil { HighlightInfoType type = getMethodNameHighlightType(method, isDeclaration, isInherited); if (type != null && elementToHighlight != null) { TextAttributes attributes = mergeWithScopeAttributes(method, type, colorsScheme); - HighlightInfo info = HighlightInfo.createHighlightInfo(type, elementToHighlight.getTextRange(), null, null, attributes); - if (info != null) return info; + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(type).range(elementToHighlight.getTextRange()); + if (attributes != null) { + builder.textAttributes(attributes); + } + return builder.createUnconditionally(); } return null; } @@ -111,7 +117,11 @@ public class HighlightNamesUtil { range = new TextRange(psiAnnotation.getTextRange().getStartOffset(), range.getEndOffset()); } - return HighlightInfo.createHighlightInfo(type, range, null, null, attributes); + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(type).range(range); + if (attributes != null) { + builder.textAttributes(attributes); + } + return builder.createUnconditionally(); } return null; } @@ -124,9 +134,13 @@ public class HighlightNamesUtil { if (varType != null) { if (variable instanceof PsiField) { TextAttributes attributes = mergeWithScopeAttributes(variable, varType, colorsScheme); - return HighlightInfo.createHighlightInfo(varType, elementToHighlight.getTextRange(), null, null, attributes); + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(varType).range(elementToHighlight.getTextRange()); + if (attributes != null) { + builder.textAttributes(attributes); + } + return builder.createUnconditionally(); } - return HighlightInfo.createHighlightInfo(varType, elementToHighlight, null); + return HighlightInfo.newHighlightInfo(varType).range(elementToHighlight).create(); } return null; } @@ -199,10 +213,10 @@ public class HighlightNamesUtil { @Nullable public static HighlightInfo highlightReassignedVariable(PsiVariable variable, PsiElement elementToHighlight) { if (variable instanceof PsiLocalVariable) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.REASSIGNED_LOCAL_VARIABLE, elementToHighlight, null); + return HighlightInfo.newHighlightInfo(HighlightInfoType.REASSIGNED_LOCAL_VARIABLE).range(elementToHighlight).create(); } if (variable instanceof PsiParameter) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.REASSIGNED_PARAMETER, elementToHighlight, null); + return HighlightInfo.newHighlightInfo(HighlightInfoType.REASSIGNED_PARAMETER).range(elementToHighlight).create(); } return null; } @@ -211,7 +225,7 @@ public class HighlightNamesUtil { PsiFile file = element.getContainingFile(); if (file == null) return null; TextAttributes result = null; - final DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(element.getProject()); + final DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(file.getProject()); List<Pair<NamedScope,NamedScopesHolder>> scopes = daemonCodeAnalyzer.getScopeBasedHighlightingCachedScopes(); for (Pair<NamedScope, NamedScopesHolder> scope : scopes) { NamedScope namedScope = scope.getFirst(); @@ -232,7 +246,9 @@ public class HighlightNamesUtil { public static TextRange getMethodDeclarationTextRange(@NotNull PsiMethod method) { if (method instanceof JspHolderMethod) return TextRange.EMPTY_RANGE; int start = stripAnnotationsFromModifierList(method.getModifierList()); - int end = method.getThrowsList().getTextRange().getEndOffset(); + final TextRange throwsRange = method.getThrowsList().getTextRange(); + LOG.assertTrue(throwsRange != null, method); + int end = throwsRange.getEndOffset(); return new TextRange(start, end); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index dbacc36fc421..f5b78ba3ce6d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -52,10 +52,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.templateLanguages.OuterLanguageElement; 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.util.StringBuilderSpinAllocator; +import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import com.intellij.xml.util.XmlStringUtil; @@ -70,8 +67,6 @@ import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static com.intellij.util.containers.ContainerUtil.newTroveSet; - /** * @author cdr * @since Jul 30, 2002 @@ -93,54 +88,51 @@ public class HighlightUtil extends HighlightUtilBase { static { ourClassIncompatibleModifiers = new THashMap<String, Set<String>>(8); - ourClassIncompatibleModifiers.put(PsiModifier.ABSTRACT, newTroveSet(PsiModifier.FINAL)); - ourClassIncompatibleModifiers.put(PsiModifier.FINAL, newTroveSet(PsiModifier.ABSTRACT)); - ourClassIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourClassIncompatibleModifiers.put(PsiModifier.PRIVATE, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourClassIncompatibleModifiers.put(PsiModifier.PUBLIC, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); - ourClassIncompatibleModifiers.put(PsiModifier.PROTECTED, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); + ourClassIncompatibleModifiers.put(PsiModifier.ABSTRACT, ContainerUtil.newTroveSet(PsiModifier.FINAL)); + ourClassIncompatibleModifiers.put(PsiModifier.FINAL, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT)); + ourClassIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, ContainerUtil.newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourClassIncompatibleModifiers.put(PsiModifier.PRIVATE, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourClassIncompatibleModifiers.put(PsiModifier.PUBLIC, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); + ourClassIncompatibleModifiers.put(PsiModifier.PROTECTED, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); ourClassIncompatibleModifiers.put(PsiModifier.STRICTFP, Collections.<String>emptySet()); ourClassIncompatibleModifiers.put(PsiModifier.STATIC, Collections.<String>emptySet()); ourInterfaceIncompatibleModifiers = new THashMap<String, Set<String>>(7); ourInterfaceIncompatibleModifiers.put(PsiModifier.ABSTRACT, Collections.<String>emptySet()); - ourInterfaceIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourInterfaceIncompatibleModifiers.put(PsiModifier.PRIVATE, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourInterfaceIncompatibleModifiers.put(PsiModifier.PUBLIC, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); - ourInterfaceIncompatibleModifiers.put(PsiModifier.PROTECTED, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); + ourInterfaceIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, ContainerUtil.newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourInterfaceIncompatibleModifiers.put(PsiModifier.PRIVATE, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourInterfaceIncompatibleModifiers.put(PsiModifier.PUBLIC, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); + ourInterfaceIncompatibleModifiers.put(PsiModifier.PROTECTED, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); ourInterfaceIncompatibleModifiers.put(PsiModifier.STRICTFP, Collections.<String>emptySet()); ourInterfaceIncompatibleModifiers.put(PsiModifier.STATIC, Collections.<String>emptySet()); ourMethodIncompatibleModifiers = new THashMap<String, Set<String>>(11); - ourMethodIncompatibleModifiers.put(PsiModifier.ABSTRACT, newTroveSet(PsiModifier.NATIVE, PsiModifier.STATIC, PsiModifier.FINAL, - PsiModifier.PRIVATE, PsiModifier.STRICTFP, PsiModifier.SYNCHRONIZED, - PsiModifier.DEFAULT)); - ourMethodIncompatibleModifiers.put(PsiModifier.NATIVE, newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STRICTFP)); - ourMethodIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourMethodIncompatibleModifiers.put(PsiModifier.PRIVATE, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourMethodIncompatibleModifiers.put(PsiModifier.PUBLIC, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); - ourMethodIncompatibleModifiers.put(PsiModifier.PROTECTED, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); - ourMethodIncompatibleModifiers.put(PsiModifier.STATIC, newTroveSet(PsiModifier.ABSTRACT, PsiModifier.DEFAULT)); - ourMethodIncompatibleModifiers.put(PsiModifier.DEFAULT, newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STATIC)); - ourMethodIncompatibleModifiers.put(PsiModifier.SYNCHRONIZED, newTroveSet(PsiModifier.ABSTRACT)); - ourMethodIncompatibleModifiers.put(PsiModifier.STRICTFP, newTroveSet(PsiModifier.ABSTRACT)); - ourMethodIncompatibleModifiers.put(PsiModifier.FINAL, newTroveSet(PsiModifier.ABSTRACT)); + ourMethodIncompatibleModifiers.put(PsiModifier.ABSTRACT, ContainerUtil.newTroveSet(PsiModifier.NATIVE, PsiModifier.STATIC, PsiModifier.FINAL, PsiModifier.PRIVATE, PsiModifier.STRICTFP, PsiModifier.SYNCHRONIZED, PsiModifier.DEFAULT)); + ourMethodIncompatibleModifiers.put(PsiModifier.NATIVE, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STRICTFP)); + ourMethodIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, ContainerUtil.newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourMethodIncompatibleModifiers.put(PsiModifier.PRIVATE, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourMethodIncompatibleModifiers.put(PsiModifier.PUBLIC, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); + ourMethodIncompatibleModifiers.put(PsiModifier.PROTECTED, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); + ourMethodIncompatibleModifiers.put(PsiModifier.STATIC, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT, PsiModifier.DEFAULT)); + ourMethodIncompatibleModifiers.put(PsiModifier.DEFAULT, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STATIC)); + ourMethodIncompatibleModifiers.put(PsiModifier.SYNCHRONIZED, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT)); + ourMethodIncompatibleModifiers.put(PsiModifier.STRICTFP, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT)); + ourMethodIncompatibleModifiers.put(PsiModifier.FINAL, ContainerUtil.newTroveSet(PsiModifier.ABSTRACT)); ourFieldIncompatibleModifiers = new THashMap<String, Set<String>>(8); - ourFieldIncompatibleModifiers.put(PsiModifier.FINAL, newTroveSet(PsiModifier.VOLATILE)); - ourFieldIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourFieldIncompatibleModifiers.put(PsiModifier.PRIVATE, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); - ourFieldIncompatibleModifiers.put(PsiModifier.PUBLIC, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); - ourFieldIncompatibleModifiers.put(PsiModifier.PROTECTED, newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); + ourFieldIncompatibleModifiers.put(PsiModifier.FINAL, ContainerUtil.newTroveSet(PsiModifier.VOLATILE)); + ourFieldIncompatibleModifiers.put(PsiModifier.PACKAGE_LOCAL, ContainerUtil.newTroveSet(PsiModifier.PRIVATE, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourFieldIncompatibleModifiers.put(PsiModifier.PRIVATE, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PROTECTED)); + ourFieldIncompatibleModifiers.put(PsiModifier.PUBLIC, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PRIVATE, PsiModifier.PROTECTED)); + ourFieldIncompatibleModifiers.put(PsiModifier.PROTECTED, ContainerUtil.newTroveSet(PsiModifier.PACKAGE_LOCAL, PsiModifier.PUBLIC, PsiModifier.PRIVATE)); ourFieldIncompatibleModifiers.put(PsiModifier.STATIC, Collections.<String>emptySet()); ourFieldIncompatibleModifiers.put(PsiModifier.TRANSIENT, Collections.<String>emptySet()); - ourFieldIncompatibleModifiers.put(PsiModifier.VOLATILE, newTroveSet(PsiModifier.FINAL)); + ourFieldIncompatibleModifiers.put(PsiModifier.VOLATILE, ContainerUtil.newTroveSet(PsiModifier.FINAL)); ourClassInitializerIncompatibleModifiers = new THashMap<String, Set<String>>(1); ourClassInitializerIncompatibleModifiers.put(PsiModifier.STATIC, Collections.<String>emptySet()); - ourConstructorNotAllowedModifiers = newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STATIC, PsiModifier.NATIVE, - PsiModifier.FINAL, PsiModifier.STRICTFP, PsiModifier.SYNCHRONIZED); + ourConstructorNotAllowedModifiers = ContainerUtil.newTroveSet(PsiModifier.ABSTRACT, PsiModifier.STATIC, PsiModifier.NATIVE, PsiModifier.FINAL, PsiModifier.STRICTFP, PsiModifier.SYNCHRONIZED); } @Nullable @@ -239,7 +231,7 @@ public class HighlightUtil extends HighlightUtilBase { } @Nullable - private static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiJavaCodeReferenceElement place) { + private static PsiClass getPackageLocalClassInTheMiddle(@NotNull PsiElement place) { if (place instanceof PsiReferenceExpression) { // check for package local classes in the middle PsiReferenceExpression expression = (PsiReferenceExpression)place; @@ -272,16 +264,18 @@ public class HighlightUtil extends HighlightUtilBase { PsiType operandType = operand.getType(); if (operandType == null) return null; if (operandType instanceof PsiLambdaExpressionType) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, "Lambda expression is not expected here"); - } + return HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Lambda expression is not expected here").create(); + } if (operandType instanceof PsiMethodReferenceType) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, "Method reference expression is not expected here"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip( + "Method reference expression is not expected here").create(); } if (TypeConversionUtil.isPrimitiveAndNotNull(operandType) || TypeConversionUtil.isPrimitiveAndNotNull(checkType) || !TypeConversionUtil.areTypesConvertible(operandType, checkType)) { String message = JavaErrorMessages.message("inconvertible.type.cast", formatType(operandType), formatType(checkType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } return null; } @@ -301,7 +295,7 @@ public class HighlightUtil extends HighlightUtilBase { !TypeConversionUtil.areTypesConvertible(operandType, castType) && !RedundantCastUtil.isInPolymorphicCall(expression)) { String message = JavaErrorMessages.message("inconvertible.type.cast", formatType(operandType), formatType(castType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } return null; @@ -324,7 +318,8 @@ public class HighlightUtil extends HighlightUtilBase { } HighlightInfo errorResult = null; if (lValue != null && !TypeConversionUtil.isLValue(lValue)) { - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, lValue, JavaErrorMessages.message("variable.expected")); + String description = JavaErrorMessages.message("variable.expected"); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(lValue).descriptionAndTooltip(description).create(); } return errorResult; @@ -349,7 +344,7 @@ public class HighlightUtil extends HighlightUtilBase { formatType(lType), formatType(rType)); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, assignment, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(assignment).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(errorResult, new ChangeToAppendFix(eqOpSign, lType, assignment)); } return errorResult; @@ -414,7 +409,7 @@ public class HighlightUtil extends HighlightUtilBase { PsiType rType = initializer.getType(); int start = variable.getTypeElement().getTextRange().getStartOffset(); int end = variable.getTextRange().getEndOffset(); - HighlightInfo highlightInfo = checkAssignability(lType, rType, initializer, new TextRange(start, end)); + HighlightInfo highlightInfo = checkAssignability(lType, rType, initializer, new TextRange(start, end), 0); if (highlightInfo != null) { registerChangeVariableTypeFixes(variable, rType, highlightInfo); } @@ -424,11 +419,15 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable static HighlightInfo checkAssignability(PsiType lType, @Nullable PsiType rType, PsiExpression expression, @NotNull PsiElement elementToHighlight) { TextRange textRange = elementToHighlight.getTextRange(); - return checkAssignability(lType, rType, expression, textRange); + return checkAssignability(lType, rType, expression, textRange, 0); } @Nullable - public static HighlightInfo checkAssignability(@Nullable PsiType lType, @Nullable PsiType rType, @Nullable PsiExpression expression, @NotNull TextRange textRange) { + public static HighlightInfo checkAssignability(@Nullable PsiType lType, + @Nullable PsiType rType, + @Nullable PsiExpression expression, + @NotNull TextRange textRange, + int navigationShift) { if (lType == rType) return null; if (expression == null) { if (rType == null || lType == null || TypeConversionUtil.isAssignable(lType, rType)) return null; @@ -439,7 +438,7 @@ public class HighlightUtil extends HighlightUtilBase { if (rType == null) { rType = expression.getType(); } - HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(lType, rType, textRange); + HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(lType, rType, textRange, navigationShift); if (rType != null && expression != null && isCastIntentionApplicable(expression, lType)) { QuickFixAction.registerQuickFixAction(highlightInfo, new AddTypeCastFix(lType, expression)); } @@ -471,13 +470,13 @@ public class HighlightUtil extends HighlightUtilBase { parent = parent.getParent(); } String description; - int navigationShift = 0; HighlightInfo errorResult = null; if (method == null && lambda != null) { //todo check return statements type inside lambda - } else if (method == null && !(parent instanceof JspFile)) { + } + else if (method == null && !(parent instanceof JspFile)) { description = JavaErrorMessages.message("return.outside.method"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, description); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } else { PsiType returnType = method != null ? method.getReturnType() : null/*JSP page returns void*/; @@ -487,14 +486,16 @@ public class HighlightUtil extends HighlightUtilBase { PsiType valueType = returnValue.getType(); if (isMethodVoid) { description = JavaErrorMessages.message("return.from.void.method"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, description); + errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); if (valueType != null) { IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, valueType, true); QuickFixAction.registerQuickFixAction(errorResult, fix); } } else { - errorResult = checkAssignability(returnType, valueType, returnValue, statement); + TextRange textRange = statement.getTextRange(); + errorResult = checkAssignability(returnType, valueType, returnValue, textRange, returnValue.getStartOffsetInParent()); if (errorResult != null && valueType != null) { IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, valueType, true); QuickFixAction.registerQuickFixAction(errorResult, fix); @@ -509,28 +510,25 @@ public class HighlightUtil extends HighlightUtilBase { } } } - navigationShift = returnValue.getStartOffsetInParent(); } else { if (!isMethodVoid) { description = JavaErrorMessages.message("missing.return.value"); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, description); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).navigationShift(PsiKeyword.RETURN.length()).create(); IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true); QuickFixAction.registerQuickFixAction(errorResult, fix); - navigationShift = PsiKeyword.RETURN.length(); } } } - if (errorResult != null) { - errorResult.navigationShift = navigationShift; - } return errorResult; } + @NotNull public static String getUnhandledExceptionsDescriptor(@NotNull final Collection<PsiClassType> unhandled) { return getUnhandledExceptionsDescriptor(unhandled, null); } + @NotNull private static String getUnhandledExceptionsDescriptor(@NotNull final Collection<PsiClassType> unhandled, @Nullable final String source) { final String exceptions = formatTypes(unhandled); return source != null ? JavaErrorMessages.message("unhandled.close.exceptions", exceptions, unhandled.size(), source) @@ -569,8 +567,7 @@ public class HighlightUtil extends HighlightUtilBase { }; PsiScopesUtil.treeWalkUp(proc, identifier, scope); if (scope instanceof PsiResourceList && proc.size() == 0) { - @SuppressWarnings({"unchecked"}) NavigatablePsiElement parent = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); - scope = parent; + scope = PsiTreeUtil.getParentOfType(variable, PsiFile.class, PsiMethod.class, PsiClassInitializer.class); PsiScopesUtil.treeWalkUp(proc, identifier, scope); } if (proc.size() > 0) { @@ -602,7 +599,8 @@ public class HighlightUtil extends HighlightUtilBase { if (isIncorrect) { String description = JavaErrorMessages.message("variable.already.defined", name); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, identifier, description); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(description).create(); if (variable instanceof PsiLocalVariable) { QuickFixAction.registerQuickFixAction(highlightInfo, new ReuseVariableDeclarationFix((PsiLocalVariable)variable)); } @@ -642,16 +640,16 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable - public static HighlightInfo checkUnhandledExceptions(@NotNull final PsiElement element, @Nullable TextRange fixRange) { + public static HighlightInfo checkUnhandledExceptions(@NotNull final PsiElement element, @Nullable TextRange textRange) { 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(); + if (textRange == null) textRange = element.getTextRange(); final String description = getUnhandledExceptionsDescriptor(unhandledExceptions); - final HighlightInfo errorResult = HighlightInfo.createHighlightInfo(highlightType, fixRange, description); + HighlightInfo errorResult = HighlightInfo.newHighlightInfo(highlightType).range(textRange).descriptionAndTooltip(description).create(); registerUnhandledExceptionFixes(element, errorResult, unhandledExceptions); return errorResult; } @@ -665,7 +663,8 @@ public class HighlightUtil extends HighlightUtilBase { if (highlightType == null) return null; final String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource"); - final HighlightInfo highlight = HighlightInfo.createHighlightInfo(highlightType, resource, description); + final HighlightInfo highlight = + HighlightInfo.newHighlightInfo(highlightType).range(resource).descriptionAndTooltip(description).create(); registerUnhandledExceptionFixes(resource, highlight, unhandled); return highlight; } @@ -697,8 +696,8 @@ public class HighlightUtil extends HighlightUtilBase { static HighlightInfo checkBreakOutsideLoop(@NotNull PsiBreakStatement statement) { if (statement.getLabelIdentifier() == null) { if (new PsiMatcherImpl(statement).ancestor(EnclosingLoopOrSwitchMatcherExpression.INSTANCE).getElement() == null) { - return HighlightInfo - .createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("break.outside.switch.or.loop")); + String description = JavaErrorMessages.message("break.outside.switch.or.loop"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } } else { @@ -712,7 +711,8 @@ public class HighlightUtil extends HighlightUtilBase { static HighlightInfo checkContinueOutsideLoop(@NotNull PsiContinueStatement statement) { if (statement.getLabelIdentifier() == null) { if (new PsiMatcherImpl(statement).ancestor(EnclosingLoopMatcherExpression.INSTANCE).getElement() == null) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("continue.outside.loop")); + String description = JavaErrorMessages.message("continue.outside.loop"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } } else { @@ -721,7 +721,7 @@ public class HighlightUtil extends HighlightUtilBase { if (!(exitedStatement instanceof PsiForStatement) && !(exitedStatement instanceof PsiWhileStatement) && !(exitedStatement instanceof PsiDoWhileStatement) && !(exitedStatement instanceof PsiForeachStatement)) { String description = JavaErrorMessages.message("not.loop.label", statement.getLabelIdentifier().getText()); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } } return null; @@ -733,7 +733,8 @@ public class HighlightUtil extends HighlightUtilBase { String incompatible = getIncompatibleModifier(modifier, modifierList); if (incompatible != null) { String message = JavaErrorMessages.message("incompatible.modifiers", modifier, incompatible); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, keyword, message); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createModifierListFix(modifierList, modifier, false, false)); return highlightInfo; } @@ -789,7 +790,8 @@ public class HighlightUtil extends HighlightUtilBase { else { if (PsiModifier.PUBLIC.equals(modifier)) { isAllowed = modifierOwnerParent instanceof PsiJavaFile || - (modifierOwnerParent instanceof PsiClass && (modifierOwnerParent instanceof JspClass || ((PsiClass)modifierOwnerParent).getQualifiedName() != null)); + modifierOwnerParent instanceof PsiClass && + (modifierOwnerParent instanceof JspClass || ((PsiClass)modifierOwnerParent).getQualifiedName() != null); } else if (PsiModifier.STATIC.equals(modifier) || PsiModifier.PRIVATE.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) || PsiModifier.PACKAGE_LOCAL.equals(modifier)) { @@ -836,7 +838,8 @@ public class HighlightUtil extends HighlightUtilBase { if (!isAllowed) { String message = JavaErrorMessages.message("modifier.not.allowed", modifier); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, keyword, message); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(keyword).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createModifierListFix(modifierList, modifier, false, false)); return highlightInfo; } @@ -886,15 +889,15 @@ public class HighlightUtil extends HighlightUtilBase { ((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) { if (text.equals(PsiLiteralExpressionImpl.HEX_PREFIX)) { final String message = JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (text.equals(PsiLiteralExpressionImpl.BIN_PREFIX)) { final String message = JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (value == null || text.equals(PsiLiteralExpressionImpl._2_IN_31)) { final String message = JavaErrorMessages.message("integer.number.too.large"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } } @@ -906,22 +909,22 @@ public class HighlightUtil extends HighlightUtilBase { ((PsiPrefixExpression)parent).getOperationTokenType() == JavaTokenType.MINUS)) { if (mText.equals(PsiLiteralExpressionImpl.HEX_PREFIX)) { final String message = JavaErrorMessages.message("hexadecimal.numbers.must.contain.at.least.one.hexadecimal.digit"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (mText.equals(PsiLiteralExpressionImpl.BIN_PREFIX)) { final String message = JavaErrorMessages.message("binary.numbers.must.contain.at.least.one.hexadecimal.digit"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (value == null || mText.equals(PsiLiteralExpressionImpl._2_IN_63)) { final String message = JavaErrorMessages.message("long.number.too.large"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } } else if (isFP) { if (value == null) { final String message = JavaErrorMessages.message("malformed.floating.point.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } else if (type == JavaTokenType.CHARACTER_LITERAL) { @@ -929,7 +932,7 @@ public class HighlightUtil extends HighlightUtilBase { if (value != null) { if (!StringUtil.endsWithChar(text, '\'')) { final String message = JavaErrorMessages.message("unclosed.char.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } else { @@ -937,31 +940,32 @@ public class HighlightUtil extends HighlightUtilBase { if (StringUtil.endsWithChar(text, '\'')) { if (text.length() == 1) { final String message = JavaErrorMessages.message("illegal.line.end.in.character.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } text = text.substring(1, text.length() - 1); } else { final String message = JavaErrorMessages.message("illegal.line.end.in.character.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } final StringBuilder chars = StringBuilderSpinAllocator.alloc(); final boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null); if (!success) { final String message = JavaErrorMessages.message("illegal.escape.character.in.character.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } final int length = chars.length(); StringBuilderSpinAllocator.dispose(chars); if (length > 1) { final String message = JavaErrorMessages.message("too.many.characters.in.character.literal"); - final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + final HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(info, new ConvertToStringLiteralAction()); return info; } else if (length == 0) { final String message = JavaErrorMessages.message("empty.character.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } } @@ -977,19 +981,19 @@ public class HighlightUtil extends HighlightUtilBase { if (StringUtil.endsWithChar(text, '\"')) { if (text.length() == 1) { final String message = JavaErrorMessages.message("illegal.line.end.in.string.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } text = text.substring(1, text.length() - 1); } else { final String message = JavaErrorMessages.message("illegal.line.end.in.string.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } StringBuilder chars = new StringBuilder(); boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null); if (!success) { final String message = JavaErrorMessages.message("illegal.escape.character.in.string.literal"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } } @@ -998,22 +1002,22 @@ public class HighlightUtil extends HighlightUtilBase { final Float number = (Float)value; if (number.isInfinite()) { final String message = JavaErrorMessages.message("floating.point.number.too.large"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (number.floatValue() == 0 && !isFPZero(text)) { final String message = JavaErrorMessages.message("floating.point.number.too.small"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } else if (value instanceof Double) { final Double number = (Double)value; if (number.isInfinite()) { final String message = JavaErrorMessages.message("floating.point.number.too.large"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } if (number.doubleValue() == 0 && !isFPZero(text)) { final String message = JavaErrorMessages.message("floating.point.number.too.small"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } @@ -1032,7 +1036,8 @@ public class HighlightUtil extends HighlightUtilBase { String[] parts = ArrayUtil.EMPTY_STRING_ARRAY; if (isInt) { - int start = 0, end = text.length(); + int start = 0; + int end = text.length(); if (text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX) || text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX)) start += 2; if (StringUtil.endsWithChar(text, 'l')) --end; parts = new String[]{text.substring(start, end)}; @@ -1050,7 +1055,7 @@ public class HighlightUtil extends HighlightUtilBase { for (String part : parts) { if (part != null && (StringUtil.startsWithChar(part, '_') || StringUtil.endsWithChar(part, '_'))) { String message = JavaErrorMessages.message("illegal.underscore"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } @@ -1076,7 +1081,7 @@ public class HighlightUtil extends HighlightUtilBase { if (expr.getNextSibling() instanceof PsiErrorElement) return null; if (!TypeConversionUtil.isBooleanType(type)) { - final HighlightInfo info = createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expr.getTextRange()); + final HighlightInfo info = createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expr.getTextRange(), 0); if (expr instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expr; final PsiMethod method = methodCall.resolveMethod(); @@ -1118,7 +1123,7 @@ public class HighlightUtil extends HighlightUtilBase { if (caughtType instanceof PsiClassType) { return checkSimpleCatchParameter(parameter, thrownTypes, (PsiClassType)caughtType); } - else if (caughtType instanceof PsiDisjunctionType) { + if (caughtType instanceof PsiDisjunctionType) { return checkMultiCatchParameter(parameter, thrownTypes); } @@ -1136,7 +1141,8 @@ public class HighlightUtil extends HighlightUtilBase { } final String description = JavaErrorMessages.message("exception.never.thrown.try", formatType(caughtType)); - final HighlightInfo errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parameter, description); + final HighlightInfo errorResult = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(errorResult, new DeleteCatchFix(parameter)); return Collections.singleton(errorResult); } @@ -1160,7 +1166,8 @@ public class HighlightUtil extends HighlightUtilBase { } if (!used) { final String description = JavaErrorMessages.message("exception.never.thrown.try", formatType(catchType)); - final HighlightInfo highlight = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, description); + final HighlightInfo highlight = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlight, new DeleteMultiCatchFix(typeElement)); highlights.add(highlight); } @@ -1178,7 +1185,7 @@ public class HighlightUtil extends HighlightUtilBase { final PsiCatchSection catchSection = (PsiCatchSection)scope; final PsiCatchSection[] allCatchSections = catchSection.getTryStatement().getCatchSections(); - final int idx = ArrayUtil.find(allCatchSections, catchSection); + final int idx = ArrayUtilRt.find(allCatchSections, catchSection); if (idx <= 0) return null; final Collection<PsiClassType> thrownTypes = ContainerUtil.newHashSet(thrownInTryStatement); @@ -1218,7 +1225,8 @@ public class HighlightUtil extends HighlightUtilBase { // check & warn if (caught.isEmpty()) { final String message = JavaErrorMessages.message("exception.already.caught.warn", formatTypes(caughtCopy), caughtCopy.size()); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.WARNING, catchSection, message); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(catchSection).descriptionAndTooltip(message).create(); if (isMultiCatch) { QuickFixAction.registerQuickFixAction(highlightInfo, new DeleteMultiCatchFix(catchTypeElement)); } @@ -1236,7 +1244,8 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable static HighlightInfo checkNotAStatement(@NotNull PsiStatement statement) { if (!PsiUtil.isStatement(statement) && !PsiUtilCore.hasErrorElementChild(statement)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("not.a.statement")); + String description = JavaErrorMessages.message("not.a.statement"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } return null; } @@ -1251,7 +1260,7 @@ public class HighlightUtil extends HighlightUtilBase { if (!isValidTypeForSwitchSelector(type, PsiUtil.isLanguageLevel7OrHigher(expression))) { String message = JavaErrorMessages.message("incompatible.types", JavaErrorMessages.message("valid.switch.selector.types"), formatType(type)); - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(errorResult, new ConvertSwitchToIfIntention(statement)); if (PsiType.LONG.equals(type) || PsiType.FLOAT.equals(type) || PsiType.DOUBLE.equals(type)) { QuickFixAction.registerQuickFixAction(errorResult, new AddTypeCastFix(PsiType.INT, expression)); @@ -1261,7 +1270,7 @@ public class HighlightUtil extends HighlightUtilBase { final PsiClass member = PsiUtil.resolveClassInClassTypeOnly(type); if (member != null && !PsiUtil.isAccessible(member, expression, null)) { String message = PsiFormatUtil.formatClass(member, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_FQ_NAME) + " is inaccessible here"; - errorResult = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } } } @@ -1297,7 +1306,7 @@ public class HighlightUtil extends HighlightUtilBase { String message = JavaErrorMessages.message("binary.operator.not.applicable", token.getText(), formatType(lType), formatType(rType)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(message).create(); } lType = TypeConversionUtil.calcTypeForBinaryExpression(lType, rType, operationSign, true); } @@ -1314,7 +1323,8 @@ public class HighlightUtil extends HighlightUtilBase { String message = JavaErrorMessages.message("unary.operator.not.applicable", token.getText(), formatType(type)); PsiElement parentExpr = token.getParent(); - HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parentExpr, message); + HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parentExpr).descriptionAndTooltip(message).create(); if (parentExpr instanceof PsiPrefixExpression && token.getTokenType() == JavaTokenType.EXCL) { QuickFixAction.registerQuickFixAction(highlightInfo, new NegationBroadScopeFix((PsiPrefixExpression)parentExpr)); } @@ -1331,14 +1341,16 @@ public class HighlightUtil extends HighlightUtilBase { if (!(parent instanceof PsiReferenceExpression)) { // like in 'Object o = super;' final int o = expr.getTextRange().getEndOffset(); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, o, o + 1, JavaErrorMessages.message("dot.expected.after.super.or.this")); + String description = JavaErrorMessages.message("dot.expected.after.super.or.this"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(o, o + 1).descriptionAndTooltip(description).create(); } if (PsiUtil.isLanguageLevel8OrHigher(expr)) { final PsiMethod method = PsiTreeUtil.getParentOfType(expr, PsiMethod.class); if (method != null && method.hasModifierProperty(PsiModifier.DEFAULT) && qualifier == null) { //todo[r.sh] "Add qualifier" quick fix - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, parent, JavaErrorMessages.message("unqualified.super.disallowed")); + String description = JavaErrorMessages.message("unqualified.super.disallowed"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(description).create(); } } } @@ -1347,7 +1359,8 @@ public class HighlightUtil extends HighlightUtilBase { if (qualifier != null) { final PsiElement resolved = qualifier.resolve(); if (resolved != null && !(resolved instanceof PsiClass)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, qualifier, JavaErrorMessages.message("class.expected")); + String description = JavaErrorMessages.message("class.expected"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description).create(); } aClass = (PsiClass)resolved; } @@ -1380,7 +1393,8 @@ public class HighlightUtil extends HighlightUtilBase { } private static HighlightInfo thisNotFoundInInterfaceInfo(PsiExpression expr) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expr, "Cannot find symbol variable this"); + return HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip("Cannot find symbol variable this").create(); } private static boolean resolvesToImmediateSuperInterface(@NotNull PsiExpression expr, @@ -1393,6 +1407,7 @@ public class HighlightUtil extends HighlightUtilBase { return superClass != null && aClass.equals(superClass); } + @NotNull static String buildProblemWithStaticDescription(@NotNull PsiElement refElement) { String type = LanguageFindUsages.INSTANCE.forLanguage(JavaLanguage.INSTANCE).getType(refElement); String name = HighlightMessageUtil.getSymbolName(refElement, PsiSubstitutor.EMPTY); @@ -1424,11 +1439,13 @@ public class HighlightUtil extends HighlightUtilBase { return qname == null || !Character.isLowerCase(qname.charAt(0)); } - static String buildProblemWithAccessDescription(@NotNull final PsiJavaCodeReferenceElement reference, @NotNull final JavaResolveResult result) { + @NotNull + static String buildProblemWithAccessDescription(@NotNull final PsiElement reference, @NotNull final JavaResolveResult result) { return buildProblemWithAccessDescription(reference, result, result.getElement()); } - static String buildProblemWithAccessDescription(@NotNull final PsiJavaCodeReferenceElement reference, + @NotNull + static String buildProblemWithAccessDescription(@NotNull final PsiElement reference, @NotNull final JavaResolveResult result, @NotNull final PsiElement resolved) { assert resolved instanceof PsiModifierListOwner : resolved; @@ -1480,7 +1497,8 @@ public class HighlightUtil extends HighlightUtilBase { if (arrayExpressionType != null && !(arrayExpressionType instanceof PsiArrayType)) { final String description = JavaErrorMessages.message("array.type.expected", formatType(arrayExpressionType)); - final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, arrayExpression, description); + final HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(arrayExpression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new ReplaceWithListAccessFix(arrayAccessExpression)); return info; } @@ -1506,7 +1524,7 @@ public class HighlightUtil extends HighlightUtilBase { final PsiClassType autoCloseable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, resource.getResolveScope()); if (TypeConversionUtil.isAssignable(autoCloseable, type)) return null; - return createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange()); + return createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange(), 0); } @Nullable @@ -1574,8 +1592,8 @@ public class HighlightUtil extends HighlightUtilBase { private static HighlightInfo checkArrayInitializerCompatibleTypes(@NotNull PsiExpression initializer, final PsiType componentType) { PsiType initializerType = initializer.getType(); if (initializerType == null) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, initializer, - JavaErrorMessages.message("illegal.initializer", formatType(componentType))); + String description = JavaErrorMessages.message("illegal.initializer", formatType(componentType)); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(initializer).descriptionAndTooltip(description).create(); } PsiExpression expression = initializer instanceof PsiArrayInitializerExpression ? null : initializer; return checkAssignability(componentType, initializerType, expression, initializer); @@ -1590,7 +1608,8 @@ public class HighlightUtil extends HighlightUtilBase { // String.class or String() are both correct if (parent instanceof PsiReferenceExpression || parent instanceof PsiMethodCallExpression) return null; if (resolved instanceof PsiVariable) return null; - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("expression.expected")); + String description = JavaErrorMessages.message("expression.expected"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } @@ -1609,8 +1628,9 @@ public class HighlightUtil extends HighlightUtilBase { return null; } - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, - JavaErrorMessages.message("array.initializer.not.allowed")); + String description = JavaErrorMessages.message("array.initializer.not.allowed"); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new AddNewArrayExpressionFix(expression)); return info; } @@ -1620,8 +1640,8 @@ public class HighlightUtil extends HighlightUtilBase { public static HighlightInfo checkCaseStatement(@NotNull PsiSwitchLabelStatement statement) { PsiSwitchStatement switchStatement = statement.getEnclosingSwitchStatement(); if (switchStatement == null) { - return HighlightInfo - .createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("case.statement.outside.switch")); + String description = JavaErrorMessages.message("case.statement.outside.switch"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } if (switchStatement.getBody() == null) return null; PsiExpression switchExpression = switchStatement.getExpression(); @@ -1645,7 +1665,7 @@ public class HighlightUtil extends HighlightUtilBase { value = ((PsiEnumConstant)element).getName(); if (!(((PsiReferenceExpression)caseValue).getQualifier() == null)) { String message = JavaErrorMessages.message("qualified.enum.constant.in.switch"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, caseValue, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(caseValue).descriptionAndTooltip(message).create(); } } } @@ -1653,8 +1673,8 @@ public class HighlightUtil extends HighlightUtilBase { value = ConstantExpressionUtil.computeCastTo(caseValue, switchType); } if (value == null) { - return HighlightInfo - .createHighlightInfo(HighlightInfoType.ERROR, caseValue, JavaErrorMessages.message("constant.expression.required")); + String description = JavaErrorMessages.message("constant.expression.required"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(caseValue).descriptionAndTooltip(description).create(); } } @@ -1678,7 +1698,8 @@ public class HighlightUtil extends HighlightUtilBase { String description = statement.isDefaultCase() ? JavaErrorMessages.message("duplicate.default.switch.label") : JavaErrorMessages.message("duplicate.switch.label", value); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, value == null ? statement : caseValue, description); + PsiElement element = value == null ? statement : caseValue; + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create(); } // must be followed with colon @@ -1692,7 +1713,11 @@ public class HighlightUtil extends HighlightUtilBase { String description = JavaErrorMessages.message("switch.colon.expected.after.case.label"); CharSequence chars = statement.getContainingFile().getViewProvider().getContents(); boolean isAfterEndOfLine = end >= chars.length() || chars.charAt(start) == '\n' || chars.charAt(start) == '\r'; - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, null, start, end, description, description, isAfterEndOfLine, null); + HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(start, end).descriptionAndTooltip(description); + if (isAfterEndOfLine) { + builder.endOfLine(); + } + return builder.create(); } return null; } @@ -1721,7 +1746,8 @@ public class HighlightUtil extends HighlightUtilBase { if (!containingClass.getManager().areElementsEquivalent(containingClass, PsiTreeUtil.getParentOfType(expression, PsiClass.class))) { return null; } - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, JavaErrorMessages.message("illegal.forward.reference")); + String description = JavaErrorMessages.message("illegal.forward.reference"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } /** @@ -1766,7 +1792,7 @@ public class HighlightUtil extends HighlightUtilBase { if (aClass == null) { String canonicalText = type.getCanonicalText(); String description = JavaErrorMessages.message("unknown.class", canonicalText); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); } } return null; @@ -1796,7 +1822,7 @@ public class HighlightUtil extends HighlightUtilBase { } String description = JavaErrorMessages.message("illegal.type.void"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, type, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(type).descriptionAndTooltip(description).create(); } @Nullable @@ -1903,7 +1929,7 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable private static HighlightInfo checkReferenceToOurInstanceInsideThisOrSuper(@NotNull final PsiElement expression, - final PsiClass referencedClass, + @NotNull PsiClass referencedClass, final String resolvedName) { if (PsiTreeUtil.getParentOfType(expression, PsiReferenceParameterList.class) != null) return null; PsiElement element = expression.getParent(); @@ -1960,7 +1986,7 @@ public class HighlightUtil extends HighlightUtilBase { private static HighlightInfo createMemberReferencedError(@NonNls final String resolvedName, @NotNull TextRange textRange) { String description = JavaErrorMessages.message("member.referenced.before.constructor.called", resolvedName); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, textRange, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create(); } @Nullable @@ -2040,7 +2066,8 @@ public class HighlightUtil extends HighlightUtilBase { @Nullable public static HighlightInfo checkLabelWithoutStatement(@NotNull PsiLabeledStatement statement) { if (statement.getStatement() == null) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("label.without.statement")); + String description = JavaErrorMessages.message("label.without.statement"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } return null; } @@ -2056,7 +2083,7 @@ public class HighlightUtil extends HighlightUtilBase { if (element instanceof PsiLabeledStatement && element != statement && Comparing.equal(((PsiLabeledStatement)element).getLabelIdentifier().getText(), text)) { String description = JavaErrorMessages.message("duplicate.label", text); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, identifier, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(description).create(); } element = element.getParent(); } @@ -2070,7 +2097,8 @@ public class HighlightUtil extends HighlightUtilBase { if (!comment.getText().endsWith("*/")) { int start = comment.getTextRange().getEndOffset() - 1; int end = start + 1; - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, start, end, JavaErrorMessages.message("unclosed.comment")); + String description = JavaErrorMessages.message("unclosed.comment"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(start, end).descriptionAndTooltip(description).create(); } return null; } @@ -2093,8 +2121,9 @@ public class HighlightUtil extends HighlightUtilBase { if (sub || sup) { final String name1 = PsiFormatUtil.formatClass(class1, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_FQ_NAME); final String name2 = PsiFormatUtil.formatClass(class2, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_FQ_NAME); - final String message = JavaErrorMessages.message("exception.must.be.disjoint", (sub ? name1 : name2), (sub ? name2 : name1)); - result.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElements.get(sub ? i : j), message)); + final String message = JavaErrorMessages.message("exception.must.be.disjoint", sub ? name1 : name2, sub ? name2 : name1); + PsiElement element = typeElements.get(sub ? i : j); + result.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create()); break; } } @@ -2111,7 +2140,7 @@ public class HighlightUtil extends HighlightUtilBase { final PsiCatchSection catchSection = (PsiCatchSection)scope; final PsiCatchSection[] allCatchSections = catchSection.getTryStatement().getCatchSections(); - final int startFrom = ArrayUtil.find(allCatchSections, catchSection) - 1; + final int startFrom = ArrayUtilRt.find(allCatchSections, catchSection) - 1; if (startFrom < 0) return null; final List<PsiTypeElement> typeElements = PsiUtil.getParameterTypeElements(parameter); @@ -2132,7 +2161,8 @@ public class HighlightUtil extends HighlightUtilBase { if (highlight) { final String className = PsiFormatUtil.formatClass(catchClass, PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_FQ_NAME); final String description = JavaErrorMessages.message("exception.already.caught", className); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, typeElement, description); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); result.add(highlightInfo); QuickFixAction.registerQuickFixAction(highlightInfo, new MoveCatchUpFix(catchSection, upperCatchSection)); @@ -2146,7 +2176,7 @@ public class HighlightUtil extends HighlightUtilBase { } } - return result.size() > 0 ? result : null; + return result.isEmpty() ? null : result; } private static boolean checkMultipleTypes(final PsiClass catchClass, @NotNull final List<PsiType> upperCatchTypes) { @@ -2166,7 +2196,7 @@ public class HighlightUtil extends HighlightUtilBase { public static HighlightInfo checkTernaryOperatorConditionIsBoolean(@NotNull PsiExpression expression, PsiType type) { if (expression.getParent() instanceof PsiConditionalExpression && ((PsiConditionalExpression)expression.getParent()).getCondition() == expression && !TypeConversionUtil.isBooleanType(type)) { - return createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expression.getTextRange()); + return createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expression.getTextRange(), 0); } return null; } @@ -2178,8 +2208,8 @@ public class HighlightUtil extends HighlightUtilBase { statement.getParent().getParent() instanceof PsiSwitchStatement && ((PsiCodeBlock)statement.getParent()).getStatements().length != 0 && statement == ((PsiCodeBlock)statement.getParent()).getStatements()[0]) { - return HighlightInfo - .createHighlightInfo(HighlightInfoType.ERROR, statement, JavaErrorMessages.message("statement.must.be.prepended.with.case.label")); + String description = JavaErrorMessages.message("statement.must.be.prepended.with.case.label"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } return null; } @@ -2194,11 +2224,11 @@ public class HighlightUtil extends HighlightUtilBase { PsiAssertStatement assertStatement = (PsiAssertStatement)expression.getParent(); if (expression == assertStatement.getAssertCondition() && !TypeConversionUtil.isBooleanType(type)) { // addTypeCast quickfix is not applicable here since no type can be cast to boolean - return createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expression.getTextRange()); + return createIncompatibleTypeHighlightInfo(PsiType.BOOLEAN, type, expression.getTextRange(), 0); } if (expression == assertStatement.getAssertDescription() && TypeConversionUtil.isVoidType(type)) { String description = JavaErrorMessages.message("void.type.is.not.allowed"); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); } return null; } @@ -2212,7 +2242,7 @@ public class HighlightUtil extends HighlightUtilBase { if (expression == synchronizedStatement.getLockExpression() && (type instanceof PsiPrimitiveType || TypeConversionUtil.isNullType(type))) { PsiClassType objectType = PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope()); - return createIncompatibleTypeHighlightInfo(objectType, type, expression.getTextRange()); + return createIncompatibleTypeHighlightInfo(objectType, type, expression.getTextRange(), 0); } } return null; @@ -2236,12 +2266,15 @@ public class HighlightUtil extends HighlightUtilBase { if (conditionalExpression.getType() == null) { // cannot derive type of conditional expression // elsetype will never be castable to thentype, so no quick fix here - return createIncompatibleTypeHighlightInfo(thenType, elseType, expression.getTextRange()); + return createIncompatibleTypeHighlightInfo(thenType, elseType, expression.getTextRange(), 0); } return null; } - private static HighlightInfo createIncompatibleTypeHighlightInfo(final PsiType lType, final PsiType rType, @NotNull final TextRange textRange) { + private static HighlightInfo createIncompatibleTypeHighlightInfo(final PsiType lType, + final PsiType rType, + @NotNull final TextRange textRange, + int navigationShift) { PsiType lType1 = lType; PsiType rType1 = rType; PsiTypeParameter[] lTypeParams = PsiTypeParameter.EMPTY_ARRAY; @@ -2299,8 +2332,7 @@ public class HighlightUtil extends HighlightUtilBase { String description = JavaErrorMessages.message("incompatible.types", formatType(lType1), formatType(rType1)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, null, textRange.getStartOffset(), textRange.getEndOffset(), - description, toolTip); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).description(description).escapedToolTip(toolTip).navigationShift(navigationShift).create(); } @Nullable @@ -2314,7 +2346,7 @@ public class HighlightUtil extends HighlightUtilBase { PsiClass importedClass = imported == null ? null : imported.getSecond(); if (importedClass != null && !element.getManager().areElementsEquivalent(importedClass, element)) { String description = JavaErrorMessages.message("single.import.class.conflict", formatClass(importedClass)); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, statement, description); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(description).create(); } importedClasses.put(name, Pair.create((PsiImportStaticReferenceElement)null, (PsiClass)element)); } @@ -2341,7 +2373,7 @@ public class HighlightUtil extends HighlightUtilBase { PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory(); PsiClassType throwable = factory.createTypeByFQClassName("java.lang.Throwable", context.getResolveScope()); if (!TypeConversionUtil.isAssignable(throwable, type)) { - HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(throwable, type, context.getTextRange()); + HighlightInfo highlightInfo = createIncompatibleTypeHighlightInfo(throwable, type, context.getTextRange(), 0); if (addCastIntention && TypeConversionUtil.areTypesConvertible(type, throwable)) { if (context instanceof PsiExpression) { QuickFixAction.registerQuickFixAction(highlightInfo, new AddTypeCastFix(throwable, (PsiExpression)context)); @@ -2368,7 +2400,7 @@ public class HighlightUtil extends HighlightUtilBase { if (label == null) return null; if (exitedStatement == null) { String message = JavaErrorMessages.message("unresolved.label", label); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, labelIdentifier, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(labelIdentifier).descriptionAndTooltip(message).create(); } return null; } @@ -2392,7 +2424,8 @@ public class HighlightUtil extends HighlightUtilBase { if (qualifierExpression == ref) { @SuppressWarnings("UnnecessaryLocalVariable") PsiElement qualifier = resolved; if (qualifier != null && !(qualifier instanceof PsiClass) && !(qualifier instanceof PsiVariable)) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, qualifierExpression, "Qualifier must be an expression"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(qualifierExpression).descriptionAndTooltip( + "Qualifier must be an expression").create(); } } } @@ -2417,7 +2450,7 @@ public class HighlightUtil extends HighlightUtilBase { HighlightInfoType type = HighlightInfoType.WRONG_REF; if (PsiUtil.isInsideJavadocComment(ref)) return null; - HighlightInfo info = HighlightInfo.createHighlightInfo(type, refName, description); + HighlightInfo info = HighlightInfo.newHighlightInfo(type).range(refName).descriptionAndTooltip(description).create(); UnresolvedReferenceQuickFixProvider.registerReferenceFixes(ref, new QuickFixActionRegistrarImpl(info)); return info; @@ -2426,7 +2459,8 @@ public class HighlightUtil extends HighlightUtilBase { if (!result.isValidResult() && !PsiUtil.isInsideJavadocComment(ref)) { if (!result.isAccessible()) { String description = buildProblemWithAccessDescription(ref, result, resolved); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, refName, description); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refName).descriptionAndTooltip(description).create(); if (result.isStaticsScopeCorrect()) { registerAccessQuickFixAction((PsiMember)resolved, ref, info, result.getCurrentFileResolveScope()); if (ref instanceof PsiReferenceExpression) { @@ -2439,7 +2473,8 @@ public class HighlightUtil extends HighlightUtilBase { if (!result.isStaticsScopeCorrect()) { String description = buildProblemWithStaticDescription(resolved); - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, refName, description); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refName).descriptionAndTooltip(description).create(); registerStaticProblemQuickFixAction(resolved, info, ref); if (ref instanceof PsiReferenceExpression) { QuickFixAction.registerQuickFixAction(info, new RenameWrongRefFix((PsiReferenceExpression)ref)); @@ -2454,8 +2489,8 @@ public class HighlightUtil extends HighlightUtilBase { if (Comparing.strEqual(((PsiClass)resolved).getQualifiedName(), ((PsiClass)resolved).getName())) { final PsiElement parent = ref.getParent(); if (parent instanceof PsiImportStaticReferenceElement || parent instanceof PsiImportStatementBase) { - return HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, refName, - JavaErrorMessages.message("cannot.resolve.symbol", refName.getText())); + String description = JavaErrorMessages.message("cannot.resolve.symbol", refName.getText()); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(refName).descriptionAndTooltip(description).create(); } } } @@ -2490,7 +2525,7 @@ public class HighlightUtil extends HighlightUtilBase { PsiClass aClass = JavaPsiFacade.getInstance(ref.getProject()).findClass(ref.getCanonicalText(), scope); if (aClass != null) { String message = JavaErrorMessages.message("package.clashes.with.class", ref.getText()); - return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, message); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(message).create(); } } } @@ -2530,7 +2565,8 @@ public class HighlightUtil extends HighlightUtilBase { } } else if (refGrandParent instanceof PsiMethod && referenceList == ((PsiMethod)refGrandParent).getThrowsList()) { - highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, JavaErrorMessages.message("class.name.expected")); + String description = JavaErrorMessages.message("class.name.expected"); + highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).create(); } return highlightInfo; } @@ -2559,7 +2595,9 @@ public class HighlightUtil extends HighlightUtilBase { PsiElement qualifierResolved = ((PsiReferenceExpression)qualifier).resolve(); if (qualifierResolved instanceof PsiClass || qualifierResolved instanceof PsiPackage) return null; } - HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, qualifier, JavaErrorMessages.message("expected.class.or.package")); + String description = JavaErrorMessages.message("expected.class.or.package"); + HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, new RemoveQualifierFix(qualifier, expression, (PsiClass)resolved)); return info; } @@ -2579,7 +2617,8 @@ public class HighlightUtil extends HighlightUtilBase { final PsiElement parent = list.getParent(); if (PsiUtil.isAnnotationMethod(parent) && list.getParametersCount() > 0) { final String message = JavaErrorMessages.message("annotation.interface.members.may.not.have.parameters"); - final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, list, message); + final HighlightInfo highlightInfo = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(list).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveParameterListFix((PsiMethod)parent)); return highlightInfo; } @@ -2615,7 +2654,8 @@ public class HighlightUtil extends HighlightUtilBase { private static HighlightInfo checkFeature(@Nullable final PsiElement element, @NotNull final Feature feature) { if (element != null && element.getManager().isInProject(element) && !PsiUtil.getLanguageLevel(element).isAtLeast(feature.level)) { final String message = JavaErrorMessages.message("insufficient.language.level", JavaErrorMessages.message(feature.key)); - final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, message); + final HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create(); QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(feature.level)); QuickFixAction.registerQuickFixAction(info, new ShowModulePropertiesFix(element)); return info; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 2db8816d2df1..7d97295b8bab 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -247,43 +247,69 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (functionalInterfaceType != null) { final String notFunctionalMessage = LambdaHighlightingUtil.checkInterfaceFunctional(functionalInterfaceType); if (notFunctionalMessage != null) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, notFunctionalMessage)); - } else { + HighlightInfo result = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(notFunctionalMessage) + .create(); + myHolder.add(result); + } + else { if (!LambdaUtil.isLambdaFullyInferred(expression, functionalInterfaceType) && !expression.hasFormalParameterTypes()) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, - "Cyclic inference")); //todo[ann] append not inferred type params info + HighlightInfo result = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cyclic inference") + .create(); + myHolder.add(result); //todo[ann] append not inferred type params info } else { final String incompatibleReturnTypesMessage = LambdaHighlightingUtil .checkReturnTypeCompatible(expression, LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType)); if (incompatibleReturnTypesMessage != null) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, incompatibleReturnTypesMessage)); - } else { - final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType); + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip(incompatibleReturnTypesMessage).create(); + myHolder.add(result); + } + else { + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); if (interfaceMethod != null) { final PsiParameter[] parameters = interfaceMethod.getParameterList().getParameters(); final PsiParameter[] lambdaParameters = expression.getParameterList().getParameters(); final String incompatibleTypesMessage = "Incompatible parameter types in lambda expression"; if (lambdaParameters.length != parameters.length) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, incompatibleTypesMessage)); - } else { - final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip(incompatibleTypesMessage).create(); + myHolder.add(result); + } + else { for (int i = 0; i < lambdaParameters.length; i++) { PsiParameter lambdaParameter = lambdaParameters[i]; if (!TypeConversionUtil.isAssignable(lambdaParameter.getType(), - GenericsUtil.eliminateWildcards(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult).substitute(parameters[i].getType())))) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, lambdaParameter, incompatibleTypesMessage)); + GenericsUtil.eliminateWildcards( + LambdaUtil.getSubstitutor(interfaceMethod, resolveResult) + .substitute(parameters[i].getType())))) { + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(lambdaParameter) + .descriptionAndTooltip(incompatibleTypesMessage).create(); + myHolder.add(result); break; } } } + if (!myHolder.hasErrorResults()) { + final PsiClass samClass = resolveResult.getElement(); + if (!PsiUtil.isAccessible(samClass, expression, null)) { + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create()); + } + } } } } } } - } else { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, "Lambda expression not expected here")); + } + else { + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip("Lambda expression not expected here").create(); + myHolder.add(result); } if (!myHolder.hasErrorResults()) { final PsiElement body = expression.getBody(); @@ -533,7 +559,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh final String description = JavaErrorMessages.message("cannot.resolve.symbol", refName); final PsiElement nameElement = ref.getReferenceNameElement(); assert nameElement != null : ref; - final HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, nameElement, description); + final HighlightInfo info = + HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(nameElement).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, SetupJDKFix.getInstance()); myHolder.add(info); } @@ -567,7 +594,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } if (description != null) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, ref, description)); + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(ref).descriptionAndTooltip(description).create()); } } } @@ -612,7 +639,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword)); if (PsiTreeUtil.getParentOfType(keyword, PsiDocTagValue.class) != null) { - myHolder.add(HighlightInfo.createHighlightInfo(JavaHighlightInfoTypes.JAVA_KEYWORD, keyword, null)); + HighlightInfo result = HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.JAVA_KEYWORD).range(keyword).create(); + myHolder.add(result); } } @@ -765,7 +793,10 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(AnnotationsHighlightUtil.checkNameValuePair(pair)); if (!myHolder.hasErrorResults()) { PsiIdentifier nameId = pair.getNameIdentifier(); - if (nameId != null) myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME, nameId, null)); + if (nameId != null) { + HighlightInfo result = HighlightInfo.newHighlightInfo(HighlightInfoType.ANNOTATION_ATTRIBUTE_NAME).range(nameId).create(); + myHolder.add(result); + } } } @@ -887,7 +918,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh !PsiTreeUtil.isAncestor(containingClass, variable, false) && !(variable instanceof PsiField)) { if (!PsiTreeUtil.isAncestor(((PsiAnonymousClass) containingClass).getArgumentList(), ref, false)) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER, ref, null)); + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.IMPLICIT_ANONYMOUS_CLASS_PARAMETER).range(ref).create()); } } @@ -919,11 +950,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh else { if (parent instanceof PsiNewExpression) { final PsiExpression newQualifier = ((PsiNewExpression)parent).getQualifier(); - if (newQualifier != null) { - place = PsiUtil.resolveClassInType(newQualifier.getType()); - } else { - place = ref; - } + place = newQualifier == null ? ref : PsiUtil.resolveClassInType(newQualifier.getType()); } else { place = ref; @@ -1013,27 +1040,53 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (myRefCountHolder != null) { myRefCountHolder.registerReference(expression, result); } - if (result.getElement() != null && !result.isAccessible()) { + final PsiElement method = result.getElement(); + if (method != null && !result.isAccessible()) { final String accessProblem = HighlightUtil.buildProblemWithAccessDescription(expression, result); - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, accessProblem)); + HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(accessProblem).create(); + myHolder.add(info); } if (!myHolder.hasErrorResults()) { final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType(); - if (functionalInterfaceType != null && LambdaUtil.dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression, null)) { - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, "Cyclic inference")); //todo[ann] append not inferred type params info + if (functionalInterfaceType != null && LambdaUtil.dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression)) { + HighlightInfo result1 = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip("Cyclic inference").create(); + myHolder.add(result1); //todo[ann] append not inferred type params info } else { final PsiElement referenceNameElement = expression.getReferenceNameElement(); if (referenceNameElement instanceof PsiKeyword) { if (!PsiMethodReferenceUtil.isValidQualifier(expression)) { final PsiElement qualifier = expression.getQualifier(); - myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, qualifier, "Cannot find class " + qualifier.getText())); + String description = "Cannot find class " + qualifier.getText(); + HighlightInfo result1 = + HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(qualifier).descriptionAndTooltip(description).create(); + myHolder.add(result1); } } } + if (!myHolder.hasErrorResults()) { + final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); + final PsiClass psiClass = resolveResult.getElement(); + if (psiClass != null && !PsiUtil.isAccessible(psiClass, expression, null)) { + myHolder.add(HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression) + .descriptionAndTooltip(HighlightUtil.buildProblemWithAccessDescription(expression, resolveResult)).create()); + } + } } if (!myHolder.hasErrorResults()) { myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, expression.getTextRange())); } + if (!myHolder.hasErrorResults()) { + if (method instanceof PsiMethod && ((PsiMethod)method).hasModifierProperty(PsiModifier.ABSTRACT)) { + final PsiElement qualifier = expression.getQualifier(); + if (qualifier instanceof PsiSuperExpression) { + myHolder.add(HighlightInfo + .newHighlightInfo(HighlightInfoType.ERROR) + .range(expression.getReferenceNameElement()) + .descriptionAndTooltip("Abstract method '" + ((PsiMethod)method).getName() + "' cannot be accessed directly").create()); + } + } + } } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java index f435a4269718..18c2e0b1c6b4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java @@ -78,24 +78,22 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); } - - field = CreateFieldFromUsageHelper.insertField(targetClass, field, myReferenceExpression); - - setupVisibility(parentClass, targetClass, field.getModifierList()); - - if (!targetClass.isInterface() && shouldCreateStaticMember(myReferenceExpression, targetClass)) { - PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); - } - - if (shouldCreateFinalMember(myReferenceExpression, targetClass)) { - PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); - } - if (createConstantField()) { PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); + } else { + if (!targetClass.isInterface() && shouldCreateStaticMember(myReferenceExpression, targetClass)) { + PsiUtil.setModifierProperty(field, PsiModifier.STATIC, true); + } + if (shouldCreateFinalMember(myReferenceExpression, targetClass)) { + PsiUtil.setModifierProperty(field, PsiModifier.FINAL, true); + } } + field = CreateFieldFromUsageHelper.insertField(targetClass, field, myReferenceExpression); + + setupVisibility(parentClass, targetClass, field.getModifierList()); + final Editor newEditor = positionCursor(project, targetFile, field); if (newEditor == null) return; Template template = diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java index 8da93c134c2b..5a15f0f7ee84 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SideEffectWarningDialog.java @@ -21,6 +21,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.psi.PsiVariable; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -53,6 +54,7 @@ public class SideEffectWarningDialog extends DialogWrapper { } + @NotNull @Override protected Action[] createActions() { List<AbstractAction> actions = new ArrayList<AbstractAction>(); @@ -97,11 +99,13 @@ public class SideEffectWarningDialog extends DialogWrapper { return actions.toArray(new Action[actions.size()]); } + @NotNull @Override protected Action getCancelAction() { return myCancelAllAction; } + @NotNull @Override protected Action getOKAction() { return myRemoveAllAction; diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java index 873631e57e2f..735520aa44ce 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/CreateClassOrPackageFix.java @@ -23,6 +23,7 @@ import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -43,6 +44,7 @@ import java.util.*; * @author peter */ public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPsiElement { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix"); private final List<PsiDirectory> myWritableDirectoryList; private final String myPresentation; @@ -233,9 +235,15 @@ public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPs public static List<PsiDirectory> getWritableDirectoryListDefault(@Nullable final PsiPackage context, final GlobalSearchScope scope, final PsiManager psiManager) { + if (LOG.isDebugEnabled()) { + LOG.debug("Getting writable directory list for package '" + (context == null ? null : context.getQualifiedName()) + "', scope=" + scope); + } final List<PsiDirectory> writableDirectoryList = new ArrayList<PsiDirectory>(); if (context != null) { for (PsiDirectory directory : context.getDirectories()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Package directory: " + directory); + } if (directory.isWritable() && scope.contains(directory.getVirtualFile())) { writableDirectoryList.add(directory); } @@ -244,11 +252,17 @@ public class CreateClassOrPackageFix extends LocalQuickFixAndIntentionActionOnPs else { for (VirtualFile root : ProjectRootManager.getInstance(psiManager.getProject()).getContentSourceRoots()) { PsiDirectory directory = psiManager.findDirectory(root); + if (LOG.isDebugEnabled()) { + LOG.debug("Root: " + root + ", directory: " + directory); + } if (directory != null && directory.isWritable() && scope.contains(directory.getVirtualFile())) { writableDirectoryList.add(directory); } } } + if (LOG.isDebugEnabled()) { + LOG.debug("Result " + writableDirectoryList); + } return writableDirectoryList; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java index 183d13c86ba1..376238573e6b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java @@ -19,7 +19,6 @@ import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.psi.*; @@ -213,7 +212,7 @@ public class GenerateEqualsHelper implements Runnable { } } buffer.append("\nreturn true;\n}"); - PsiMethod result = myFactory.createMethodFromText(buffer.toString(), null); + PsiMethod result = myFactory.createMethodFromText(buffer.toString(), myClass); final PsiParameter parameter = result.getParameterList().getParameters()[0]; PsiUtil.setModifierProperty(parameter, PsiModifier.FINAL, styleSettings.GENERATE_FINAL_PARAMETERS); @@ -395,6 +394,7 @@ public class GenerateEqualsHelper implements Runnable { buffer.append("return 0;\n}"); } PsiMethod hashCode = myFactory.createMethodFromText(buffer.toString(), null); + hashCode = (PsiMethod)myJavaCodeStyleManager.shortenClassReferences(hashCode); return (PsiMethod)myCodeStyleManager.reformat(hashCode); } @@ -472,7 +472,7 @@ public class GenerateEqualsHelper implements Runnable { private static void adjustHashCodeToArrays(@NonNls StringBuilder buffer, final PsiField field, final String name) { if (field.getType() instanceof PsiArrayType && hasArraysHashCode(field)) { - buffer.append("Arrays.hashCode("); + buffer.append("java.util.Arrays.hashCode("); buffer.append(name); buffer.append(")"); } diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/JavaImplementationTextSelectioner.java b/java/java-impl/src/com/intellij/codeInsight/hint/JavaImplementationTextSelectioner.java index 3f7083a69aea..cef9ee28a753 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/JavaImplementationTextSelectioner.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/JavaImplementationTextSelectioner.java @@ -21,6 +21,7 @@ package com.intellij.codeInsight.hint; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocCommentOwner; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; @@ -44,13 +45,16 @@ public class JavaImplementationTextSelectioner implements ImplementationTextSele } if (element != null) { - return element.getTextRange().getStartOffset(); - } - else { - LOG.error("Element should not be null: " + parent.getText()); - return parent.getTextRange().getStartOffset(); + TextRange range = element.getTextRange(); + if (range != null) { + return range.getStartOffset(); + } + LOG.error("Range should not be null: " + element + "; " + element.getClass()); } - } + + LOG.error("Element should not be null: " + parent.getText()); + return parent.getTextRange().getStartOffset(); + } @Override public int getTextEndOffset(@NotNull PsiElement element) { diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java index 8008c75ab5b6..73ac96b7a5d3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java @@ -431,7 +431,13 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc public void updateUI(final Object p, final ParameterInfoUIContext context) { if (p instanceof CandidateInfo) { CandidateInfo info = (CandidateInfo)p; - updateMethodPresentation((PsiMethod)info.getElement(), getCandidateInfoSubstitutor(info), context); + PsiMethod method = (PsiMethod)info.getElement(); + if (!method.isValid()) { + context.setUIComponentEnabled(false); + return; + } + + updateMethodPresentation(method, getCandidateInfoSubstitutor(info), context); } else { updateMethodPresentation((PsiMethod)p, null, context); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java index 2aa865d316c6..2f4ff88fddf0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateClassDialog.java @@ -126,6 +126,7 @@ public class CreateClassDialog extends DialogWrapper { return false; } + @NotNull @Override protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction()}; diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java index cba613755b46..e93cd0d70cbc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java +++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java @@ -28,6 +28,7 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.PsiClassReferenceType; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -213,27 +214,29 @@ public class PsiTypeLookupItem extends LookupItem { final PsiClass psiClass = classResolveResult.getElement(); if (psiClass != null) { - final PsiSubstitutor substitutor = classResolveResult.getSubstitutor(); - - PsiClass resolved = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper().resolveReferencedClass(psiClass.getName(), context); - - Set<String> allStrings = new HashSet<String>(); - String lookupString = psiClass.getName(); - allStrings.add(lookupString); - if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass) && !PsiUtil.isInnerClass(psiClass)) { - // inner class name should be shown qualified if its not accessible by single name - PsiClass aClass = psiClass.getContainingClass(); - while (aClass != null && !PsiUtil.isInnerClass(aClass)) { - lookupString = aClass.getName() + '.' + lookupString; - allStrings.add(lookupString); - aClass = aClass.getContainingClass(); + String name = psiClass.getName(); + if (name != null) { + final PsiSubstitutor substitutor = classResolveResult.getSubstitutor(); + + PsiClass resolved = JavaPsiFacade.getInstance(psiClass.getProject()).getResolveHelper().resolveReferencedClass(name, context); + + Set<String> allStrings = new HashSet<String>(); + allStrings.add(name); + if (!psiClass.getManager().areElementsEquivalent(resolved, psiClass) && !PsiUtil.isInnerClass(psiClass)) { + // inner class name should be shown qualified if its not accessible by single name + PsiClass aClass = psiClass.getContainingClass(); + while (aClass != null && !PsiUtil.isInnerClass(aClass)) { + name = aClass.getName() + '.' + name; + allStrings.add(name); + aClass = aClass.getContainingClass(); + } } - } - PsiTypeLookupItem item = new PsiTypeLookupItem(psiClass, lookupString, diamond, bracketsCount, importFixer); - item.addLookupStrings(allStrings.toArray(new String[allStrings.size()])); - item.setAttribute(SUBSTITUTOR, substitutor); - return item; + PsiTypeLookupItem item = new PsiTypeLookupItem(psiClass, name, diamond, bracketsCount, importFixer); + item.addLookupStrings(ArrayUtil.toStringArray(allStrings)); + item.setAttribute(SUBSTITUTOR, substitutor); + return item; + } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java index 94ebc55f537a..42e990f3aee0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/JavaCodeContextType.java @@ -95,7 +95,7 @@ public abstract class JavaCodeContextType extends TemplateContextType { } private static boolean isStatementContext(PsiElement element) { - if (isAfterExpression(element)) { + if (isAfterExpression(element) || JavaStringContextType.isStringLiteral(element)) { return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/template/JavaStringContextType.java b/java/java-impl/src/com/intellij/codeInsight/template/JavaStringContextType.java index bbd52e8c0584..01831be70d5f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/template/JavaStringContextType.java +++ b/java/java-impl/src/com/intellij/codeInsight/template/JavaStringContextType.java @@ -34,9 +34,12 @@ public class JavaStringContextType extends TemplateContextType { @Override public boolean isInContext(@NotNull final PsiFile file, final int offset) { if (PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(StdLanguages.JAVA)) { - PsiElement element = file.findElementAt(offset); - return element instanceof PsiJavaToken && ((PsiJavaToken) element).getTokenType() == JavaTokenType.STRING_LITERAL; + return isStringLiteral(file.findElementAt(offset)); } return false; } + + static boolean isStringLiteral(PsiElement element) { + return element instanceof PsiJavaToken && ((PsiJavaToken) element).getTokenType() == JavaTokenType.STRING_LITERAL; + } } diff --git a/java/java-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java b/java/java-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java index 88cc269db319..6861ff990ac7 100644 --- a/java/java-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java @@ -76,7 +76,7 @@ public class AnnotateMethodFix implements LocalQuickFix { if (annotateOverriddenMethods()) { PsiMethod[] methods = OverridingMethodsSearch.search(method, GlobalSearchScope.allScope(project), true).toArray(PsiMethod.EMPTY_ARRAY); for (PsiMethod psiMethod : methods) { - if (!AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) { + if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) && !AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) { toAnnotate.add(psiMethod); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java b/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java index 5fbf4c3aa5bf..866f39c62f4b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/NumericOverflowInspection.java @@ -18,6 +18,7 @@ package com.intellij.codeInspection; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.JavaErrorMessages; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.util.ConstantEvaluationOverflowException; @@ -62,7 +63,7 @@ public class NumericOverflowInspection extends BaseLocalInspectionTool { @Override public void visitExpression(PsiExpression expression) { - boolean info = hasOverflow(expression); + boolean info = hasOverflow(expression, holder.getProject()); if (info) { holder.registerProblem(expression, JavaErrorMessages.message("numeric.overflow.in.expression"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } @@ -70,12 +71,12 @@ public class NumericOverflowInspection extends BaseLocalInspectionTool { }; } - private static boolean hasOverflow(PsiExpression expr) { + private static boolean hasOverflow(PsiExpression expr, @NotNull Project project) { if (!TypeConversionUtil.isNumericType(expr.getType())) return false; boolean overflow = false; try { if (expr.getUserData(HAS_OVERFLOW_IN_CHILD) == null) { - JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr, true); + JavaPsiFacade.getInstance(project).getConstantEvaluationHelper().computeConstantExpression(expr, true); } else { overflow = true; diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ConditionCheckDialog.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ConditionCheckDialog.java new file mode 100644 index 000000000000..0f8a7257efdf --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ConditionCheckDialog.java @@ -0,0 +1,288 @@ +/* + * Copyright 2000-2013 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.codeInspection.dataFlow; + +import com.intellij.codeInsight.*; +import com.intellij.codeInspection.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.ui.*; +import com.intellij.ui.*; +import com.intellij.ui.components.*; +import org.jetbrains.annotations.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; + +/** + * Dialog that appears when user clicks the "Configure IsNull/IsNotNull/True/False Check/Assertion Methods" + * on the Errors dialog for the Constant Conditions Inspection. It is divided into 6 parts + * <ol> + * <li>Is Null Check MethodsPanel</li> + * <li>Is Not Null Check MethodsPanel</li> + * <li>Assert Is Null MethodsPanel</li> + * <li>Assert Is Not Null MethodsPanel</li> + * <li>Assert True MethodsPanel</li> + * <li>Assert False MethodsPanel</li> + * </ol> + * + * @author <a href="mailto:johnnyclark@gmail.com">Johnny Clark</a> + * Creation Date: 8/3/12 + */ +public class ConditionCheckDialog extends DialogWrapper { + private final Project myProject; + private final @NotNull Splitter mainSplitter; + private final @NotNull MethodsPanel myIsNullCheckMethodPanel; + private final @NotNull MethodsPanel myIsNotNullCheckMethodPanel; + private final @NotNull MethodsPanel myAssertIsNullMethodPanel; + private final @NotNull MethodsPanel myAssertIsNotNullMethodPanel; + private final @NotNull MethodsPanel myAssertTrueMethodPanel; + private final @NotNull MethodsPanel myAssertFalseMethodPanel; + + public ConditionCheckDialog(Project project, String mainDialogTitle) { + super(project, true); + myProject = project; + + final ConditionCheckManager manager = ConditionCheckManager.getInstance(myProject); + mainSplitter = new Splitter(true, 0.3f); + final Splitter topThirdSplitter = new Splitter(false); + final Splitter bottomTwoThirdsSplitter = new Splitter(true); + final Splitter isNullIsNotNullCheckMethodSplitter = new Splitter(false); + final Splitter assertTrueFalseMethodSplitter = new Splitter(false); + + List<ConditionChecker> isNullCheckMethods = new ArrayList<ConditionChecker>(manager.getIsNullCheckMethods()); + List<ConditionChecker> isNotNullCheckMethods = new ArrayList<ConditionChecker>(manager.getIsNotNullCheckMethods()); + List<ConditionChecker> assertIsNullMethods = new ArrayList<ConditionChecker>(manager.getAssertIsNullMethods()); + List<ConditionChecker> assertIsNotNullMethods = new ArrayList<ConditionChecker>(manager.getAssertIsNotNullMethods()); + List<ConditionChecker> assertTrueMethods = new ArrayList<ConditionChecker>(manager.getAssertTrueMethods()); + List<ConditionChecker> assertFalseMethods = new ArrayList<ConditionChecker>(manager.getAssertFalseMethods()); + + myAssertIsNullMethodPanel = new MethodsPanel(assertIsNullMethods, ConditionChecker.Type.ASSERT_IS_NULL_METHOD, myProject); + myAssertIsNotNullMethodPanel = new MethodsPanel(assertIsNotNullMethods, ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD, myProject); + myIsNullCheckMethodPanel = new MethodsPanel(isNullCheckMethods, ConditionChecker.Type.IS_NULL_METHOD, myProject); + myIsNotNullCheckMethodPanel = new MethodsPanel(isNotNullCheckMethods, ConditionChecker.Type.IS_NOT_NULL_METHOD, myProject); + myAssertTrueMethodPanel = new MethodsPanel(assertTrueMethods, ConditionChecker.Type.ASSERT_TRUE_METHOD, myProject); + myAssertFalseMethodPanel = new MethodsPanel(assertFalseMethods, ConditionChecker.Type.ASSERT_FALSE_METHOD, myProject); + + isNullIsNotNullCheckMethodSplitter.setFirstComponent(myIsNullCheckMethodPanel.getComponent()); + isNullIsNotNullCheckMethodSplitter.setSecondComponent(myIsNotNullCheckMethodPanel.getComponent()); + assertTrueFalseMethodSplitter.setFirstComponent(myAssertTrueMethodPanel.getComponent()); + assertTrueFalseMethodSplitter.setSecondComponent(myAssertFalseMethodPanel.getComponent()); + + topThirdSplitter.setFirstComponent(myAssertIsNullMethodPanel.getComponent()); + topThirdSplitter.setSecondComponent(myAssertIsNotNullMethodPanel.getComponent()); + bottomTwoThirdsSplitter.setFirstComponent(isNullIsNotNullCheckMethodSplitter); + bottomTwoThirdsSplitter.setSecondComponent(assertTrueFalseMethodSplitter); + + mainSplitter.setFirstComponent(topThirdSplitter); + mainSplitter.setSecondComponent(bottomTwoThirdsSplitter); + + topThirdSplitter.setPreferredSize(new Dimension(600, 150)); + bottomTwoThirdsSplitter.setPreferredSize(new Dimension(600, 300)); + + myAssertIsNullMethodPanel + .setOtherMethodsPanels(myAssertIsNotNullMethodPanel, myIsNullCheckMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel, + myAssertFalseMethodPanel); + myAssertIsNotNullMethodPanel + .setOtherMethodsPanels(myAssertIsNullMethodPanel, myIsNullCheckMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel, + myAssertFalseMethodPanel); + myIsNullCheckMethodPanel + .setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myAssertTrueMethodPanel, + myAssertFalseMethodPanel); + myIsNotNullCheckMethodPanel + .setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNullCheckMethodPanel, myAssertTrueMethodPanel, + myAssertFalseMethodPanel); + myAssertTrueMethodPanel + .setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myIsNullCheckMethodPanel, + myAssertFalseMethodPanel); + myAssertFalseMethodPanel + .setOtherMethodsPanels(myAssertIsNullMethodPanel, myAssertIsNotNullMethodPanel, myIsNotNullCheckMethodPanel, myIsNullCheckMethodPanel, + myAssertTrueMethodPanel); + + init(); + setTitle(mainDialogTitle); + } + + @Override + protected JComponent createCenterPanel() { + return mainSplitter; + } + + @Override + protected void doOKAction() { + final ConditionCheckManager manager = ConditionCheckManager.getInstance(myProject); + manager.setIsNotNullCheckMethods(myIsNotNullCheckMethodPanel.getConditionChecker()); + manager.setIsNullCheckMethods(myIsNullCheckMethodPanel.getConditionChecker()); + manager.setAssertIsNotNullMethods(myAssertIsNotNullMethodPanel.getConditionChecker()); + manager.setAssertIsNullMethods(myAssertIsNullMethodPanel.getConditionChecker()); + manager.setAssertTrueMethods(myAssertTrueMethodPanel.getConditionChecker()); + manager.setAssertFalseMethods(myAssertFalseMethodPanel.getConditionChecker()); + + super.doOKAction(); + } + + /** + * Is Null, Is Not Null, Assert True and Assert False Method Panel at the top of the main Dialog. + */ + class MethodsPanel { + private final @NotNull JBList myList; + private final @NotNull JPanel myPanel; + private final @NotNull Project myProject; + private Set<MethodsPanel> otherPanels; + + public MethodsPanel(final List<ConditionChecker> checkers, final ConditionChecker.Type type, final @NotNull Project myProject) { + this.myProject = myProject; + myList = new JBList(new CollectionListModel<ConditionChecker>(checkers)); + myPanel = new JPanel(new BorderLayout()); + myPanel.setBorder(IdeBorderFactory.createTitledBorder(initTitle(type), false, new Insets(10, 0, 0, 0))); + myPanel.setPreferredSize(new Dimension(400, 150)); + + myList.setCellRenderer(new ColoredListCellRenderer() { + @Override + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + String s = value.toString(); + if (s.contains("*")) { + int indexOfAsterix1 = s.indexOf("*"); + int indexOfAsterix2 = s.lastIndexOf("*"); + if (indexOfAsterix1 >= 0 && + indexOfAsterix1 < s.length() && + indexOfAsterix2 >= 0 && + indexOfAsterix2 < s.length() && + indexOfAsterix1 < indexOfAsterix2) { + append(s.substring(0, indexOfAsterix1), SimpleTextAttributes.REGULAR_ATTRIBUTES); + append(s.substring(indexOfAsterix1 + 1, indexOfAsterix2), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); + append(s.substring(indexOfAsterix2 + 1), SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else { + append(s, SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + } + } + }); + + final ToolbarDecorator toolbarDecorator = + ToolbarDecorator.createDecorator(myList).disableUpDownActions().setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton anActionButton) { + chooseMethod(null, type, myList.getModel().getSize()); + } + }).setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton anActionButton) { + CollectionListModel model = getCollectionListModel(); + if (myList.getSelectedIndex() >= 0 && myList.getSelectedIndex() < model.getSize()) { + model.remove(myList.getSelectedIndex()); + } + } + }); + + myList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + int index = myList.locationToIndex(e.getPoint()); + CollectionListModel<ConditionChecker> model = getCollectionListModel(); + if (index >= 0 && model.getSize() > index) { + chooseMethod(model.getElementAt(index), type, index); + } + } + } + }); + final JPanel panel = toolbarDecorator.createPanel(); + myPanel.add(panel); + myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + + private String initTitle(@NotNull ConditionChecker.Type type) { + if (type.equals(ConditionChecker.Type.IS_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.isNull.method.panel.title"); + } + else if (type.equals(ConditionChecker.Type.IS_NOT_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.isNotNull.method.panel.title"); + } + else if (type.equals(ConditionChecker.Type.ASSERT_IS_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.isNull.method.panel.title"); + } + else if (type.equals(ConditionChecker.Type.ASSERT_IS_NOT_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.isNotNull.method.panel.title"); + } + else if (type.equals(ConditionChecker.Type.ASSERT_TRUE_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.true.method.panel.title"); + } + else if (type.equals(ConditionChecker.Type.ASSERT_FALSE_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.false.method.panel.title"); + } + else { + throw new IllegalArgumentException("MethodCheckerDetailsDialog does not support type " + type); + } + } + + private void chooseMethod(@Nullable ConditionChecker checker, ConditionChecker.Type type, int index) { + MethodCheckerDetailsDialog pickMethodPanel = + new MethodCheckerDetailsDialog(checker, type, myProject, myPanel, getConditionCheckers(), getOtherCheckers()); + pickMethodPanel.show(); + ConditionChecker chk = pickMethodPanel.getConditionChecker(); + if (chk != null) { + CollectionListModel<ConditionChecker> model = getCollectionListModel(); + if (model.getSize() <= index) { + model.add(chk); + } + else { + model.setElementAt(chk, index); + } + } + } + + private CollectionListModel<ConditionChecker> getCollectionListModel() { + //noinspection unchecked + return (CollectionListModel<ConditionChecker>)myList.getModel(); + } + + @NotNull + public JPanel getComponent() { + return myPanel; + } + + public List<ConditionChecker> getConditionChecker() { + CollectionListModel<ConditionChecker> model = getCollectionListModel(); + return new ArrayList<ConditionChecker>(model.getItems()); + } + + public Set<ConditionChecker> getConditionCheckers() { + Set<ConditionChecker> set = new HashSet<ConditionChecker>(); + set.addAll(getConditionChecker()); + return set; + } + + public void setOtherMethodsPanels(MethodsPanel p1, MethodsPanel p2, MethodsPanel p3, MethodsPanel p4, MethodsPanel p5) { + otherPanels = new HashSet<MethodsPanel>(); + otherPanels.add(p1); + otherPanels.add(p2); + otherPanels.add(p3); + otherPanels.add(p4); + otherPanels.add(p5); + } + + public Set<ConditionChecker> getOtherCheckers() { + Set<ConditionChecker> otherCheckers = new HashSet<ConditionChecker>(); + for (MethodsPanel otherPanel : otherPanels) { + otherCheckers.addAll(otherPanel.getConditionCheckers()); + } + return otherCheckers; + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index e3170217680f..05f75a3a8fcf 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInspection.dataFlow; +import com.intellij.codeInsight.ConditionCheckManager; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.dataFlow.value.*; @@ -1218,7 +1219,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { ConditionalGotoInstruction cond = new ConditionalGotoInstruction(NOT_FOUND, false, null); addInstruction(cond); addInstruction(new EmptyStackInstruction()); - addInstruction(new PushInstruction(myFactory.getTypeFactory().create(ref), null)); + addInstruction(new PushInstruction(myFactory.getNotNullFactory().create(ref), null)); addThrowCode(ref); cond.setOffset(myCurrentFlow.getInstructionCount()); } @@ -1305,7 +1306,8 @@ class ControlFlowAnalyzer extends JavaElementVisitor { return true; } } - else if ("junit.framework.Assert".equals(className) || "org.junit.Assert".equals(className) || "org.testng.Assert".equals(className)) { + else if ("junit.framework.Assert".equals(className) || "org.junit.Assert".equals(className) || + "junit.framework.TestCase".equals(className) || "org.testng.Assert".equals(className)) { boolean testng = "org.testng.Assert".equals(className); if ("fail".equals(methodName)) { pushParameters(params, false, !testng); @@ -1342,6 +1344,82 @@ class ControlFlowAnalyzer extends JavaElementVisitor { } } + if (ConditionCheckManager.isCheck(resolved)) { + if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isAssertIsNullCheckMethod(resolved, paramIndex++)) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); + conditionalExit(exitPoint, false); // Exit if Equal NULL is True + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } else if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isAssertIsNotNullCheckMethod(resolved, paramIndex++)) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); + conditionalExit(exitPoint, true); // Exit if NotEqual NULL is True + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } else if (ConditionCheckManager.isNullCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isNullCheckMethod(resolved, paramIndex++)) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.EQEQ, null, expression.getProject())); + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } else if (ConditionCheckManager.isNotNullCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isNotNullCheckMethod(resolved, paramIndex++)) { + addInstruction(new PushInstruction(myFactory.getConstFactory().getNull(), null)); + addInstruction(new BinopInstruction(JavaTokenType.NE, null, expression.getProject())); + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } else if (ConditionCheckManager.isAssertTrueCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isAssertTrueCheckMethod(resolved, paramIndex++)) { + conditionalExit(exitPoint, false); + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } else if (ConditionCheckManager.isAssertFalseCheckMethod(resolved)) { + int paramIndex = 0; + for (PsiExpression param : params) { + param.accept(this); + if (ConditionCheckManager.isAssertFalseCheckMethod(resolved, paramIndex++)) { + conditionalExit(exitPoint, true); + } else { + addInstruction(new PopInstruction()); + } + } + return true; + } + } + // Idea project only. if (qualifierExpression != null) { if (qualifierExpression.textMatches("LOG")) { diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index 56b1d22041f4..2b7bd60bae48 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -587,6 +587,24 @@ public class DataFlowInspection extends BaseLocalInspectionTool { gc.insets.bottom = 15; add(configureAnnotations, gc); + final JButton configureCheckAnnotations = new JButton(InspectionsBundle.message("configure.checker.option.button")); + configureCheckAnnotations.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Project project = PlatformDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(OptionsPanel.this)); + if (project == null) project = ProjectManager.getInstance().getDefaultProject(); + final ConditionCheckDialog dialog = new ConditionCheckDialog(project, + InspectionsBundle.message("configure.checker.option.main.dialog.title") + ); + dialog.show(); + } + }); + gc.gridy++; + gc.fill = GridBagConstraints.NONE; + gc.insets.left = 20; + gc.insets.bottom = 15; + add(configureCheckAnnotations, gc); + gc.fill = GridBagConstraints.HORIZONTAL; gc.weighty = 1; gc.insets.left = 0; diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java index dd5183d451d8..6a1ce9b2e82d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java @@ -46,7 +46,7 @@ import java.util.*; public class DataFlowRunner { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.dataFlow.DataFlowRunner"); - private static final Key<Integer> TOO_EXPENSIVE_SIZE = Key.create("TOO_EXPENSIVE_SIZE"); + private static final Key<Integer> TOO_EXPENSIVE_HASH = Key.create("TOO_EXPENSIVE_HASH"); public static final long ourTimeLimit = 1000 * 1000 * 1000; //1 sec in nanoseconds private Instruction[] myInstructions; @@ -103,14 +103,16 @@ public class DataFlowRunner { myFields = flow.getFields(); if (LOG.isDebugEnabled()) { + LOG.debug("Analyzing code block: " + psiBlock.getText()); for (int i = 0; i < myInstructions.length; i++) { Instruction instruction = myInstructions[i]; LOG.debug(i + ": " + instruction.toString()); } } - Integer tooExpensiveSize = psiBlock.getUserData(TOO_EXPENSIVE_SIZE); - if (tooExpensiveSize != null && tooExpensiveSize == psiBlock.getText().hashCode()) { + Integer tooExpensiveHash = psiBlock.getUserData(TOO_EXPENSIVE_HASH); + if (tooExpensiveHash != null && tooExpensiveHash == psiBlock.getText().hashCode()) { + LOG.debug("Too complex because hasn't changed since being too complex already"); return RunnerResult.TOO_COMPLEX; } @@ -125,7 +127,8 @@ public class DataFlowRunner { int count = 0; while (!queue.isEmpty()) { if (count % 50 == 0 && !unitTestMode && measurer.isTimeOver()) { - psiBlock.putUserData(TOO_EXPENSIVE_SIZE, psiBlock.getText().hashCode()); + LOG.debug("Too complex because the analysis took too long"); + psiBlock.putUserData(TOO_EXPENSIVE_HASH, psiBlock.getText().hashCode()); return RunnerResult.TOO_COMPLEX; } ProgressManager.checkCanceled(); @@ -140,11 +143,14 @@ public class DataFlowRunner { if (instruction instanceof BranchingInstruction) { if (!instruction.setMemoryStateProcessed(instructionState.getMemoryState().createCopy())) { + LOG.debug("Too complex because too many different possible states"); return RunnerResult.TOO_COMPLEX; // Too complex :( } } - //System.out.println(instructionState); + if (LOG.isDebugEnabled()) { + LOG.debug(instructionState.toString()); + } DfaInstructionState[] after = instruction.accept(this, instructionState.getMemoryState(), visitor); if (after != null) { @@ -160,15 +166,18 @@ public class DataFlowRunner { count++; } - psiBlock.putUserData(TOO_EXPENSIVE_SIZE, null); + psiBlock.putUserData(TOO_EXPENSIVE_HASH, null); + LOG.debug("Analysis ok"); return RunnerResult.OK; } catch (ArrayIndexOutOfBoundsException e) { - LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */ + LOG.error(psiBlock.getText(), e); // TODO fix in better times return RunnerResult.ABORTED; } catch (EmptyStackException e) { - //LOG.error(psiBlock.getText(), e); /* TODO[max] !!! hack (of 18186). Please fix in better times. */ + if (LOG.isDebugEnabled()) { + LOG.error(e); // TODO fix in better times + } return RunnerResult.ABORTED; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/MethodCheckerDetailsDialog.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/MethodCheckerDetailsDialog.java new file mode 100644 index 000000000000..5d34364e6452 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/MethodCheckerDetailsDialog.java @@ -0,0 +1,708 @@ +/* + * Copyright 2000-2013 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.codeInspection.dataFlow; + +import com.intellij.codeInsight.*; +import com.intellij.codeInspection.*; +import com.intellij.ide.util.*; +import com.intellij.openapi.editor.event.*; +import com.intellij.openapi.project.*; +import com.intellij.openapi.ui.*; +import com.intellij.psi.*; +import com.intellij.psi.search.*; +import com.intellij.ui.*; +import org.jetbrains.annotations.*; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.beans.*; +import java.util.*; +import java.util.List; + +import static com.intellij.codeInsight.ConditionChecker.Type.*; + +/** + * Dialog that appears when the user clicks the Add Button or double clicks a row item in a MethodsPanel. The MethodsPanel is accessed from the ConditionCheckDialog + */ +class MethodCheckerDetailsDialog extends DialogWrapper implements PropertyChangeListener, ItemListener { + private final @NotNull ConditionChecker.Type myType; + private final @NotNull Project myProject; + private final @NotNull ParameterDropDown parameterDropDown; + private final @NotNull MethodDropDown methodDropDown; + private final @NotNull ClassField classField; + private final @NotNull Set<ConditionChecker> myOtherCheckers; + private final @Nullable ConditionChecker myPreviouslySelectedChecker; + /** + * Set by the OK and/or Cancel actions so that the caller can retrieve it via a call to getMethodIsNullIsNotNullChecker + */ + private @Nullable ConditionChecker mySelectedChecker; + + MethodCheckerDetailsDialog(@Nullable ConditionChecker previouslySelectedChecker, + @NotNull ConditionChecker.Type type, + @NotNull Project project, + @NotNull Component component, + @NotNull Set<ConditionChecker> otherCheckersSameType, + @NotNull Set<ConditionChecker> otherCheckers) { + super(component, true); + if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type); + + myProject = project; + myType = type; + myOtherCheckers = new HashSet<ConditionChecker>(otherCheckersSameType); + myOtherCheckers.addAll(otherCheckers); + myPreviouslySelectedChecker = previouslySelectedChecker; + if (myPreviouslySelectedChecker != null) myOtherCheckers.remove(myPreviouslySelectedChecker); + + PsiClass psiClass = null; + PsiMethod psiMethod = null; + PsiParameter psiParameter = null; + if (previouslySelectedChecker != null) { + psiClass = + JavaPsiFacade.getInstance(myProject).findClass(previouslySelectedChecker.getClassName(), GlobalSearchScope.allScope(myProject)); + if (psiClass != null) { + for (PsiMethod method : psiClass.findMethodsByName(previouslySelectedChecker.getMethodName(), true)) { + if (previouslySelectedChecker.equals(buildParameterClassListFromPsiMethod(method))) { + psiMethod = method; + break; + } + } + } + + if (psiMethod != null) { + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + if (parameters.length - 1 >= previouslySelectedChecker.getCheckedParameterIndex()) { + psiParameter = parameters[previouslySelectedChecker.getCheckedParameterIndex()]; + } + } + } + + if (psiClass == null || psiMethod == null || psiParameter == null) { + psiClass = null; + psiMethod = null; + psiParameter = null; + } + + classField = new ClassField(myProject, psiClass); + methodDropDown = new MethodDropDown(psiClass, psiMethod, myType, MethodDropDown.buildModel()); + parameterDropDown = new ParameterDropDown(psiMethod, psiParameter, ParameterDropDown.buildModel(), myType); + classField.addPropertyChangeListener(methodDropDown); + classField.addPropertyChangeListener(parameterDropDown); + classField.addPropertyChangeListener(this); + methodDropDown.addItemListener(parameterDropDown); + methodDropDown.addItemListener(this); + parameterDropDown.addItemListener(this); + init(); + checkOkActionEnable(); + setTitle(initTitle(type)); + } + + private static boolean isSupported(ConditionChecker.Type type) { + return type == IS_NULL_METHOD || type == IS_NOT_NULL_METHOD || + type == ASSERT_IS_NULL_METHOD || type == ASSERT_IS_NOT_NULL_METHOD || + type == ASSERT_TRUE_METHOD || type == ASSERT_FALSE_METHOD; + } + + private static List<String> buildParameterClassListFromPsiMethod(PsiMethod psiMethod) { + List<String> parameterClasses = new ArrayList<String>(); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (PsiParameter param : parameters) { + PsiTypeElement typeElement = param.getTypeElement(); + if (typeElement == null) return new ArrayList<String>(); + + PsiType psiType = typeElement.getType(); + + parameterClasses.add(psiType.getCanonicalText()); + } + return parameterClasses; + } + + private static String initTitle(@NotNull ConditionChecker.Type type) { + if (type.equals(IS_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.isNull.add.method.checker.dialog.title"); + } + else if (type.equals(IS_NOT_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.isNotNull.add.method.checker.dialog.title"); + } + else if (type.equals(ASSERT_IS_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.isNull.add.method.checker.dialog.title"); + } + else if (type.equals(ASSERT_IS_NOT_NULL_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.isNotNull.add.method.checker.dialog.title"); + } + else if (type.equals(ASSERT_TRUE_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.true.add.method.checker.dialog.title"); + } + else if (type.equals(ASSERT_FALSE_METHOD)) { + return InspectionsBundle.message("configure.checker.option.assert.false.add.method.checker.dialog.title"); + } + else { + throw new IllegalArgumentException("MethodCheckerDetailsDialog does not support type " + type); + } + } + + @Override + protected JComponent createCenterPanel() { + final JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + + final LabeledComponent<ClassField> classComponent = new LabeledComponent<ClassField>(); + final LabeledComponent<MethodDropDown> methodComponent = new LabeledComponent<MethodDropDown>(); + final LabeledComponent<ParameterDropDown> parameterComponent = new LabeledComponent<ParameterDropDown>(); + + classComponent.setText("Class"); + methodComponent.setText("Method"); + parameterComponent.setText("Parameter"); + + classComponent.setComponent(classField); + methodComponent.setComponent(methodDropDown); + parameterComponent.setComponent(parameterDropDown); + + panel.add(classComponent); + panel.add(methodComponent); + panel.add(parameterComponent); + + return panel; + } + + @Nullable + ConditionChecker getConditionChecker() { + return mySelectedChecker; + } + + @Nullable + private ConditionChecker buildConditionChecker() { + PsiClass psiClass = classField.getPsiClass(); + PsiMethod psiMethod = methodDropDown.getSelectedPsiMethod(); + PsiParameter psiParameter = parameterDropDown.getSelectedPsiParameter(); + if (psiClass != null && psiMethod != null && psiParameter != null) { + return new ConditionChecker.FromPsiBuilder(psiMethod, psiParameter, myType).build(); + } + else { + return null; + } + } + + private boolean overlaps(ConditionChecker thisChecker) { + for (ConditionChecker overlappingChecker : myOtherCheckers) { + if (thisChecker.overlaps(overlappingChecker)) { + Messages.showMessageDialog(myProject, InspectionsBundle.message("configure.checker.option.overlap.error.msg") + + " " + + overlappingChecker.getConditionCheckType() + " " + overlappingChecker.toString(), + InspectionsBundle.message("configure.checker.option.overlap.error.title"), Messages.getErrorIcon()); + return true; + } + } + return false; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + checkOkActionEnable(); + } + + @Override + public void itemStateChanged(ItemEvent e) { + checkOkActionEnable(); + } + + private void checkOkActionEnable() { + if (classField.getPsiClass() == null || + methodDropDown.getSelectedPsiMethod() == null || + parameterDropDown.getSelectedPsiParameter() == null) { + setOKActionEnabled(false); + } + else { + setOKActionEnabled(true); + } + } + + @Override + protected void doOKAction() { + ConditionChecker checker = buildConditionChecker(); + if (checker != null && !overlaps(checker)) { + if (checker.equals(myPreviouslySelectedChecker)) { + mySelectedChecker = myPreviouslySelectedChecker; + } + else { + mySelectedChecker = checker; + } + super.doOKAction(); + } + } + + public boolean isOKActionEnabled() { + if (!myOKAction.isEnabled()) return false; + PsiClass psiClass = classField.getPsiClass(); + PsiMethod psiMethod = methodDropDown.getSelectedPsiMethod(); + PsiParameter psiParameter = parameterDropDown.getSelectedPsiParameter(); + if (psiClass == null || psiMethod == null || psiParameter == null) { + return false; + } + else { + return true; + } + } + + /** + * Input Text Field for Class Name + */ + static class ClassField extends EditorTextFieldWithBrowseButton implements ActionListener, DocumentListener { + public static final String PROPERTY_PSICLASS = "ClassField.myPsiClass"; + private final @NotNull Project myProject; + private @Nullable PsiClass myPsiClass; + + public ClassField(@NotNull Project project, @Nullable PsiClass psiClass) { + super(project, true, buildVisibilityChecker()); + myProject = project; + myPsiClass = psiClass; + setPreferredSize(new Dimension(500, (int)getPreferredSize().getHeight())); + if (myPsiClass != null) { //noinspection ConstantConditions + setText(myPsiClass.getQualifiedName()); + } + addActionListener(this); + getChildComponent().addDocumentListener(this); + } + + private static JavaCodeFragment.VisibilityChecker buildVisibilityChecker() { + return new JavaCodeFragment.VisibilityChecker() { + @Override + public Visibility isDeclarationVisible(PsiElement declaration, PsiElement place) { + return Visibility.VISIBLE; + } + }; + } + + @Override + public void actionPerformed(ActionEvent e) { + final TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject) + .createNoInnerClassesScopeChooser("Choose Class", GlobalSearchScope.allScope(myProject), new ClassFilter() { + @Override + public boolean isAccepted(PsiClass aClass) { + return !aClass.isAnnotationType(); + } + }, null); + chooser.showDialog(); + PsiClass psiClass = chooser.getSelected(); + if (psiClass != null) { //noinspection ConstantConditions + setText(chooser.getSelected().getQualifiedName()); + } + } + + @Nullable + public PsiClass getPsiClass() { + return myPsiClass; + } + + @Override + public void beforeDocumentChange(DocumentEvent event) { + } + + @Override + public void documentChanged(DocumentEvent event) { + String className = event.getDocument().getText(); + PsiClass psiClass = null; + if (className != null) { + psiClass = JavaPsiFacade.getInstance(myProject).findClass(className, GlobalSearchScope.allScope(myProject)); + } + + if (psiClass != null && myPsiClass != null) { + if (!psiClass.equals(myPsiClass)) { + firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass); + myPsiClass = psiClass; + } + } + else if (psiClass != null) { + firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass); + myPsiClass = psiClass; + } + else if (myPsiClass != null) { + firePropertyChange(PROPERTY_PSICLASS, myPsiClass, psiClass); + myPsiClass = null; + } + } + } + + /** + * Drop Down for picking Method Name + */ + static class MethodDropDown extends JComboBox implements PropertyChangeListener { + private final @NotNull ConditionChecker.Type myType; + private final @NotNull SortedComboBoxModel<MethodWrapper> myModel; + private @Nullable PsiClass myPsiClass; + + MethodDropDown(@Nullable PsiClass psiClass, + @Nullable PsiMethod psiMethod, + @NotNull ConditionChecker.Type type, + @NotNull SortedComboBoxModel<MethodWrapper> model) { + super(model); + + if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type); + + myPsiClass = psiClass; + myType = type; + myModel = model; + setEnabled(myPsiClass != null); + initValues(); + if (psiMethod != null) { + for (Iterator<MethodWrapper> iterator = myModel.iterator(); iterator.hasNext(); ) { + MethodWrapper methodWrapper = iterator.next(); + if (methodWrapper.getPsiMethod().equals(psiMethod)) { + setSelectedItem(methodWrapper); + } + } + } + } + + private static boolean isMethodFromJavaLangObject(PsiMethod method) { + if (method == null) return false; + + PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) return false; + String name = containingClass.getQualifiedName(); + if (name == null) return false; + + if (CommonClassNames.JAVA_LANG_OBJECT.equals(name)) return true; + + return false; + } + + @NotNull + public static SortedComboBoxModel<MethodWrapper> buildModel() { + return new SortedComboBoxModel<MethodWrapper>(new Comparator<MethodWrapper>() { + @Override + public int compare(MethodWrapper o1, MethodWrapper o2) { + return o1.compareTo(o2); + } + }); + } + + private void initValues() { + if (myPsiClass != null) { + myModel.clear(); + myModel.setSelectedItem(null); + PsiMethod[] allMethods = myPsiClass.getAllMethods(); + for (PsiMethod method : allMethods) { + MethodWrapper methodWrapper = new MethodWrapper(method); + if (qualifies(method) && !myModel.getItems().contains(methodWrapper)) myModel.add(methodWrapper); + } + } + } + + public boolean qualifies(PsiMethod psiMethod) { + if (isMethodFromJavaLangObject(psiMethod)) { + return false; + } + + final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + if (parameters.length < 1) { + return false; + } + + if (myType == IS_NULL_METHOD || myType == IS_NOT_NULL_METHOD) { + PsiType returnType = psiMethod.getReturnType(); + if (returnType != PsiType.BOOLEAN && (returnType == null || !returnType.getCanonicalText().equals(Boolean.class.toString()))) { + return false; + } + } + else if (myType == ASSERT_TRUE_METHOD || myType == ASSERT_FALSE_METHOD) { + boolean booleanParamExists = false; + for (PsiParameter psiParameter : parameters) { + PsiType type = psiParameter.getType(); + if (type.equals(PsiType.BOOLEAN) || type.getCanonicalText().equals(Boolean.class.toString())) { + booleanParamExists = true; + break; + } + } + + if (!booleanParamExists) { + return false; + } + } + // Else it's ASSERT_IS_NULL_METHOD or ASSERT_IS_NOT_NULL_METHOD. + // In that case there is no additional validation + + return true; + } + + /** + * Called when ClassField is set and when user selects entry in the MethodDropDown + */ + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(ClassField.PROPERTY_PSICLASS)) { + if (evt.getNewValue() == null) { + clear(); + } + else { + setEnabled(true); + if (myPsiClass == null || !myPsiClass.equals(evt.getNewValue())) { // ClassChanged so refresh list + myPsiClass = (PsiClass)evt.getNewValue(); + initValues(); + } + } + } + } + + public void clear() { + myModel.clear(); + myModel.setSelectedItem(null); + setEnabled(false); + myPsiClass = null; + } + + @Nullable + public PsiMethod getSelectedPsiMethod() { + MethodWrapper methodWrapper = myModel.getSelectedItem(); + if (methodWrapper == null) return null; + + return methodWrapper.getPsiMethod(); + } + } + + /** + * Drop Down for picking Parameter Name + */ + static class ParameterDropDown extends JComboBox implements PropertyChangeListener, ItemListener { + private final @NotNull SortedComboBoxModel<ParameterWrapper> myModel; + private final @NotNull ConditionChecker.Type myType; + private @Nullable PsiMethod myPsiMethod; + + public ParameterDropDown(@Nullable PsiMethod psiMethod, + @Nullable PsiParameter psiParameter, + @NotNull SortedComboBoxModel<ParameterWrapper> model, + @NotNull ConditionChecker.Type type) { + super(model); + + if (!isSupported(type)) throw new IllegalArgumentException("Type is invalid " + type); + + myPsiMethod = psiMethod; + myModel = model; + myType = type; + + if (myPsiMethod != null) { + setEnabled(true); + myModel.addAll(getParameterWrappers()); + if (psiParameter != null) { + for (Iterator iterator = myModel.iterator(); iterator.hasNext(); ) { + ParameterWrapper wrapper = (ParameterWrapper)iterator.next(); + if (wrapper.getPsiParameter().equals(psiParameter)) setSelectedItem(wrapper); + } + } + } + else { + setEnabled(false); + } + } + + public static SortedComboBoxModel<ParameterWrapper> buildModel() { + return new SortedComboBoxModel<ParameterWrapper>(new Comparator<ParameterWrapper>() { + @Override + public int compare(ParameterWrapper o1, ParameterWrapper o2) { + return o1.compareTo(o2); + } + }); + } + + List<ParameterWrapper> getParameterWrappers() { + List<ParameterWrapper> wrappers = new ArrayList<ParameterWrapper>(); + if (myPsiMethod != null) { + PsiParameterList parameterList = myPsiMethod.getParameterList(); + for (int i = 0; i < parameterList.getParameters().length; i++) { + PsiParameter psiParameter = parameterList.getParameters()[i]; + if (myType == ASSERT_TRUE_METHOD || myType == ASSERT_FALSE_METHOD) { + PsiType type = psiParameter.getType(); + if (type.equals(PsiType.BOOLEAN) || type.getCanonicalText().equals(Boolean.class.toString())) { + wrappers.add(new ParameterWrapper(psiParameter, i)); + } + } + else { + wrappers.add(new ParameterWrapper(psiParameter, i)); + } + + } + } + return wrappers; + } + + @Override + public void itemStateChanged(ItemEvent e) { + if (e.getSource() instanceof MethodDropDown) { // The MethodDropDown has changed. + MethodDropDown methodDropDown = (MethodDropDown)e.getSource(); + if (methodDropDown.getSelectedPsiMethod() != null) { + setEnabled(true); + if (myPsiMethod == null || !myPsiMethod.equals(methodDropDown.getSelectedPsiMethod())) { + myPsiMethod = methodDropDown.getSelectedPsiMethod(); + myModel.clear(); + myModel.addAll(getParameterWrappers()); + myModel.setSelectedItem(null); + } + } + else { + myPsiMethod = null; + myModel.clear(); + myModel.setSelectedItem(null); + setEnabled(false); + } + } + else { + throw new RuntimeException("Unexpected Configuration ParameterDropDown is only expected to receive events from MethodDropDown."); + } + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(ClassField.PROPERTY_PSICLASS)) { + if (evt.getNewValue() == null) { + setEnabled(false); + } + } + } + + @Nullable + public PsiParameter getSelectedPsiParameter() { + ParameterWrapper parameterWrapper = myModel.getSelectedItem(); + if (parameterWrapper == null) return null; + + return parameterWrapper.getPsiParameter(); + } + + class ParameterWrapper implements Comparable<ParameterWrapper> { + private final @NotNull String id; + private final @NotNull PsiParameter psiParameter; + private final int index; + + ParameterWrapper(@NotNull PsiParameter psiParameter, int index) { + this.psiParameter = psiParameter; + this.index = index; + String typeName; + PsiTypeElement typeElement = psiParameter.getTypeElement(); + if (typeElement == null) { + typeName = ""; + } + else { + if (typeElement.getType() instanceof PsiPrimitiveType) { + typeName = ((PsiPrimitiveType)typeElement.getType()).getBoxedTypeName(); + } + else { + typeName = typeElement.getType().getCanonicalText(); + } + } + + id = typeName + " " + psiParameter.getName(); + } + + @Override + public int compareTo(ParameterWrapper o) { + return index - o.index; + } + + @Override + public String toString() { + return id; + } + + @NotNull + public PsiParameter getPsiParameter() { + return psiParameter; + } + } + } + + static class MethodWrapper implements Comparable<MethodWrapper> { + private final @NotNull PsiMethod myPsiMethod; + private final @NotNull String myId; + + MethodWrapper(@NotNull PsiMethod psiMethod) { + this.myPsiMethod = psiMethod; + + List<String> parameterClassNames = new ArrayList<String>(); + PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + for (PsiParameter psiParameter : parameters) { + parameterClassNames.add(getParameterQualifiedName(psiParameter)); + } + + myId = initId(psiMethod.getName(), parameterClassNames); + } + + private static String getParameterQualifiedName(PsiParameter psiParameter) { + PsiTypeElement typeElement = psiParameter.getTypeElement(); + if (typeElement == null) { + return ""; + } + + if (typeElement.getType() instanceof PsiPrimitiveType) { + return ((PsiPrimitiveType)typeElement.getType()).getBoxedTypeName(); + } + + return typeElement.getType().getCanonicalText(); + } + + private static String initId(String methodName, List<String> parameterNames) { + String shortName = methodName + "("; + for (String parameterName : parameterNames) { + if (parameterNames.lastIndexOf(".") > -1) { + shortName += parameterName.substring(parameterName.lastIndexOf(".") + 1) + ", "; + } + else { + shortName += parameterName + ", "; + } + } + + if (parameterNames.size() > 0) shortName = shortName.substring(0, shortName.lastIndexOf(", ")); + + shortName += ")"; + return shortName; + } + + @NotNull + public PsiMethod getPsiMethod() { + return myPsiMethod; + } + + @NotNull + public String getId() { + return myId; + } + + @Override + public String toString() { + return myId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MethodWrapper that = (MethodWrapper)o; + + if (!myId.equals(that.myId)) return false; + + return true; + } + + @Override + public int hashCode() { + return myId.hashCode(); + } + + @Override + public int compareTo(MethodWrapper o) { + return myId.compareTo(o.myId); + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java index 5ee8cadb7ffd..d379a9f8e079 100644 --- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java +++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/MethodBodyChecker.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -33,7 +33,6 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.reference.SoftReference; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.PatchedSoftReference; import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -82,7 +81,7 @@ public class MethodBodyChecker { SoftReference<Map<String, PsiMethod>> ref = aClass.getUserData(CACHE_KEY); Map<String, PsiMethod> cache = ref == null ? null : ref.get(); if (cache == null) { - aClass.putUserData(CACHE_KEY, new PatchedSoftReference<Map<String, PsiMethod>>(cache = new ConcurrentHashMap<String, PsiMethod>())); + aClass.putUserData(CACHE_KEY, new SoftReference<Map<String, PsiMethod>>(cache = new ConcurrentHashMap<String, PsiMethod>())); } return cache; } @@ -107,7 +106,7 @@ public class MethodBodyChecker { if (PsiEquivalenceUtil.areElementsEquivalent(body, templateBody, new Comparator<PsiElement>(){ public int compare(final PsiElement element1, final PsiElement element2) { - // templates may be different on super method name + // templates may be different on super method name if (element1 == superMethod && (element2 == templateMethod || element2 == null)) return 0; return 1; } diff --git a/java/java-impl/src/com/intellij/codeInspection/java15api/api1.7.txt b/java/java-impl/src/com/intellij/codeInspection/java15api/api1.7.txt index f700c1f4b19c..316c990b2806 100644 --- a/java/java-impl/src/com/intellij/codeInspection/java15api/api1.7.txt +++ b/java/java-impl/src/com/intellij/codeInspection/java15api/api1.7.txt @@ -304,7 +304,6 @@ java.awt.Window#setOpacity(float;) java.awt.Window#getShape() java.awt.Window#setShape(java.awt.Shape;) java.awt.Window#isOpaque() -java.awt.Window#paint(java.awt.Graphics;) java.awt.GraphicsConfiguration#isTranslucencyCapable() java.awt.event.InvocationEvent#dispatched java.awt.event.InvocationEvent#isDispatched() diff --git a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java index 11caefd75ef8..f185806be3c6 100644 --- a/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/magicConstant/MagicConstantInspection.java @@ -292,7 +292,8 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { private static AllowedValues getAllowedValuesFromMagic(@NotNull PsiModifierListOwner element, @NotNull PsiType type, - @NotNull PsiAnnotation magic) { + @NotNull PsiAnnotation magic, + @NotNull PsiManager manager) { PsiAnnotationMemberValue[] allowedValues; final boolean canBeOred; if (TypeConversionUtil.getTypeRank(type) <= TypeConversionUtil.LONG_RANK) { @@ -307,7 +308,7 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { canBeOred = false; } } - else if (type.equals(PsiType.getJavaLangString(element.getManager(), GlobalSearchScope.allScope(element.getProject())))) { + else if (type.equals(PsiType.getJavaLangString(manager, GlobalSearchScope.allScope(manager.getProject())))) { PsiAnnotationMemberValue strValuesAttr = magic.findAttributeValue("stringValues"); allowedValues = strValuesAttr instanceof PsiArrayInitializerMemberValue ? ((PsiArrayInitializerMemberValue)strValuesAttr).getInitializers() : PsiAnnotationMemberValue.EMPTY_ARRAY; canBeOred = false; @@ -321,17 +322,20 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { } // last resort: try valuesFromClass - PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type); + PsiAnnotationMemberValue[] values = readFromClass("valuesFromClass", magic, type, manager); boolean ored = false; if (values == null) { - values = readFromClass("flagsFromClass", magic, type); + values = readFromClass("flagsFromClass", magic, type, manager); ored = true; } if (values == null) return null; return new AllowedValues(values, ored); } - private static PsiAnnotationMemberValue[] readFromClass(@NonNls @NotNull String attributeName, @NotNull PsiAnnotation magic, @NotNull PsiType type) { + private static PsiAnnotationMemberValue[] readFromClass(@NonNls @NotNull String attributeName, + @NotNull PsiAnnotation magic, + @NotNull PsiType type, + @NotNull PsiManager manager) { PsiAnnotationMemberValue fromClassAttr = magic.findAttributeValue(attributeName); PsiType fromClassType = fromClassAttr instanceof PsiClassObjectAccessExpression ? ((PsiClassObjectAccessExpression)fromClassAttr).getOperand().getType() : null; PsiClass fromClass = fromClassType instanceof PsiClassType ? ((PsiClassType)fromClassType).resolve() : null; @@ -343,7 +347,7 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { if (!field.hasModifierProperty(PsiModifier.PUBLIC) || !field.hasModifierProperty(PsiModifier.STATIC) || !field.hasModifierProperty(PsiModifier.FINAL)) continue; PsiType fieldType = field.getType(); if (!Comparing.equal(fieldType, type)) continue; - PsiAssignmentExpression e = (PsiAssignmentExpression)JavaPsiFacade.getElementFactory(field.getProject()).createExpressionFromText("x="+fqn + "." + field.getName(), field); + PsiAssignmentExpression e = (PsiAssignmentExpression)JavaPsiFacade.getElementFactory(manager.getProject()).createExpressionFromText("x="+fqn + "." + field.getName(), field); PsiReferenceExpression refToField = (PsiReferenceExpression)e.getRExpression(); constants.add(refToField); } @@ -354,11 +358,12 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { static AllowedValues getAllowedValues(@NotNull PsiModifierListOwner element, PsiType type, Set<PsiClass> visited) { PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(element, true, null); + PsiManager manager = element.getManager(); for (PsiAnnotation annotation : annotations) { AllowedValues values; if (type != null && MagicConstant.class.getName().equals(annotation.getQualifiedName())) { //PsiAnnotation magic = AnnotationUtil.findAnnotationInHierarchy(element, Collections.singleton(MagicConstant.class.getName())); - values = getAllowedValuesFromMagic(element, type, annotation); + values = getAllowedValuesFromMagic(element, type, annotation, manager); if (values != null) return values; } @@ -372,10 +377,10 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { if (values != null) return values; } - return parseBeanInfo(element); + return parseBeanInfo(element, manager); } - private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner) { + private static AllowedValues parseBeanInfo(@NotNull PsiModifierListOwner owner, @NotNull PsiManager manager) { PsiMethod method = null; if (owner instanceof PsiParameter) { PsiParameter parameter = (PsiParameter)owner; @@ -442,7 +447,7 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { List<String> words = StringUtil.split(line, " ", true, true); if (words.size() != 2) continue; String ref = words.get(1); - PsiExpression constRef = JavaPsiFacade.getElementFactory(aClass.getProject()).createExpressionFromText(ref, aClass); + PsiExpression constRef = JavaPsiFacade.getElementFactory(manager.getProject()).createExpressionFromText(ref, aClass); if (!(constRef instanceof PsiReferenceExpression)) continue; PsiReferenceExpression expr = (PsiReferenceExpression)constRef; values.add(expr); @@ -492,7 +497,7 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { final Set<PsiExpression> visited) { if (isGoodExpression(argument, allowedValues, scope, manager, visited)) return true; - return processValuesFlownTo(argument, scope, new Processor<PsiExpression>() { + return processValuesFlownTo(argument, scope, manager, new Processor<PsiExpression>() { @Override public boolean process(PsiExpression expression) { return isGoodExpression(expression, allowedValues, scope, manager, visited); @@ -594,12 +599,13 @@ public class MagicConstantInspection extends BaseJavaLocalInspectionTool { private static boolean processValuesFlownTo(@NotNull final PsiExpression argument, @NotNull PsiElement scope, + @NotNull PsiManager manager, @NotNull final Processor<PsiExpression> processor) { SliceAnalysisParams params = new SliceAnalysisParams(); params.dataFlowToThis = true; - params.scope = new AnalysisScope(new LocalSearchScope(scope), argument.getProject()); + params.scope = new AnalysisScope(new LocalSearchScope(scope), manager.getProject()); - SliceRootNode rootNode = new SliceRootNode(scope.getProject(), new DuplicateMap(), SliceManager.createRootUsage(argument, params)); + SliceRootNode rootNode = new SliceRootNode(manager.getProject(), new DuplicateMap(), SliceManager.createRootUsage(argument, params)); Collection<? extends AbstractTreeNode> children = rootNode.getChildren().iterator().next().getChildren(); for (AbstractTreeNode child : children) { diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java b/java/java-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java index a8edce01d507..03a202db332e 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java @@ -81,7 +81,9 @@ public class AnnotateOverriddenMethodParameterFix implements LocalQuickFix { for (PsiParameter psiParam : toAnnotate) { try { assert psiParam != null : toAnnotate; - new AddAnnotationFix(myAnnotation, psiParam, myAnnosToRemove).invoke(project, null, psiParam.getContainingFile()); + if (AnnotationUtil.isAnnotatingApplicable(psiParam, myAnnotation)) { + new AddAnnotationFix(myAnnotation, psiParam, myAnnosToRemove).invoke(project, null, psiParam.getContainingFile()); + } } catch (IncorrectOperationException e) { LOG.error(e); diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java b/java/java-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java new file mode 100644 index 000000000000..53b439f0d2d5 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/ChangeNullableDefaultsFix.java @@ -0,0 +1,66 @@ +/* + * Copyright 2000-2013 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.codeInspection.nullable; + +import com.intellij.codeInsight.NullableNotNullManager; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiAnnotation; +import org.jetbrains.annotations.NotNull; + +/** +* User: anna +* Date: 2/22/13 +*/ +class ChangeNullableDefaultsFix implements LocalQuickFix { + private final NullableNotNullManager myManager; + private final String myNotNullName; + private final String myNullableName; + + public ChangeNullableDefaultsFix(PsiAnnotation notNull, PsiAnnotation nullable, NullableNotNullManager manager) { + myNotNullName = notNull != null ? notNull.getQualifiedName() : null; + myNullableName = nullable != null ? nullable.getQualifiedName() : null; + myManager = manager; + } + + ChangeNullableDefaultsFix(String notNull, String nullable, NullableNotNullManager manager) { + myManager = manager; + myNotNullName = notNull; + myNullableName = nullable; + } + + @NotNull + @Override + public String getName() { + return "Make \"" + (myNotNullName != null ? myNotNullName : myNullableName) + "\" default annotation"; + } + + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + if (myNotNullName != null) { + myManager.setDefaultNotNull(myNotNullName); + } else { + myManager.setDefaultNullable(myNullableName); + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index 6923ccceb060..b59d821bbecf 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -79,13 +79,21 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { if (TypeConversionUtil.isPrimitiveAndNotNull(type)) { return; } - final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject()); + Project project = holder.getProject(); + final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); if (annotated.isDeclaredNotNull ^ annotated.isDeclaredNullable) { final String anno = annotated.isDeclaredNotNull ? manager.getDefaultNotNull() : manager.getDefaultNullable(); final List<String> annoToRemove = annotated.isDeclaredNotNull ? manager.getNullables() : manager.getNotNulls(); - final String propName = JavaCodeStyleManager.getInstance(field.getProject()).variableNameToPropertyName(field.getName(), - VariableKind.FIELD); + if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) { + final PsiAnnotation notNull = AnnotationUtil.findAnnotation(field, manager.getNotNulls()); + final PsiAnnotation nullable = AnnotationUtil.findAnnotation(field, manager.getNullables()); + holder.registerProblem(field.getNameIdentifier(), "Nullable/NotNull defaults are not accessible in current context", + new ChangeNullableDefaultsFix(notNull, nullable, manager)); + return; + } + + String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD); final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC); final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false); final String nullableSimpleName = StringUtil.getShortName(manager.getDefaultNullable()); @@ -223,7 +231,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } } private static Annotated check(final PsiModifierListOwner parameter, final ProblemsHolder holder, PsiType type) { - final NullableNotNullManager manager = NullableNotNullManager.getInstance(parameter.getProject()); + final NullableNotNullManager manager = NullableNotNullManager.getInstance(holder.getProject()); PsiAnnotation isDeclaredNotNull = AnnotationUtil.findAnnotation(parameter, manager.getNotNulls()); PsiAnnotation isDeclaredNullable = AnnotationUtil.findAnnotation(parameter, manager.getNullables()); if (isDeclaredNullable != null && isDeclaredNotNull != null) { @@ -289,9 +297,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { reported_not_annotated_method_overrides_notnull = true; final String defaultNotNull = nullableManager.getDefaultNotNull(); final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); + final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull) + ? createAnnotateMethodFix(defaultNotNull, annotationsToRemove) + : createChangeDefaultNotNullFix(nullableManager, superMethod); holder.registerProblem(method.getNameIdentifier(), InspectionsBundle.message("inspection.nullable.problems.method.overrides.NotNull"), - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, createAnnotateMethodFix(defaultNotNull, annotationsToRemove)); + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + wrapFix(fix)); } if (REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE || REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL) { PsiParameter[] superParameters = superMethod.getParameterList().getParameters(); @@ -313,10 +325,13 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { if (!AnnotationUtil.isAnnotated(parameter, nullableManager.getAllAnnotations(), false, false) && nullableManager.isNotNull(superParameter, false)) { reported_not_annotated_parameter_overrides_notnull[i] = true; + final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, nullableManager.getDefaultNotNull()) + ? new AddNotNullAnnotationFix(parameter) + : createChangeDefaultNotNullFix(nullableManager, superParameter); holder.registerProblem(parameter.getNameIdentifier(), InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new AddNotNullAnnotationFix(parameter)); + wrapFix(fix)); } } } @@ -334,22 +349,34 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } if (hasAnnotatedParameter || annotated.isDeclaredNotNull) { PsiManager manager = method.getManager(); + final String defaultNotNull = nullableManager.getDefaultNotNull(); + final boolean superMethodApplicable = AnnotationUtil.isAnnotatingApplicable(method, defaultNotNull); PsiMethod[] overridings = OverridingMethodsSearch.search(method, GlobalSearchScope.allScope(manager.getProject()), true).toArray(PsiMethod.EMPTY_ARRAY); boolean methodQuickFixSuggested = false; for (PsiMethod overriding : overridings) { if (!manager.isInProject(overriding)) continue; + + final boolean applicable = AnnotationUtil.isAnnotatingApplicable(overriding, defaultNotNull); if (!methodQuickFixSuggested && annotated.isDeclaredNotNull && !nullableManager.isNotNull(overriding, false) && (nullableManager.isNullable(overriding, false) || !nullableManager.isNullable(overriding, true))) { method.getNameIdentifier(); //load tree - PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls()); - final String defaultNotNull = nullableManager.getDefaultNotNull(); + PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNotNulls()); final String[] annotationsToRemove = ArrayUtil.toStringArray(nullableManager.getNullables()); + + final LocalQuickFix fix; + if (applicable) { + fix = new MyAnnotateMethodFix(defaultNotNull, annotationsToRemove); + } + else { + fix = superMethodApplicable ? null : createChangeDefaultNotNullFix(nullableManager, method); + } + holder.registerProblem(annotation, InspectionsBundle.message("nullable.stuff.problems.overridden.methods.are.not.annotated"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new MyAnnotateMethodFix(defaultNotNull, annotationsToRemove)); + wrapFix(fix)); methodQuickFixSuggested = true; } if (hasAnnotatedParameter) { @@ -363,7 +390,7 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { holder.registerProblem(annotation, InspectionsBundle.message("nullable.stuff.problems.overridden.method.parameters.are.not.annotated"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, - new AnnotateOverriddenMethodParameterFix(nullableManager.getDefaultNotNull(), nullableManager.getDefaultNullable())); + wrapFix(!applicable ? createChangeDefaultNotNullFix(nullableManager, parameters[i]) : new AnnotateOverriddenMethodParameterFix(defaultNotNull, nullableManager.getDefaultNullable()))); parameterQuickFixSuggested[i] = true; } } @@ -373,6 +400,19 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { } } + private static LocalQuickFix[] wrapFix(LocalQuickFix fix) { + if (fix == null) return LocalQuickFix.EMPTY_ARRAY; + return new LocalQuickFix[]{fix}; + } + + private static LocalQuickFix createChangeDefaultNotNullFix(NullableNotNullManager nullableManager, PsiModifierListOwner modifierListOwner) { + final PsiAnnotation annotation = AnnotationUtil.findAnnotation(modifierListOwner, nullableManager.getNotNulls()); + if (annotation != null) { + return new ChangeNullableDefaultsFix(annotation.getQualifiedName(), null, nullableManager); + } + return null; + } + protected AnnotateMethodFix createAnnotateMethodFix(final String defaultNotNull, final String[] annotationsToRemove) { return new AnnotateMethodFix(defaultNotNull, annotationsToRemove); } diff --git a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java index b124faa57c29..d0a0aa7f038c 100644 --- a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java +++ b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java @@ -210,7 +210,7 @@ public class PackageUtil { } if (psiDirectory == null) { - if (!checkSourceRootsConfigured(module)) return null; + if (!checkSourceRootsConfigured(module, askUserToCreate)) return null; final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); List<PsiDirectory> directoryList = new ArrayList<PsiDirectory>(); for (VirtualFile sourceRoot : sourceRoots) { @@ -355,15 +355,22 @@ public class PackageUtil { } public static boolean checkSourceRootsConfigured(final Module module) { + return checkSourceRootsConfigured(module, true); + } + + public static boolean checkSourceRootsConfigured(final Module module, final boolean askUserToSetupSourceRoots) { VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); if (sourceRoots.length == 0) { - Messages.showErrorDialog( - module.getProject(), - ProjectBundle.message("module.source.roots.not.configured.error", module.getName()), - ProjectBundle.message("module.source.roots.not.configured.title") - ); + if (!askUserToSetupSourceRoots) { + return false; + } + + Project project = module.getProject(); + Messages.showErrorDialog(project, + ProjectBundle.message("module.source.roots.not.configured.error", module.getName()), + ProjectBundle.message("module.source.roots.not.configured.title")); - ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME); + ProjectSettingsService.getInstance(project).showModuleConfigurationDialog(module.getName(), CommonContentEntriesEditor.NAME); sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(); if (sourceRoots.length == 0) { diff --git a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningDialog.java b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningDialog.java index eb83161cacaa..15c17f6cc639 100644 --- a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningDialog.java +++ b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningDialog.java @@ -20,6 +20,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -55,6 +56,7 @@ class SuperMethodWarningDialog extends DialogWrapper { init(); } + @NotNull protected Action[] createActions(){ return new Action[]{getOKAction(),new NoAction(),getCancelAction()}; } diff --git a/java/java-impl/src/com/intellij/ide/util/TreeJavaClassChooserDialog.java b/java/java-impl/src/com/intellij/ide/util/TreeJavaClassChooserDialog.java index 98fc00ed91ee..994bddb9458c 100644 --- a/java/java-impl/src/com/intellij/ide/util/TreeJavaClassChooserDialog.java +++ b/java/java-impl/src/com/intellij/ide/util/TreeJavaClassChooserDialog.java @@ -60,7 +60,7 @@ public class TreeJavaClassChooserDialog extends AbstractTreeClassChooserDialog<P @Nullable ClassFilter classFilter, PsiClass baseClass, @Nullable PsiClass initialClass, boolean isShowMembers) { - super(title, project, scope, PsiClass.class, createFilter(classFilter), baseClass, initialClass, isShowMembers); + super(title, project, scope, PsiClass.class, createFilter(classFilter), baseClass, initialClass, isShowMembers, true); } @Override diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java index 59449defd59a..5b7c3ef01ad2 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java @@ -260,7 +260,12 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl final Collection<String> sources = new HashSet<String>(); final Runnable findRunnable = new Runnable() { public void run() { - myGenerationOptions.accept(new MyContentIterator(myProject, packages, sources)); + final int scopeType = myGenerationOptions.getScopeType(); + final boolean usePackageNotation = scopeType == AnalysisScope.MODULE || + scopeType == AnalysisScope.MODULES || + scopeType == AnalysisScope.PROJECT || + scopeType == AnalysisScope.DIRECTORY; + myGenerationOptions.accept(new MyContentIterator(myProject, packages, sources, usePackageNotation)); } }; if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(findRunnable, "Search for sources to generate javadoc in...", false, myProject)) { @@ -329,8 +334,10 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl private final PsiManager myPsiManager; private final Collection<String> myPackages; private final Collection<String> mySourceFiles; + private final boolean myUsePackageNotation; - public MyContentIterator(Project project, Collection<String> packages, Collection<String> sources) { + public MyContentIterator(Project project, Collection<String> packages, Collection<String> sources, boolean canUsePackageNotation) { + myUsePackageNotation = canUsePackageNotation; myPsiManager = PsiManager.getInstance(project); myPackages = packages; mySourceFiles = sources; @@ -345,7 +352,7 @@ public class JavadocConfiguration implements ModuleRunProfile, JDOMExternalizabl if (file instanceof PsiJavaFile) { final PsiJavaFile javaFile = (PsiJavaFile)file; final String packageName = javaFile.getPackageName(); - if (containsPackagePrefix(module, packageName) || (packageName.length() == 0 && !(javaFile instanceof JspFile))) { + if (containsPackagePrefix(module, packageName) || (packageName.length() == 0 && !(javaFile instanceof JspFile)) || !myUsePackageNotation) { mySourceFiles.add(FileUtil.toSystemIndependentName(fileOrDir.getPath())); } else { diff --git a/java/java-impl/src/com/intellij/openapi/module/BasePackageParameterFactory.java b/java/java-impl/src/com/intellij/openapi/module/BasePackageParameterFactory.java index e2f3308f7ef2..809f65d80d7d 100644 --- a/java/java-impl/src/com/intellij/openapi/module/BasePackageParameterFactory.java +++ b/java/java-impl/src/com/intellij/openapi/module/BasePackageParameterFactory.java @@ -60,7 +60,7 @@ public class BasePackageParameterFactory extends ProjectTemplateParameterFactory @Override public String getLabel() { - return "Base package:"; + return "Base \u001Bpackage:"; } @Override diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java new file mode 100644 index 000000000000..8e8ca8b6381e --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2013 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.openapi.projectRoots; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.process.ProcessOutput; +import com.intellij.execution.util.ExecUtil; +import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileChooser.FileSystemTree; +import com.intellij.openapi.fileChooser.actions.FileChooserAction; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.InputEvent; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +/** + * User: Vassiliy.Kudryashov + */ +public class JdkPopupAction extends AnAction { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileChooser.actions.JDKPopupAction"); + + public JdkPopupAction() { + super("Show Quick list", "", AllIcons.General.AddJdk); + } + + @Override + public void update(AnActionEvent e) { + boolean enabled = isEnabledInCurrentOS(); + if (enabled) { + FileSystemTree tree = FileSystemTree.DATA_KEY.getData(e.getDataContext()); + if (tree == null || Boolean.TRUE != tree.getData(JavaSdkImpl.KEY)) { + enabled = false; + } + } + e.getPresentation().setEnabled(enabled); + e.getPresentation().setVisible(enabled); + } + + @Override + public void actionPerformed(final AnActionEvent e) { + final JComponent component; + final boolean showInMiddle; + InputEvent inputEvent = e.getInputEvent(); + Object source = inputEvent != null ? inputEvent.getSource() : null; + if (source instanceof JComponent) { + component = (JComponent)source; + showInMiddle = false; + } + else { + Component c = e.getData(PlatformDataKeys.CONTEXT_COMPONENT); + component = c instanceof JComponent? (JComponent)c : null; + showInMiddle = true; + } + + if (!isEnabledInCurrentOS() || component == null) return; + + ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { + + @Override + public void run() { + final ArrayList<Pair<File, String>> jdkLocations = retrieveJDKLocations(); + + if (jdkLocations.isEmpty()) { + return; + } + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + showPopupMenu(e, jdkLocations, showInMiddle, component); + } + }); + } + }, "Looking for JDK locations...", false, e.getProject(), component); + } + + private static boolean isEnabledInCurrentOS() { + return SystemInfo.isWindows; + } + + private static void showPopupMenu(AnActionEvent e, + final ArrayList<Pair<File, String>> jdkLocations, + boolean showInMiddle, + JComponent component) { + ActionPopupMenu menu = + ActionManager.getInstance().createActionPopupMenu(e.getPlace(), new ActionGroup() { + @NotNull + @Override + public AnAction[] getChildren(@Nullable AnActionEvent e) { + List<AnAction> result = new ArrayList<AnAction>(); + for (final Pair<File, String> homes : jdkLocations) { + result.add(new FileChooserAction("", null, null) { + @Override + protected void update(FileSystemTree fileChooser, AnActionEvent e) { + e.getPresentation().setText(homes.getSecond(), false); + boolean selected = false; + VirtualFile selectedFile = fileChooser.getSelectedFile(); + if (selectedFile != null) { + selected = homes.getFirst().getAbsolutePath().equals(VfsUtilCore.virtualToIoFile(selectedFile).getAbsolutePath()); + } + e.getPresentation().setIcon(selected ? AllIcons.Diff.CurrentLine : null); + } + + @Override + protected void actionPerformed(FileSystemTree fileChooser, AnActionEvent e) { + fileChooser.select(VfsUtil.findFileByIoFile(homes.getFirst(), true), null); + } + }); + } + return result.toArray(new AnAction[result.size()]); + } + }); + JPopupMenu menuComponent = menu.getComponent(); + if (showInMiddle) { + menuComponent + .show(component, (component.getWidth() - menuComponent.getWidth()) / 2, + (component.getHeight() - menuComponent.getHeight()) / 2); + } + else { + menuComponent.show(component, 0, component.getHeight()); + } + } + + private static ArrayList<Pair<File, String>> retrieveJDKLocations() { + ArrayList<Pair<File, String>> jdkLocations = new ArrayList<Pair<File, String>>(); + Collection<String> homePaths = JavaSdk.getInstance().suggestHomePaths(); + for (final String path : homePaths) { + try { + File file = new File(path); + File javaExe = new File(new File(file, "bin"), "java.exe"); + ProcessOutput output = ExecUtil.execAndGetOutput(Arrays.asList(javaExe.getAbsolutePath(), "-version"), null); + List<String> lines = output.getStderrLines(); + if (lines.isEmpty()) { + lines = output.getStdoutLines(); + } + StringBuilder stringBuilder = new StringBuilder(); + if (lines.size() == 3) { + stringBuilder.append("JDK "); + String line = lines.get(1); + int pos = line.indexOf("(build "); + if (pos != -1) { + stringBuilder.append(line.substring(pos + 7, line.length() - 1)); + } + line = lines.get(2); + pos = line.indexOf(" (build"); + if (pos != -1) { + String substring = line.substring(0, pos); + stringBuilder.append(" (").append(substring).append(")"); + } + } + else { + stringBuilder.append(file.getName()); + } + jdkLocations.add(Pair.create(file, stringBuilder.toString())); + } + catch (ExecutionException e) { + LOG.debug(e); + } + } + return jdkLocations; + } +} diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index ae5381090152..41102853ca8a 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -17,8 +17,10 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.execution.util.ExecUtil; import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.DataKey; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.*; import com.intellij.openapi.roots.AnnotationOrderRootType; @@ -27,6 +29,7 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.*; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import org.jdom.Element; @@ -37,6 +40,7 @@ import org.jetbrains.jps.model.java.impl.JavaSdkUtil; import javax.swing.*; import java.io.File; +import java.io.FileFilter; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -53,6 +57,7 @@ public class JavaSdkImpl extends JavaSdk { @NonNls private static final String JAVA_VERSION_PREFIX = "java version "; @NonNls private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; private static final Map<JavaSdkVersion, String[]> VERSION_STRINGS = new EnumMap<JavaSdkVersion, String[]>(JavaSdkVersion.class); + public static final DataKey<Boolean> KEY = DataKey.create("JavaSdk"); static { VERSION_STRINGS.put(JavaSdkVersion.JDK_1_0, new String[]{"1.0"}); @@ -180,9 +185,78 @@ public class JavaSdkImpl extends JavaSdk { return "/usr/jdk"; } + if (SystemInfo.isWindows) { + String property = System.getProperty("java.home"); + if (property == null) return null; + File javaHome = new File(property).getParentFile();//actually java.home points to to jre home + if (javaHome != null && JdkUtil.checkForJdk(javaHome)) { + return javaHome.getAbsolutePath(); + } + } return null; } + @NotNull + @Override + public Collection<String> suggestHomePaths() { + if (!SystemInfo.isWindows) + return Collections.singletonList(suggestHomePath()); + + String property = System.getProperty("java.home"); + if (property == null) + return Collections.emptyList(); + + File javaHome = new File(property).getParentFile();//actually java.home points to to jre home + if (javaHome == null || !javaHome.isDirectory() || javaHome.getParentFile() == null) { + return Collections.emptyList(); + } + ArrayList<String> result = new ArrayList<String>(); + File javasFolder = javaHome.getParentFile(); + scanFolder(javasFolder, result); + File parentFile = javasFolder.getParentFile(); + File root = parentFile != null ? parentFile.getParentFile() : null; + String name = parentFile != null ? parentFile.getName() : ""; + if (name.contains("Program Files") && root != null) { + String x86Suffix = " (x86)"; + boolean x86 = name.endsWith(x86Suffix) && name.length() > x86Suffix.length(); + File anotherJavasFolder; + if (x86) { + anotherJavasFolder = new File(root, name.substring(0, name.length() - x86Suffix.length())); + } + else { + anotherJavasFolder = new File(root, name + x86Suffix); + } + if (anotherJavasFolder.isDirectory()) { + scanFolder(new File(anotherJavasFolder, javasFolder.getName()), result); + } + } + return result; + } + + private static void scanFolder(File javasFolder, ArrayList<String> result) { + File[] candidates = javasFolder.listFiles(new FileFilter() { + @Override + public boolean accept(File pathname) { + return JdkUtil.checkForJdk(pathname); + } + }); + if (candidates != null) { + result.addAll(ContainerUtil.map2List(candidates, new Function<File, String>() { + @Override + public String fun(File file) { + return file.getAbsolutePath(); + } + })); + } + } + + @Override + public FileChooserDescriptor getHomeChooserDescriptor() { + FileChooserDescriptor descriptor = super.getHomeChooserDescriptor(); + descriptor.putUserData(KEY, Boolean.TRUE); + return descriptor; + } + @NonNls public static final String MAC_HOME_PATH = "/Home"; @Override diff --git a/java/java-impl/src/com/intellij/psi/AbstractQualifiedReference.java b/java/java-impl/src/com/intellij/psi/AbstractQualifiedReference.java index 43a05188a6d2..58537918cd49 100644 --- a/java/java-impl/src/com/intellij/psi/AbstractQualifiedReference.java +++ b/java/java-impl/src/com/intellij/psi/AbstractQualifiedReference.java @@ -68,7 +68,8 @@ public abstract class AbstractQualifiedReference<T extends AbstractQualifiedRefe @Override @NotNull public final ResolveResult[] multiResolve(final boolean incompleteCode) { - return ResolveCache.getInstance(getProject()).resolveWithCaching(this, MY_RESOLVER, true, false); + PsiFile file = getContainingFile(); + return ResolveCache.getInstance(file.getProject()).resolveWithCaching(this, MY_RESOLVER, true, false,file); } @Override diff --git a/java/java-impl/src/com/intellij/psi/filters/types/AssignableFromFilter.java b/java/java-impl/src/com/intellij/psi/filters/types/AssignableFromFilter.java index 72cd4d29d0ef..b2f7611ff673 100644 --- a/java/java-impl/src/com/intellij/psi/filters/types/AssignableFromFilter.java +++ b/java/java-impl/src/com/intellij/psi/filters/types/AssignableFromFilter.java @@ -53,9 +53,10 @@ public class AssignableFromFilter implements ElementFilter{ public boolean isAcceptable(Object element, PsiElement context){ PsiType type = myType; if(type == null) { - final PsiClass aClass = JavaPsiFacade.getInstance(context.getProject()).findClass(myClassName, context.getResolveScope()); + JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(context.getProject()); + final PsiClass aClass = psiFacade.findClass(myClassName, context.getResolveScope()); if (aClass != null) { - type = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass, PsiSubstitutor.EMPTY); + type = psiFacade.getElementFactory().createType(aClass, PsiSubstitutor.EMPTY); } else { type = null; diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java index 8b30b996bfe2..0e98a3873bb8 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java @@ -187,15 +187,20 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper MemberOrderService service = ServiceManager.getService(MemberOrderService.class); PsiElement anchor = service.getAnchor(member, settings.getCommonSettings(JavaLanguage.INSTANCE), aClass); - if (anchor != null && PsiTreeUtil.skipSiblingsForward(anchor, PsiWhiteSpace.class) == aClass.getRBrace()) { - // Given member should be inserted as the last child. - return aClass.getRBrace(); + PsiElement newAnchor = skipWhitespaces(aClass, anchor); + if (newAnchor != null) { + return newAnchor; } - + if (anchor != null && anchor != aClass) { anchor = anchor.getNextSibling(); while (anchor instanceof PsiJavaToken && (anchor.getText().equals(",") || anchor.getText().equals(";"))) { + final boolean afterComma = anchor.getText().equals(","); anchor = anchor.getNextSibling(); + if (afterComma) { + newAnchor = skipWhitespaces(aClass, anchor); + if (newAnchor != null) return newAnchor; + } } if (anchor != null) { return anchor; @@ -215,7 +220,15 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper return aClass.getRBrace(); } - + + private static PsiElement skipWhitespaces(PsiClass aClass, PsiElement anchor) { + if (anchor != null && PsiTreeUtil.skipSiblingsForward(anchor, PsiWhiteSpace.class) == aClass.getRBrace()) { + // Given member should be inserted as the last child. + return aClass.getRBrace(); + } + return null; + } + // TODO remove as soon as an arrangement sub-system is provided for groovy. public static int getMemberOrderWeight(PsiElement member, CodeStyleSettings settings) { if (member instanceof PsiField) { diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java b/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java index 6d05e6aff9dd..21a03d7e2bc3 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaRegExpHost.java @@ -16,18 +16,28 @@ package com.intellij.psi.impl; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.projectRoots.JavaSdk; import com.intellij.openapi.projectRoots.JavaSdkVersion; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; +import org.intellij.lang.regexp.DefaultRegExpPropertiesProvider; import org.intellij.lang.regexp.RegExpLanguageHost; import org.intellij.lang.regexp.psi.RegExpGroup; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author yole */ public class JavaRegExpHost implements RegExpLanguageHost { + + private final DefaultRegExpPropertiesProvider myPropertiesProvider; + + public JavaRegExpHost() { + myPropertiesProvider = DefaultRegExpPropertiesProvider.getInstance(); + } + @Override public boolean characterNeedsEscaping(char c) { return c == ']' || c == '}'; @@ -51,7 +61,7 @@ public class JavaRegExpHost implements RegExpLanguageHost { @Override public boolean supportsNamedGroupSyntax(RegExpGroup group) { if (group.isRubyNamedGroup()) { - final Module module = ModuleUtil.findModuleForPsiElement(group); + final Module module = ModuleUtilCore.findModuleForPsiElement(group); if (module != null) { final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { @@ -62,4 +72,27 @@ public class JavaRegExpHost implements RegExpLanguageHost { } return false; } + + @Override + public boolean isValidCategory(@NotNull String category) { + return myPropertiesProvider.isValidCategory(category); + } + + @NotNull + @Override + public String[][] getAllKnownProperties() { + return myPropertiesProvider.getAllKnownProperties(); + } + + @Nullable + @Override + public String getPropertyDescription(@Nullable String name) { + return myPropertiesProvider.getPropertyDescription(name); + } + + @NotNull + @Override + public String[][] getKnownCharacterClasses() { + return myPropertiesProvider.getKnownCharacterClasses(); + } } diff --git a/java/java-impl/src/com/intellij/psi/impl/search/AnnotatedPackagesSearcher.java b/java/java-impl/src/com/intellij/psi/impl/search/AnnotatedPackagesSearcher.java index 397c85cc9642..ff7684e21edc 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/AnnotatedPackagesSearcher.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/AnnotatedPackagesSearcher.java @@ -55,7 +55,7 @@ public class AnnotatedPackagesSearcher implements QueryExecutor<PsiPackage, Anno final GlobalSearchScope scope = useScope instanceof GlobalSearchScope ? (GlobalSearchScope)useScope : null; - final Collection<PsiAnnotation> annotations = JavaAnnotationIndex.getInstance().get(annotationShortName, annClass.getProject(), scope); + final Collection<PsiAnnotation> annotations = JavaAnnotationIndex.getInstance().get(annotationShortName, psiManager.getProject(), scope); for (PsiAnnotation annotation : annotations) { PsiModifierList modlist = (PsiModifierList)annotation.getParent(); final PsiElement owner = modlist.getParent(); diff --git a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java index b54a18f42467..1594b3b3674e 100644 --- a/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java +++ b/java/java-impl/src/com/intellij/psi/impl/smartPointers/AnchorElementInfo.java @@ -58,7 +58,7 @@ class AnchorElementInfo extends SelfElementInfo { if (stubId != -1) { PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject); if (!(file instanceof PsiFileWithStubSupport)) return null; - return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType); + return PsiAnchor.restoreFromStubIndex((PsiFileWithStubSupport)file, stubId, myStubElementType, false); } if (!mySyncMarkerIsValid) return null; PsiFile file = SelfElementInfo.restoreFileFromVirtual(getVirtualFile(), myProject); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java index ae1e9773bc8c..15716567cab7 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java @@ -78,28 +78,54 @@ public class ImportHelper{ } }); - int[] entryForName = ArrayUtil.newIntArray(names.size()); - PackageEntry[] entries = mySettings.IMPORT_LAYOUT_TABLE.getEntries(); - for(int i = 0; i < names.size(); i++){ - Pair<String, Boolean> pair = names.get(i); - String packageName = pair.getFirst(); - Boolean isStatic = pair.getSecond(); - entryForName[i] = findEntryIndex(packageName, isStatic, entries); - } + List<Pair<String, Boolean>> resultList = sortItemsAccordingToSettings(names, mySettings); - List<Pair<String, Boolean>> resultList = new ArrayList<Pair<String, Boolean>>(names.size()); - for(int i = 0; i < entries.length; i++){ - for(int j = 0; j < names.size(); j++){ - if (entryForName[j] == i){ - resultList.add(names.get(j)); - names.set(j, null); + final Set<String> classesOrPackagesToImportOnDemand = new THashSet<String>(); + collectOnDemandImports(resultList, classesOrPackagesToImportOnDemand, ImportHelper.this.mySettings); + + Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand); + Set<String> toReimport = new THashSet<String>(); + calcClassesConflictingViaOnDemandImports(file, classesOrPackagesToImportOnDemand, file.getResolveScope(), toReimport); + classesToUseSingle.addAll(toReimport); + + try { + StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle); + for (PsiElement nonImport : nonImports) { + text.append("\n").append(nonImport.getText()); + } + String ext = StdFileTypes.JAVA.getDefaultExtension(); + PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); + final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject()); + codeStyleManager.reformat(dummyFile); + + PsiImportList newImportList = dummyFile.getImportList(); + PsiImportList result = (PsiImportList)newImportList.copy(); + PsiImportList oldList = file.getImportList(); + if (oldList.isReplaceEquivalent(result)) return null; + if (!nonImports.isEmpty()) { + PsiElement firstPrevious = newImportList.getPrevSibling(); + while (firstPrevious != null && firstPrevious.getPrevSibling() != null) { + firstPrevious = firstPrevious.getPrevSibling(); + } + for (PsiElement element = firstPrevious; element != null && element != newImportList; element = element.getNextSibling()) { + result.add(element.copy()); + } + for (PsiElement element = newImportList.getNextSibling(); element != null; element = element.getNextSibling()) { + result.add(element.copy()); } } + return result; } - for (Pair<String, Boolean> name : names) { - if (name != null) resultList.add(name); + catch(IncorrectOperationException e) { + LOG.error(e); + return null; } + } + public static void collectOnDemandImports(List<Pair<String, Boolean>> resultList, + final Set<String> classesOrPackagesToImportOnDemand, + final CodeStyleSettings settings) { TObjectIntHashMap<String> packageToCountMap = new TObjectIntHashMap<String>(); TObjectIntHashMap<String> classToCountMap = new TObjectIntHashMap<String>(); for (Pair<String, Boolean> pair : resultList) { @@ -117,7 +143,7 @@ public class ImportHelper{ } } - final Set<String> classesOrPackagesToImportOnDemand = new THashSet<String>(); + class MyVisitorProcedure implements TObjectIntProcedure<String> { private final boolean myIsVisitingPackages; @@ -127,7 +153,7 @@ public class ImportHelper{ @Override public boolean execute(final String packageOrClassName, final int count) { - if (isToUseImportOnDemand(packageOrClassName, count, !myIsVisitingPackages)){ + if (isToUseImportOnDemand(packageOrClassName, count, !myIsVisitingPackages, settings)){ classesOrPackagesToImportOnDemand.add(packageOrClassName); } return true; @@ -135,45 +161,31 @@ public class ImportHelper{ } classToCountMap.forEachEntry(new MyVisitorProcedure(false)); packageToCountMap.forEachEntry(new MyVisitorProcedure(true)); + } - Set<String> classesToUseSingle = findSingleImports(file, resultList, classesOrPackagesToImportOnDemand); - Set<String> toReimport = new THashSet<String>(); - calcClassesConflictingViaOnDemandImports(file, classesOrPackagesToImportOnDemand, file.getResolveScope(), toReimport); - classesToUseSingle.addAll(toReimport); - - try { - StringBuilder text = buildImportListText(resultList, classesOrPackagesToImportOnDemand, classesToUseSingle); - for (PsiElement nonImport : nonImports) { - text.append("\n").append(nonImport.getText()); - } - String ext = StdFileTypes.JAVA.getDefaultExtension(); - PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); - final PsiJavaFile dummyFile = (PsiJavaFile)factory.createFileFromText("_Dummy_." + ext, StdFileTypes.JAVA, text); - CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(file.getProject()); - codeStyleManager.reformat(dummyFile); + public static List<Pair<String, Boolean>> sortItemsAccordingToSettings(List<Pair<String, Boolean>> names, final CodeStyleSettings settings) { + int[] entryForName = ArrayUtil.newIntArray(names.size()); + PackageEntry[] entries = settings.IMPORT_LAYOUT_TABLE.getEntries(); + for(int i = 0; i < names.size(); i++){ + Pair<String, Boolean> pair = names.get(i); + String packageName = pair.getFirst(); + Boolean isStatic = pair.getSecond(); + entryForName[i] = findEntryIndex(packageName, isStatic, entries); + } - PsiImportList newImportList = dummyFile.getImportList(); - PsiImportList result = (PsiImportList)newImportList.copy(); - PsiImportList oldList = file.getImportList(); - if (oldList.isReplaceEquivalent(result)) return null; - if (!nonImports.isEmpty()) { - PsiElement firstPrevious = newImportList.getPrevSibling(); - while (firstPrevious != null && firstPrevious.getPrevSibling() != null) { - firstPrevious = firstPrevious.getPrevSibling(); - } - for (PsiElement element = firstPrevious; element != null && element != newImportList; element = element.getNextSibling()) { - result.add(element.copy()); - } - for (PsiElement element = newImportList.getNextSibling(); element != null; element = element.getNextSibling()) { - result.add(element.copy()); + List<Pair<String, Boolean>> resultList = new ArrayList<Pair<String, Boolean>>(names.size()); + for(int i = 0; i < entries.length; i++){ + for(int j = 0; j < names.size(); j++){ + if (entryForName[j] == i){ + resultList.add(names.get(j)); + names.set(j, null); } } - return result; } - catch(IncorrectOperationException e) { - LOG.error(e); - return null; + for (Pair<String, Boolean> name : names) { + if (name != null) resultList.add(name); } + return resultList; } @NotNull @@ -620,13 +632,16 @@ public class ImportHelper{ return maxSpace; } - private boolean isToUseImportOnDemand(@NotNull String packageName, int classCount, boolean isStaticImportNeeded){ - if (!mySettings.USE_SINGLE_CLASS_IMPORTS) return true; - int limitCount = isStaticImportNeeded ? mySettings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND : - mySettings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND; + private static boolean isToUseImportOnDemand(@NotNull String packageName, + int classCount, + boolean isStaticImportNeeded, + final CodeStyleSettings settings){ + if (!settings.USE_SINGLE_CLASS_IMPORTS) return true; + int limitCount = isStaticImportNeeded ? settings.NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND : + settings.CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND; if (classCount >= limitCount) return true; if (packageName.length() == 0) return false; - PackageEntryTable table = mySettings.PACKAGES_TO_USE_IMPORT_ON_DEMAND; + PackageEntryTable table = settings.PACKAGES_TO_USE_IMPORT_ON_DEMAND; return table != null && table.contains(packageName); } diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java index 04dd71c7970d..f1072ea571d7 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java @@ -31,6 +31,7 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; @@ -341,8 +342,9 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer @Override @NotNull public JavaResolveResult advancedResolve(boolean incompleteCode) { - final ResolveCache resolveCache = ResolveCache.getInstance(getElement().getProject()); - return (JavaResolveResult) resolveCache.resolveWithCaching(this, MyResolver.INSTANCE, false, false)[0]; + PsiFile file = getElement().getContainingFile(); + final ResolveCache resolveCache = ResolveCache.getInstance(file.getProject()); + return (JavaResolveResult) resolveCache.resolveWithCaching(this, MyResolver.INSTANCE, false, false,file)[0]; } private JavaResolveResult doAdvancedResolve() { @@ -411,7 +413,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer if (containingFile == null) return JavaResolveResult.EMPTY; } - final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement); + final ClassResolverProcessor processor = new ClassResolverProcessor(getCanonicalText(), psiElement, containingFile); containingFile.processDeclarations(processor, ResolveState.initial(), null, psiElement); if (processor.getResult().length == 1) { @@ -439,13 +441,14 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer } private GlobalSearchScope getScope() { - final GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(getElement().getProject()); + Project project = getElement().getProject(); + GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(project); if (scope == null) { final Module module = ModuleUtilCore.findModuleForPsiElement(getElement()); if (module != null) { return module.getModuleWithDependenciesAndLibrariesScope(true); } - return GlobalSearchScope.allScope(getElement().getProject()); + return GlobalSearchScope.allScope(project); } return scope; } @@ -583,6 +586,7 @@ public class JavaClassReference extends GenericReference implements PsiJavaRefer return myJavaClassReferenceSet; } + @NotNull @Override public String getUnresolvedMessagePattern() { return myJavaClassReferenceSet.getUnresolvedMessagePattern(myIndex); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java index 94827c3a03f5..537b3216df4d 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/PsiPackageReference.java @@ -60,6 +60,7 @@ public class PsiPackageReference extends PsiPolyVariantReferenceBase<PsiElement> return subPackages.toArray(); } + @NotNull @Override public String getUnresolvedMessagePattern() { return JavaErrorMessages.message("cannot.resolve.package"); diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java index 94285b366fea..2876f7611a15 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java @@ -68,6 +68,9 @@ public class MyTestInjector { registerForStringVarInitializer(parent, project, js, "js", null, null); registerForStringVarInitializer(parent, project, js, "jsSeparated", " + ", " + 'separator'"); registerForStringVarInitializer(parent, project, js, "jsBrokenPrefix", "xx ", ""); + + registerForStringVarInitializer(parent, project, Language.findLanguageByID("Oracle"), "oracle", null, null); + registerForParameterValue(parent, project, Language.findLanguageByID("Groovy"), "groovy"); } diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java index 5a8a050ea450..3f6d15814df7 100644 --- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java @@ -35,6 +35,7 @@ import com.intellij.ui.NonFocusableCheckBox; import com.intellij.util.Function; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.FormBuilder; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -105,6 +106,7 @@ class AnonymousToInnerDialog extends DialogWrapper{ myNameField.selectNameWithoutExtension(); } + @NotNull protected Action[] createActions(){ return new Action[]{getOKAction(),getCancelAction(),getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java index 1465aa097d49..b8d1f1770cd6 100644 --- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassDialog.java @@ -37,6 +37,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -84,6 +85,7 @@ class CopyClassDialog extends DialogWrapper{ myNameField.selectAll(); } + @NotNull protected Action[] createActions(){ return new Action[]{getOKAction(),getCancelAction(),getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java index 35e7ffafbfb9..5e64113cfda7 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodDialog.java @@ -41,6 +41,7 @@ import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -142,6 +143,7 @@ public class ExtractMethodDialog extends AbstractExtractDialog { return myCbChainedConstructor != null && myCbChainedConstructor.isSelected(); } + @NotNull protected Action[] createActions() { if (myHelpId != null) { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java index 92f992e7914a..b5a9099c8c14 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractMethodObjectDialog.java @@ -33,6 +33,7 @@ import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -126,6 +127,7 @@ public class ExtractMethodObjectDialog extends AbstractExtractDialog { return false; } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java index 3a1347715e06..fa216113b276 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java @@ -44,7 +44,6 @@ import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.WindowManager; import com.intellij.psi.*; @@ -446,9 +445,15 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase } } + protected abstract boolean accept(ElementToWorkOn elementToWorkOn); + + protected ElementToWorkOn.ElementsProcessor<ElementToWorkOn> getElementProcessor(final Project project, final Editor editor) { + return new ElementToWorkOn.ElementsProcessor<ElementToWorkOn>() { + @Override + public boolean accept(ElementToWorkOn el) { + return BaseExpressionToFieldHandler.this.accept(el); + } - protected Pass<ElementToWorkOn> getElementProcessor(final Project project, final Editor editor) { - return new Pass<ElementToWorkOn>() { @Override public void pass(final ElementToWorkOn elementToWorkOn) { if (elementToWorkOn == null) return; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/ElementToWorkOn.java b/java/java-impl/src/com/intellij/refactoring/introduceField/ElementToWorkOn.java index 3dab04d34b94..93e19e3581bc 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/ElementToWorkOn.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/ElementToWorkOn.java @@ -29,6 +29,7 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.introduceVariable.IntroduceVariableBase; import com.intellij.refactoring.util.CommonRefactoringUtil; +import java.util.Iterator; import java.util.List; /** @@ -60,7 +61,7 @@ public class ElementToWorkOn { return myExpression == null; } - public static void processElementToWorkOn(final Editor editor, final PsiFile file, final String refactoringName, final String helpId, final Project project, final Pass<ElementToWorkOn> processor) { + public static void processElementToWorkOn(final Editor editor, final PsiFile file, final String refactoringName, final String helpId, final Project project, final ElementsProcessor<ElementToWorkOn> processor) { PsiLocalVariable localVar = null; PsiExpression expr = null; @@ -92,13 +93,20 @@ public class ElementToWorkOn { if (statementsInRange.length == 1 && (PsiUtilCore.hasErrorElementChild(statementsInRange[0]) || !PsiUtil.isStatement(statementsInRange[0]))) { editor.getSelectionModel().selectLineAtCaret(); final ElementToWorkOn elementToWorkOn = getElementToWorkOn(editor, file, refactoringName, helpId, project, localVar, expr); - if (elementToWorkOn == null || elementToWorkOn.getLocalVariable() == null && elementToWorkOn.getExpression() == null) { + if (elementToWorkOn == null || elementToWorkOn.getLocalVariable() == null && elementToWorkOn.getExpression() == null || !processor.accept(elementToWorkOn)) { editor.getSelectionModel().removeSelection(); } } if (!editor.getSelectionModel().hasSelection()){ final List<PsiExpression> expressions = IntroduceVariableBase.collectExpressions(file, editor, offset, statementsInRange); + for (Iterator<PsiExpression> iterator = expressions.iterator(); iterator.hasNext(); ) { + PsiExpression expression = iterator.next(); + if (!processor.accept(new ElementToWorkOn(null, expression))) { + iterator.remove(); + } + } + if (expressions.isEmpty()) { editor.getSelectionModel().selectLineAtCaret(); } @@ -177,4 +185,9 @@ public class ElementToWorkOn { } return new ElementToWorkOn(localVar, expr); } + + public interface ElementsProcessor<T> { + boolean accept(ElementToWorkOn el); + void pass(T t); + } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java index ca2009d89145..553610f7e0fa 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java @@ -55,6 +55,7 @@ import com.intellij.util.IncorrectOperationException; import com.intellij.util.ui.UIUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -163,6 +164,7 @@ class IntroduceConstantDialog extends DialogWrapper { return myTypeSelector.getSelectedType(); } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java index 31734bdb32e0..103777895cbc 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantHandler.java @@ -296,6 +296,17 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler { return null; } + @Override + protected boolean accept(ElementToWorkOn elementToWorkOn) { + final PsiExpression expr = elementToWorkOn.getExpression(); + if (expr != null) { + return isStaticFinalInitializer(expr) == null; + } + final PsiLocalVariable localVariable = elementToWorkOn.getLocalVariable(); + final PsiExpression initializer = localVariable.getInitializer(); + return initializer != null && isStaticFinalInitializer(initializer) == null; + } + protected boolean validClass(PsiClass parentClass, Editor editor) { return true; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java index 0aaad5f3608f..27ad6be98620 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java @@ -32,6 +32,7 @@ import com.intellij.refactoring.ui.*; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.RefactoringMessageUtil; import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -125,6 +126,7 @@ class IntroduceFieldDialog extends DialogWrapper { } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java index c16fc9fbcdd8..a4338d463cc3 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldHandler.java @@ -157,6 +157,11 @@ public class IntroduceFieldHandler extends BaseExpressionToFieldHandler { dialog.getFieldType(), localVariable != null, (TargetDestination)null, false, false); } + @Override + protected boolean accept(ElementToWorkOn elementToWorkOn) { + return true; + } + private static PsiElement getElement(PsiExpression expr, PsiElement anchorElement) { PsiElement element = null; if (expr != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java index e8518f3d6300..346b1571f690 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/EnclosingMethodSelectionDialog.java @@ -32,6 +32,7 @@ import com.intellij.refactoring.ui.MethodCellRenderer; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBList; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -62,6 +63,7 @@ public class EnclosingMethodSelectionDialog extends DialogWrapper { } } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction()/*, getHelpAction()*/}; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java index eaa5afffb0c4..52d9e3902bf0 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java @@ -40,7 +40,6 @@ import com.intellij.openapi.ui.popup.JBPopupAdapter; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.psi.*; @@ -90,7 +89,12 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase { public void invoke(@NotNull final Project project, final Editor editor, PsiFile file, DataContext dataContext) { PsiDocumentManager.getInstance(project).commitAllDocuments(); editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - ElementToWorkOn.processElementToWorkOn(editor, file, REFACTORING_NAME, HelpID.INTRODUCE_PARAMETER, project, new Pass<ElementToWorkOn>() { + ElementToWorkOn.processElementToWorkOn(editor, file, REFACTORING_NAME, HelpID.INTRODUCE_PARAMETER, project, new ElementToWorkOn.ElementsProcessor<ElementToWorkOn>() { + @Override + public boolean accept(ElementToWorkOn el) { + return true; + } + @Override public void pass(final ElementToWorkOn elementToWorkOn) { if (elementToWorkOn == null) return; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java index 74782d91cb3c..99b2d6a096a1 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java @@ -29,6 +29,7 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.ui.*; import com.intellij.ui.NonFocusableCheckBox; import com.intellij.ui.StateRestoringCheckBox; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -82,6 +83,7 @@ class IntroduceVariableDialog extends DialogWrapper implements IntroduceVariable super.dispose(); } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java index ce3dd18283f7..8d36bf6bef90 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java @@ -21,6 +21,9 @@ import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.statistics.StatisticsInfo; import com.intellij.psi.statistics.StatisticsManager; +import com.intellij.psi.util.MethodSignature; +import com.intellij.psi.util.MethodSignatureUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.JavaRefactoringSettings; import com.intellij.refactoring.RefactoringBundle; @@ -253,6 +256,12 @@ public class PullUpDialog extends RefactoringDialog { return ((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC); } if (element instanceof PsiMethod) { + if (currentSuperClass.isInterface()) { + final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(currentSuperClass, myClass, PsiSubstitutor.EMPTY); + final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor); + final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false); + if (superClassMethod != null) return false; + } return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC); } return true; diff --git a/java/java-impl/src/com/intellij/refactoring/migration/MigrationDialog.java b/java/java-impl/src/com/intellij/refactoring/migration/MigrationDialog.java index 6bc6c77dcf27..ac3891bb0b1d 100644 --- a/java/java-impl/src/com/intellij/refactoring/migration/MigrationDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/migration/MigrationDialog.java @@ -23,6 +23,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.RefactoringBundle; import com.intellij.ui.ScrollPaneFactory; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; @@ -56,6 +57,7 @@ public class MigrationDialog extends DialogWrapper{ init(); } + @NotNull protected Action[] createActions(){ return new Action[]{getOKAction(),getCancelAction(),getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java index 66dc0e301bc1..a05b1dbd69e0 100644 --- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java +++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithBuilder/ParameterData.java @@ -21,6 +21,7 @@ package com.intellij.refactoring.replaceConstructorWithBuilder; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; @@ -30,7 +31,6 @@ import com.intellij.refactoring.util.RefactoringUtil; import java.util.Map; public class ParameterData { - private final String myName; private final String myParameterName; private final PsiType myType; private String myFieldName; @@ -39,8 +39,7 @@ public class ParameterData { private boolean myInsertSetter = true; private static final Logger LOG = Logger.getInstance("#" + ParameterData.class.getName()); - public ParameterData(String name, String parameterName, PsiType type) { - myName = name; + public ParameterData(String parameterName, PsiType type) { myParameterName = parameterName; myType = type; } @@ -77,14 +76,24 @@ public class ParameterData { final String paramName = parameter.getName(); final String pureParamName = styleManager.variableNameToPropertyName(paramName, VariableKind.PARAMETER); - ParameterData parameterData = result.get(pureParamName); + String uniqueParamName = pureParamName; + ParameterData parameterData = result.get(uniqueParamName); + int i = 0; + while (parameterData != null) { + if (!Comparing.equal(parameter.getType(), parameterData.getType())) { + uniqueParamName = pureParamName + i++; + parameterData = result.get(uniqueParamName); + } else { + break; + } + } if (parameterData == null) { - parameterData = new ParameterData(pureParamName, paramName, parameter.getType()); + parameterData = new ParameterData(paramName, parameter.getType()); - parameterData.setFieldName(styleManager.suggestVariableName(VariableKind.FIELD, pureParamName, null, parameter.getType()).names[0]); - parameterData.setSetterName(PropertyUtil.suggestSetterName(pureParamName)); + parameterData.setFieldName(styleManager.suggestVariableName(VariableKind.FIELD, uniqueParamName, null, parameter.getType()).names[0]); + parameterData.setSetterName(PropertyUtil.suggestSetterName(uniqueParamName)); - result.put(pureParamName, parameterData); + result.put(uniqueParamName, parameterData); } return parameterData; diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java index 89c7c3b2af8d..4217acec0330 100644 --- a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java @@ -32,6 +32,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usages.impl.UsagePreviewPanel; import com.intellij.util.ui.Table; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.ListSelectionEvent; @@ -93,6 +94,7 @@ class OverridingMethodsDialog extends DialogWrapper { return result; } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction()/*, getHelpAction()*/}; } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/FailedConversionsDialog.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/FailedConversionsDialog.java index d42e32e368b6..02acc41ec8cc 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/FailedConversionsDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/FailedConversionsDialog.java @@ -21,6 +21,7 @@ import com.intellij.refactoring.RefactoringBundle; import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -43,6 +44,7 @@ public class FailedConversionsDialog extends DialogWrapper { init(); } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), new ViewUsagesAction(), new CancelAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/ui/InfoDialog.java b/java/java-impl/src/com/intellij/refactoring/ui/InfoDialog.java index c20ade157515..9cecc2200c88 100644 --- a/java/java-impl/src/com/intellij/refactoring/ui/InfoDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/ui/InfoDialog.java @@ -25,6 +25,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.project.Project; import com.intellij.util.ui.UIUtil; import com.intellij.refactoring.RefactoringBundle; +import org.jetbrains.annotations.NotNull; public class InfoDialog extends DialogWrapper{ private JCheckBox myShowInFutureCheckBox; @@ -42,6 +43,7 @@ public class InfoDialog extends DialogWrapper{ setOKButtonText(RefactoringBundle.message("ok.button")); } + @NotNull protected Action[] createActions(){ return new Action[]{getOKAction()}; } diff --git a/java/java-impl/src/com/intellij/refactoring/ui/YesNoPreviewUsagesDialog.java b/java/java-impl/src/com/intellij/refactoring/ui/YesNoPreviewUsagesDialog.java index 4867f3269eac..7f82cda4a051 100644 --- a/java/java-impl/src/com/intellij/refactoring/ui/YesNoPreviewUsagesDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/ui/YesNoPreviewUsagesDialog.java @@ -26,6 +26,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.MultiLineLabelUI; import com.intellij.openapi.ui.Messages; import com.intellij.refactoring.RefactoringBundle; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -80,6 +81,7 @@ public class YesNoPreviewUsagesDialog extends DialogWrapper { return panel; } + @NotNull protected Action[] createActions() { if(myHelpID != null){ return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; diff --git a/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java b/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java index 31e3fe43a562..eccaa6505f2e 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java +++ b/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -29,7 +29,7 @@ import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiJavaReference; import com.intellij.psi.PsiNamedElement; -import com.intellij.psi.impl.source.tree.SourceUtil; +import com.intellij.psi.impl.source.tree.AstBufferUtil; import com.intellij.util.NullableFunction; import com.intellij.util.PairProcessor; import com.intellij.util.WalkingState; @@ -60,8 +60,8 @@ public class SliceLeafAnalyzer { elementToCompare = resolved; } } - return elementToCompare instanceof PsiNamedElement ? - ((PsiNamedElement)elementToCompare).getName() : SourceUtil.getTextSkipWhiteSpaceAndComments(elementToCompare.getNode()); + return elementToCompare instanceof PsiNamedElement ? ((PsiNamedElement)elementToCompare).getName() + : AstBufferUtil.getTextSkippingWhitespaceComments(elementToCompare.getNode()); } }); return Comparing.hashcode(text); diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java index ac604a13516d..ffecd93366e6 100644 --- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java +++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestDialog.java @@ -257,6 +257,7 @@ public class CreateTestDialog extends DialogWrapper { return getClass().getName(); } + @NotNull protected Action[] createActions() { return new Action[]{getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java index 1572e71f5180..4c51caf02632 100644 --- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java +++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.java @@ -45,6 +45,7 @@ import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -207,6 +208,7 @@ public class UnscrambleDialog extends DialogWrapper { myEditorPanel.add(myStacktraceEditorPanel, BorderLayout.CENTER); } + @NotNull protected Action[] createActions(){ return new Action[]{createNormalizeTextAction(), getOKAction(), getCancelAction(), getHelpAction()}; } diff --git a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java index a5b0cf2698c3..d4f579084216 100644 --- a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java +++ b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java @@ -16,15 +16,10 @@ package com.intellij.util.xml; -import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider; import com.intellij.psi.search.GlobalSearchScope; @@ -38,12 +33,8 @@ import org.jetbrains.annotations.Nullable; public class PsiClassConverter extends Converter<PsiClass> implements CustomReferenceConverter<PsiClass> { public PsiClass fromString(final String s, final ConvertContext context) { - return findClass(s, context); - } - - public static PsiClass findClass(String s, ConvertContext context) { final DomElement element = context.getInvocationElement(); - final GlobalSearchScope scope = element instanceof GenericDomValue ? context.getSearchScope() : null; + final GlobalSearchScope scope = element instanceof GenericDomValue ? getScope(context) : null; return DomJavaUtil.findClass(s, context.getFile(), context.getModule(), scope); } |