diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index 00f2758af93c..ec9ee6136183 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -198,22 +198,28 @@ public class LineBreakpoint extends BreakpointWithHighlighter { final VirtualFile breakpointFile = position.getFile().getVirtualFile(); final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); if (breakpointFile != null && fileIndex.isUnderSourceRootOfType(breakpointFile, JavaModuleSourceRootTypes.SOURCES)) { + if (debugProcess.getSearchScope().contains(breakpointFile)) { + return true; + } // apply filtering to breakpoints from content sources only, not for sources attached to libraries final Collection candidates = findClassCandidatesInSourceContent(className, debugProcess.getSearchScope(), fileIndex); if (LOG.isDebugEnabled()) { LOG.debug("Found "+ (candidates == null? "null" : candidates.size()) + " candidate containing files for class " + className); } if (candidates == null) { + // If no candidates are found in scope then assume that class is loaded dynamically and allow breakpoint return true; } - for (VirtualFile classFile : candidates) { - if (LOG.isDebugEnabled()) { - LOG.debug("Breakpoint file: " + breakpointFile.getPath()+ "; candidate file: " + classFile.getPath()); - } - if (breakpointFile.equals(classFile)) { - return true; - } - } + + // breakpointFile is not in scope here and there are some candidates in scope + //for (VirtualFile classFile : candidates) { + // if (LOG.isDebugEnabled()) { + // LOG.debug("Breakpoint file: " + breakpointFile.getPath()+ "; candidate file: " + classFile.getPath()); + // } + // if (breakpointFile.equals(classFile)) { + // return true; + // } + //} if (LOG.isDebugEnabled()) { final GlobalSearchScope scope = debugProcess.getSearchScope(); final boolean contains = scope.contains(breakpointFile); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java index 5e8fb9d20af6..fc25273899bb 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java @@ -159,10 +159,7 @@ public class HighlightNamesUtil { @Nullable public static HighlightInfo highlightClassNameInQualifier(final PsiJavaCodeReferenceElement element, @NotNull TextAttributesScheme colorsScheme) { - PsiExpression qualifierExpression = null; - if (element instanceof PsiReferenceExpression) { - qualifierExpression = ((PsiReferenceExpression)element).getQualifierExpression(); - } + PsiElement qualifierExpression = element.getQualifier(); if (qualifierExpression instanceof PsiJavaCodeReferenceElement) { PsiElement resolved = ((PsiJavaCodeReferenceElement)qualifierExpression).resolve(); if (resolved instanceof PsiClass) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index a8978279b789..621d49f53edf 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -647,12 +647,12 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh final String refName = ref.getReferenceName(); final JavaResolveResult[] results = ref.multiResolve(false); + final PsiElement referenceNameElement = ref.getReferenceNameElement(); if (results.length == 0) { final String description = JavaErrorMessages.message("cannot.resolve.symbol", refName); - final PsiElement nameElement = ref.getReferenceNameElement(); - assert nameElement != null : ref; + assert referenceNameElement != null : ref; final HighlightInfo info = - HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(nameElement).descriptionAndTooltip(description).create(); + HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(referenceNameElement).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createSetupJDKFix()); myHolder.add(info); } @@ -690,6 +690,22 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } } + if (!myHolder.hasErrorResults()) { + final PsiElement resolved = results.length == 1 ? results[0].getElement() : null; + final TextAttributesScheme colorsScheme = myHolder.getColorsScheme(); + if (resolved instanceof PsiClass) { + myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)resolved, ref, colorsScheme)); + } + else{ + myHolder.add(HighlightNamesUtil.highlightClassNameInQualifier(ref, colorsScheme)); + if (resolved instanceof PsiVariable) { + myHolder.add(HighlightNamesUtil.highlightVariableName((PsiVariable)resolved, referenceNameElement, colorsScheme)); + } + else if (resolved instanceof PsiMethod) { + myHolder.add(HighlightNamesUtil.highlightMethodName((PsiMethod)resolved, referenceNameElement, false, colorsScheme)); + } + } + } } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java b/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java index 826a68e52253..153bafb001f0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/TargetElementUtil.java @@ -215,7 +215,9 @@ public class TargetElementUtil extends TargetElementUtilBase { @Override public Collection getTargetCandidates(final PsiReference reference) { PsiElement parent = reference.getElement().getParent(); - if (parent instanceof PsiCallExpression) { + if (parent instanceof PsiMethodCallExpression || parent instanceof PsiNewExpression && + ((PsiNewExpression)parent).getArrayDimensions().length == 0 && + ((PsiNewExpression)parent).getArrayInitializer() == null) { PsiCallExpression callExpr = (PsiCallExpression)parent; boolean allowStatics = false; PsiExpression qualifier = callExpr instanceof PsiMethodCallExpression ? ((PsiMethodCallExpression)callExpr).getMethodExpression().getQualifierExpression() diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java index a85023a09ecd..04042c004add 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/JavaVariableInplaceIntroducer.java @@ -392,6 +392,12 @@ public class JavaVariableInplaceIntroducer extends AbstractJavaInplaceIntroducer return super.getCaretOffset(); } + @Override + public void finish(boolean success) { + super.finish(success); + myEditor.putUserData(ReassignVariableUtil.DECLARATION_KEY, null); + } + @Override protected String[] suggestNames(PsiType defaultType, String propName) { return IntroduceVariableBase.getSuggestedName(defaultType, myExpr).names; diff --git a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java index 909c5b7b0b3a..78718d8006dd 100644 --- a/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java +++ b/java/java-impl/src/com/intellij/testIntegration/JavaTestFinder.java @@ -107,7 +107,7 @@ public class JavaTestFinder implements TestFinder { PsiShortNamesCache cache = PsiShortNamesCache.getInstance(klass.getProject()); String klassName = klass.getName(); - Pattern pattern = Pattern.compile(".*" + klassName + ".*"); + Pattern pattern = Pattern.compile(".*" + klassName + ".*", Pattern.CASE_INSENSITIVE); HashSet names = new HashSet(); cache.getAllClassNames(names); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java index e25fa4ac277e..b40bf74cc456 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/NamesHighlighting.java @@ -1,4 +1,6 @@ import java.io.*; // highlight on demand import as class name +import static java.io.File.pathSeparator; +import static java.io.File.*; class a { void method() { diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java index 8c1c9a3b4986..b90ef12355b2 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaPredefinedConfigurations.java @@ -24,7 +24,7 @@ class JavaPredefinedConfigurations { // Expression patterns createSearchTemplateInfo(SSRBundle.message("predefined.configuration.method.calls"), "'_Instance?.'MethodCall('_Parameter*)", EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.new.expressions"), "new 'Constructor('_Argument*)", EXPRESSION_TYPE), - createSearchTemplateInfo(SSRBundle.message("predefined.configuration.lambdas"), "('_Parameter) -> ", EXPRESSION_TYPE), + createSearchTemplateInfo(SSRBundle.message("predefined.configuration.lambdas"), "('_Parameter*) -> ", EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.field.selections"),"'_Instance?.'Field",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.array.access"),"'_Field['_Index]",EXPRESSION_TYPE), createSearchTemplateInfo(SSRBundle.message("predefined.configuration.assignments"),"'_Inst = '_Expr",EXPRESSION_TYPE), diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index 88ce7b2c6ea9..51636ee5972f 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -21,6 +21,8 @@ import com.intellij.structuralsearch.impl.matcher.iterators.HierarchyNodeIterato import com.intellij.structuralsearch.impl.matcher.predicates.NotPredicate; import com.intellij.structuralsearch.impl.matcher.predicates.RegExpPredicate; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.util.*; @@ -383,17 +385,23 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitLambdaExpression(PsiLambdaExpression expression) { - final PsiLambdaExpression expression2 = (PsiLambdaExpression)myMatchingVisitor.getElement(); - boolean result = true; - final PsiParameterList parameterList1 = expression.getParameterList(); - if (parameterList1.getParametersCount() != 0) { - result = myMatchingVisitor.matchSons(parameterList1, expression2.getParameterList()); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiLambdaExpression) { + final PsiLambdaExpression expression2 = (PsiLambdaExpression)other; + boolean result = true; + final PsiParameterList parameterList1 = expression.getParameterList(); + if (parameterList1.getParametersCount() != 0) { + result = myMatchingVisitor.matchSons(parameterList1, expression2.getParameterList()); + } + final PsiElement body1 = getElementToMatch(expression.getBody()); + if (body1 != null && result) { + result = myMatchingVisitor.matchSequentially(body1, getElementToMatch(expression2.getBody())); + } + myMatchingVisitor.setResult(result); } - final PsiElement body1 = getElementToMatch(expression.getBody()); - if (body1 != null) { - result = myMatchingVisitor.matchSequentially(body1, getElementToMatch(expression2.getBody())); + else { + myMatchingVisitor.setResult(false); } - myMatchingVisitor.setResult(result); } private static PsiElement getElementToMatch(PsiElement element) { @@ -570,10 +578,15 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitArrayAccessExpression(final PsiArrayAccessExpression slice) { - final PsiArrayAccessExpression slice2 = (PsiArrayAccessExpression)myMatchingVisitor.getElement(); - - myMatchingVisitor.setResult(myMatchingVisitor.match(slice.getArrayExpression(), slice2.getArrayExpression()) && - myMatchingVisitor.match(slice.getIndexExpression(), slice2.getIndexExpression())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiArrayAccessExpression) { + final PsiArrayAccessExpression slice2 = (PsiArrayAccessExpression)other; + myMatchingVisitor.setResult(myMatchingVisitor.match(slice.getArrayExpression(), slice2.getArrayExpression()) && + myMatchingVisitor.match(slice.getIndexExpression(), slice2.getIndexExpression())); + } + else { + myMatchingVisitor.setResult(false); + } } @Override @@ -731,9 +744,6 @@ public class JavaMatchingVisitor extends JavaElementVisitor { PsiElement[] typeparams = null; if (el2 instanceof PsiJavaCodeReferenceElement) { typeparams = ((PsiJavaCodeReferenceElement)el2).getParameterList().getTypeParameterElements(); - if (typeparams.length > 0) { - el2 = ((PsiJavaCodeReferenceElement)el2).getReferenceNameElement(); - } } else if (el2 instanceof PsiTypeParameter) { el2 = ((PsiTypeParameter)el2).getNameIdentifier(); @@ -752,13 +762,13 @@ public class JavaMatchingVisitor extends JavaElementVisitor { PsiReferenceParameterList list = null; if (el instanceof PsiJavaCodeReferenceElement) { list = ((PsiJavaCodeReferenceElement)el).getParameterList(); + el = ((PsiJavaCodeReferenceElement)el).getReferenceNameElement(); } if (list != null && list.getTypeParameterElements().length > 0) { boolean result = typeparams != null && myMatchingVisitor.matchSequentially(list.getTypeParameterElements(), typeparams); if (!result) return false; - el = ((PsiJavaCodeReferenceElement)el).getReferenceNameElement(); } else { if (_type2 instanceof PsiTypeElement) { @@ -831,25 +841,17 @@ public class JavaMatchingVisitor extends JavaElementVisitor { el2 = parent; } } - final String text = stripTypeParameters(el.getText()); - String text2; - if (el2 instanceof PsiClass) { - text2 = ((PsiClass)el2).getQualifiedName(); - if (text2 == null) text2 = el2.getText(); - } else { - text2 = el2.getText(); - } - - final boolean equalsIgnorePackage = MatchUtils.compareWithNoDifferenceToPackage(text, stripTypeParameters(text2)); + final String text = getText(el); + final String text2 = getText(el2); + final boolean equalsIgnorePackage = MatchUtils.compareWithNoDifferenceToPackage(text, text2); if (equalsIgnorePackage || !(el2 instanceof PsiJavaReference)) { return equalsIgnorePackage; } else { - PsiElement element2 = ((PsiJavaReference)el2).resolve(); + final PsiElement element2 = ((PsiJavaReference)el2).resolve(); if (element2 instanceof PsiClass) { - final PsiClass aClass = (PsiClass)element2; - return text.equals(aClass.getQualifiedName()) || text.equals(aClass.getName()); + return text.equals(((PsiClass)element2).getQualifiedName()); } else { return MatchUtils.compareWithNoDifferenceToPackage(text, text2); @@ -857,12 +859,33 @@ public class JavaMatchingVisitor extends JavaElementVisitor { } } - private static String stripTypeParameters(String string) { - final int index = string.indexOf('<'); - if (index == -1) { - return string; + @Contract(pure = true) + private static String getText(@NotNull PsiElement element) { + String result; + if (element instanceof PsiClass) { + result = ((PsiClass)element).getQualifiedName(); + if (result == null) result = element.getText(); + } else { + result = element.getText(); } - return string.substring(0, index); + final int whitespace = lastIndexOfWhitespace(result); + if (whitespace >= 0) { + // strips off any annotations + result = result.substring(whitespace + 1); + } + final int index = result.indexOf('<'); + if (index == -1) { + return result; + } + return result.substring(0, index); + } + + @Contract(pure = true) + private static int lastIndexOfWhitespace(@NotNull CharSequence s) { + for (int i = s.length() - 1; i >= 0; i--) { + if (Character.isWhitespace(s.charAt(i))) return i; + } + return -1; } private boolean checkMatchWithingHierarchy(PsiElement el2, SubstitutionHandler handler, PsiElement context) { @@ -1119,9 +1142,14 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitExpressionStatement(final PsiExpressionStatement expr) { - final PsiExpressionStatement expr2 = (PsiExpressionStatement)myMatchingVisitor.getElement(); - - myMatchingVisitor.setResult(myMatchingVisitor.match(expr.getExpression(), expr2.getExpression())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiExpressionStatement) { + final PsiExpressionStatement expr2 = (PsiExpressionStatement)other; + myMatchingVisitor.setResult(myMatchingVisitor.match(expr.getExpression(), expr2.getExpression())); + } + else { + myMatchingVisitor.setResult(false); + } } @Override @@ -1156,11 +1184,17 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitAssignmentExpression(final PsiAssignmentExpression assign) { - final PsiAssignmentExpression assign2 = (PsiAssignmentExpression)myMatchingVisitor.getElement(); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiAssignmentExpression) { + final PsiAssignmentExpression assign2 = (PsiAssignmentExpression)other; - myMatchingVisitor.setResult(assign.getOperationTokenType().equals(assign2.getOperationTokenType()) && - myMatchingVisitor.match(assign.getLExpression(), assign2.getLExpression()) && - myMatchingVisitor.match(assign.getRExpression(), assign2.getRExpression())); + myMatchingVisitor.setResult(assign.getOperationTokenType().equals(assign2.getOperationTokenType()) && + myMatchingVisitor.match(assign.getLExpression(), assign2.getLExpression()) && + myMatchingVisitor.match(assign.getRExpression(), assign2.getRExpression())); + } + else { + myMatchingVisitor.setResult(false); + } } @Override @@ -1212,13 +1246,13 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitBlockStatement(final PsiBlockStatement block) { - if (myMatchingVisitor.getElement() instanceof PsiCodeBlock && - !(myMatchingVisitor.getElement().getParent() instanceof PsiBlockStatement) - ) { - myMatchingVisitor.setResult(myMatchingVisitor.matchSons(block.getCodeBlock(), myMatchingVisitor.getElement())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiCodeBlock) { + myMatchingVisitor.setResult(!(other.getParent() instanceof PsiBlockStatement) && + myMatchingVisitor.matchSons(block.getCodeBlock(), other)); } else { - final PsiBlockStatement block2 = (PsiBlockStatement)myMatchingVisitor.getElement(); + final PsiBlockStatement block2 = (PsiBlockStatement)other; myMatchingVisitor.setResult(myMatchingVisitor.matchSons(block, block2)); } } @@ -1414,14 +1448,20 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitInstanceOfExpression(final PsiInstanceOfExpression instanceOf) { - final PsiInstanceOfExpression instanceOf2 = (PsiInstanceOfExpression)myMatchingVisitor.getElement(); - myMatchingVisitor.setResult(myMatchingVisitor.match(instanceOf.getOperand(), instanceOf2.getOperand())); - if (myMatchingVisitor.getResult()) { - final PsiTypeElement checkType = instanceOf.getCheckType(); - if (checkType != null) { - myMatchingVisitor.setResult(matchType(checkType, instanceOf2.getCheckType())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiInstanceOfExpression) { + final PsiInstanceOfExpression instanceOf2 = (PsiInstanceOfExpression)other; + myMatchingVisitor.setResult(myMatchingVisitor.match(instanceOf.getOperand(), instanceOf2.getOperand())); + if (myMatchingVisitor.getResult()) { + final PsiTypeElement checkType = instanceOf.getCheckType(); + if (checkType != null) { + myMatchingVisitor.setResult(matchType(checkType, instanceOf2.getCheckType())); + } } } + else { + myMatchingVisitor.setResult(false); + } } @Override @@ -1501,22 +1541,39 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitTypeCastExpression(final PsiTypeCastExpression cast) { - final PsiTypeCastExpression cast2 = (PsiTypeCastExpression)myMatchingVisitor.getElement(); - - myMatchingVisitor.setResult(myMatchingVisitor.match(cast.getCastType(), cast2.getCastType()) && - myMatchingVisitor.match(cast.getOperand(), cast2.getOperand())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiTypeCastExpression) { + final PsiTypeCastExpression cast2 = (PsiTypeCastExpression)other; + myMatchingVisitor.setResult(myMatchingVisitor.match(cast.getCastType(), cast2.getCastType()) && + myMatchingVisitor.match(cast.getOperand(), cast2.getOperand())); + } + else { + myMatchingVisitor.setResult(false); + } } @Override public void visitClassObjectAccessExpression(final PsiClassObjectAccessExpression expr) { - final PsiClassObjectAccessExpression expr2 = (PsiClassObjectAccessExpression)myMatchingVisitor.getElement(); - - myMatchingVisitor.setResult(myMatchingVisitor.match(expr.getOperand(), expr2.getOperand())); + final PsiElement other = myMatchingVisitor.getElement(); + if (other instanceof PsiClassObjectAccessExpression) { + final PsiClassObjectAccessExpression expr2 = (PsiClassObjectAccessExpression)other; + myMatchingVisitor.setResult(myMatchingVisitor.match(expr.getOperand(), expr2.getOperand())); + } + else { + myMatchingVisitor.setResult(false); + } } @Override public void visitReferenceElement(final PsiJavaCodeReferenceElement ref) { - myMatchingVisitor.setResult(matchType(ref, myMatchingVisitor.getElement())); + final PsiElement other = myMatchingVisitor.getElement(); + final PsiAnnotation[] annotations = PsiTreeUtil.getChildrenOfType(ref, PsiAnnotation.class); + if (annotations != null) { + final PsiAnnotation[] otherAnnotations = PsiTreeUtil.getChildrenOfType(other, PsiAnnotation.class); + myMatchingVisitor.setResult(otherAnnotations != null && myMatchingVisitor.matchInAnyOrder(annotations, otherAnnotations)); + if (!myMatchingVisitor.getResult()) return; + } + myMatchingVisitor.setResult(matchType(ref, other)); } @Override diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java index 74e80f046aa4..77b076938efc 100644 --- a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java +++ b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java @@ -26,6 +26,10 @@ import org.jetbrains.annotations.NotNull; * @author Eugene.Kudelevsky */ public class WebReference extends PsiReferenceBase { + public WebReference(@NotNull PsiElement element) { + super(element, true); + } + public WebReference(@NotNull PsiElement element, @NotNull TextRange textRange) { super(element, textRange, true); } @@ -35,6 +39,10 @@ public class WebReference extends PsiReferenceBase { return new MyFakePsiElement(); } + protected String getUrl() { + return getValue(); + } + @NotNull @Override public Object[] getVariants() { @@ -43,25 +51,31 @@ public class WebReference extends PsiReferenceBase { class MyFakePsiElement extends FakePsiElement { @Override - public PsiElement getParent() { - return myElement; - } - - @Override - public void navigate(boolean requestFocus) { - BrowserUtil.browse(getValue()); + public PsiElement getParent() { + return myElement; } @Override - public String getPresentableText() { - return getValue(); - } + public void navigate(boolean requestFocus) { + BrowserUtil.browse(getUrl()); + } - @Override - public TextRange getTextRange() { - final TextRange rangeInElement = getRangeInElement(); - final TextRange elementRange = myElement.getTextRange(); - return elementRange != null ? rangeInElement.shiftRight(elementRange.getStartOffset()) : rangeInElement; - } + @Override + public String getPresentableText() { + return getUrl(); + } + + + @Override + public String getName() { + return getUrl(); + } + + @Override + public TextRange getTextRange() { + final TextRange rangeInElement = getRangeInElement(); + final TextRange elementRange = myElement.getTextRange(); + return elementRange != null ? rangeInElement.shiftRight(elementRange.getStartOffset()) : rangeInElement; + } } } diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java index f2ec3ac18234..d88464d6d032 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/RefactoringScopeElementListenerProvider.java @@ -24,6 +24,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiQualifiedNamedElement; import com.intellij.psi.search.scope.packageSet.*; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; import com.intellij.refactoring.listeners.RefactoringElementListenerComposite; @@ -39,10 +40,30 @@ public class RefactoringScopeElementListenerProvider implements RefactoringEleme @Override public RefactoringElementListener getListener(PsiElement element) { - final PsiFile containingFile = element.getContainingFile(); if (!(element instanceof PsiQualifiedNamedElement) && !(element instanceof PsiDirectory)) return null; - final String oldName = getQualifiedName(element); + + final PsiFile containingFile = element.getContainingFile(); + RefactoringElementListenerComposite composite = null; + String oldName = getQualifiedName(element, false); + if (oldName != null) { + composite = getComposite(element, containingFile, null, oldName); + } + + if (element instanceof PsiQualifiedNamedElement) { + oldName = getQualifiedName(element, true); + if (oldName != null) { + composite = getComposite(element, containingFile, composite, oldName); + } + } + + return composite; + } + + private static RefactoringElementListenerComposite getComposite(PsiElement element, + PsiFile containingFile, + RefactoringElementListenerComposite composite, + String oldName) { for (final NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(element.getProject())) { final NamedScope[] scopes = holder.getEditableScopes(); for (int i = 0; i < scopes.length; i++) { @@ -56,13 +77,16 @@ public class RefactoringScopeElementListenerProvider implements RefactoringEleme return composite; } - private static String getQualifiedName(PsiElement element) { - if (element instanceof PsiQualifiedNamedElement) { + private static String getQualifiedName(PsiElement element, boolean acceptQNames) { + if (element instanceof PsiQualifiedNamedElement && acceptQNames) { return ((PsiQualifiedNamedElement)element).getQualifiedName(); } else { final Project project = element.getProject(); - final VirtualFile virtualFile = ((PsiDirectory)element).getVirtualFile(); + final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element); + if (virtualFile == null) { + return null; + } return FilePatternPackageSet.getRelativePath(virtualFile, ProjectRootManager.getInstance(project).getFileIndex(), true, @@ -106,12 +130,16 @@ public class RefactoringScopeElementListenerProvider implements RefactoringEleme public void elementRenamedOrMoved(@NotNull PsiElement newElement) { LOG.assertTrue(newElement instanceof PsiQualifiedNamedElement || newElement instanceof PsiDirectory); try { - final String newPattern = text.replace(descriptor.getOldQName(), getQualifiedName(newElement)); - final PackageSet newSet = PackageSetFactory.getInstance().compile(newPattern); - NamedScope newScope = new NamedScope(descriptor.getScope().getName(), newSet); final NamedScope[] currentScopes = descriptor.getHolder().getEditableScopes(); - currentScopes[descriptor.getIdx()] = newScope; - descriptor.getHolder().setScopes(currentScopes); + final PackageSet currentPackageSet = currentScopes[descriptor.getIdx()].getValue(); + final String qualifiedName = getQualifiedName(newElement, !(currentPackageSet instanceof FilePatternPackageSet)); + if (qualifiedName != null) { + final String newPattern = text.replace(descriptor.getOldQName(), qualifiedName); + final PackageSet newSet = PackageSetFactory.getInstance().compile(newPattern); + NamedScope newScope = new NamedScope(descriptor.getScope().getName(), newSet); + currentScopes[descriptor.getIdx()] = newScope; + descriptor.getHolder().setScopes(currentScopes); + } } catch (ParsingException ignore) { } @@ -124,9 +152,7 @@ public class RefactoringScopeElementListenerProvider implements RefactoringEleme final NamedScope[] currentScopes = descriptor.getHolder().getEditableScopes(); final PatternBasedPackageSet packageSet = (PatternBasedPackageSet)currentScopes[descriptor.getIdx()].getValue(); if (packageSet == null) return; - final String oldPattern = packageSet.getPattern().replace(getQualifiedName(newElement), oldQualifiedName); - final PackageSet newSet = PackageSetFactory.getInstance().compile(oldPattern); - NamedScope newScope = new NamedScope(descriptor.getScope().getName(), newSet); + NamedScope newScope = new NamedScope(descriptor.getScope().getName(), PackageSetFactory.getInstance().compile(text)); currentScopes[descriptor.getIdx()] = newScope; descriptor.getHolder().setScopes(currentScopes); } diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index 2e24a9f70e01..3a3037930c85 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -19,10 +19,8 @@ import com.intellij.ide.BrowserUtil; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.JBInsets; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -39,8 +37,6 @@ import javax.swing.*; import javax.swing.border.Border; import javax.swing.tree.TreeCellRenderer; import java.awt.*; -import java.awt.geom.GeneralPath; -import java.awt.geom.PathIterator; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -686,25 +682,10 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co } // 2. Waved effect if (attributes.isWaved()) { - GraphicsConfig config = GraphicsUtil.setupAAPainting(g); - Stroke oldStroke = g.getStroke(); - try { - g.setStroke(new BasicStroke(.7F)); - if (attributes.getWaveColor() != null) { - g.setColor(attributes.getWaveColor()); - } - final int wavedAt = textBaseline + 1; - GeneralPath wavePath = new GeneralPath(PathIterator.WIND_EVEN_ODD); - wavePath.moveTo(offset, wavedAt); - for (int x = offset; x <= offset + fragmentWidth; x += 4) { - wavePath.lineTo(x + 2, wavedAt + 2); - wavePath.lineTo(x + 4, wavedAt); - } - g.draw(wavePath); - } finally { - config.restore(); - g.setStroke(oldStroke); + if (attributes.getWaveColor() != null) { + g.setColor(attributes.getWaveColor()); } + UIUtil.drawWave(g, new Rectangle(offset, textBaseline + 1, fragmentWidth, Math.max(2, metrics.getDescent()))); } // 3. Underline if (attributes.isUnderline()) { diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstallPluginAction.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstallPluginAction.java index 90b7f64baf9d..1c83d63642be 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/InstallPluginAction.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstallPluginAction.java @@ -86,6 +86,10 @@ public class InstallPluginAction extends AnAction implements DumbAware { install(null); } + public static boolean isInstalling(IdeaPluginDescriptor node) { + return ourInstallingNodes.contains(node); + } + public void install(@Nullable final Runnable onSuccess) { IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects(); diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java index b41bc733b174..264f81f2413a 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java @@ -141,10 +141,14 @@ public class PluginHeaderPanel { myActionId = null; } } + UIUtil.setEnabled(myButtonPanel, true, true); if (myManager == null || myActionId == null || (myManager.getInstalled() != myManager.getAvailable() && myActionId == ACTION_ID.UNINSTALL)) { myActionId = ACTION_ID.INSTALL; myButtonPanel.setVisible(false); } + else if (InstallPluginAction.isInstalling(plugin)) { + UIUtil.setEnabled(myButtonPanel, false, true); + } myRoot.revalidate(); ((JComponent)myInstallButton.getParent()).revalidate(); myInstallButton.revalidate(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 52cdc8c558e2..8e32de8231e5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1713,7 +1713,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi else { endVisLine = offsetToVisualLine(myDocument.getLineEndOffset(Math.min(myDocument.getLineCount() - 1, endLine))); } - int height = endVisLine * getLineHeight() - yStartLine + getLineHeight() + WAVE_HEIGHT; + int height = endVisLine * getLineHeight() - yStartLine + getLineHeight() + 2; myEditorComponent.repaintEditorComponent(visibleArea.x, yStartLine, visibleArea.x + visibleArea.width, height); myGutterComponent.repaint(0, yStartLine, myGutterComponent.getWidth(), height); @@ -2236,7 +2236,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi int y = visibleLineToY(visibleStartLine) + getAscent() + 1; g.setColor(attributes.getEffectColor()); if (attributes.getEffectType() == EffectType.WAVE_UNDERSCORE) { - drawWave(g, end.x, end.x + charWidth - 1, y); + UIUtil.drawWave((Graphics2D)g, new Rectangle(end.x, y, charWidth - 1, 2)); } else if (attributes.getEffectType() == EffectType.BOLD_DOTTED_LINE) { final int dottedAt = SystemInfo.isMac ? y - 1 : y; @@ -3368,7 +3368,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } else if (effectType == EffectType.WAVE_UNDERSCORE) { g.setColor(effectColor); - drawWave(g, xStart, xEnd, y + 1); + UIUtil.drawWave((Graphics2D)g, new Rectangle(xStart, y+1, xEnd - xStart, getDescent() - 1)); g.setColor(savedColor); } else if (effectType == EffectType.BOLD_DOTTED_LINE) { @@ -3515,25 +3515,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } } - private static final int WAVE_HEIGHT = 2; - private static final int WAVE_SEGMENT_LENGTH = 4; - - private static void drawWave(Graphics g, int xStart, int xEnd, int y) { - int startSegment = xStart / WAVE_SEGMENT_LENGTH; - int endSegment = xEnd / WAVE_SEGMENT_LENGTH; - for (int i = startSegment; i < endSegment; i++) { - drawWaveSegment(g, WAVE_SEGMENT_LENGTH * i, y); - } - - int x = WAVE_SEGMENT_LENGTH * endSegment; - UIUtil.drawLine(g, x, y + WAVE_HEIGHT, x + WAVE_SEGMENT_LENGTH / 2, y); - } - - private static void drawWaveSegment(Graphics g, int x, int y) { - UIUtil.drawLine(g, x, y + WAVE_HEIGHT, x + WAVE_SEGMENT_LENGTH / 2, y); - UIUtil.drawLine(g, x + WAVE_SEGMENT_LENGTH / 2, y, x + WAVE_SEGMENT_LENGTH, y + WAVE_HEIGHT); - } - private int getTextSegmentWidth(@NotNull CharSequence text, int start, int end, diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java index d01e47b9ba4a..21aca44c74ae 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java @@ -48,7 +48,7 @@ public class UpdateSettingsConfigurable extends BaseConfigurable implements Sear @Override public JComponent createComponent() { myUpdatesSettingsPanel = new UpdatesSettingsPanel(); - myUpdatesSettingsPanel.myCheckNow.setEnabled(myCheckNowEnabled); + myUpdatesSettingsPanel.myCheckNow.setVisible(myCheckNowEnabled); return myUpdatesSettingsPanel.myPanel; } diff --git a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java deleted file mode 100644 index cfecf57b8c85..000000000000 --- a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.psi.impl; - -import com.intellij.ide.BrowserUtil; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiReferenceBase; -import org.jetbrains.annotations.NotNull; - -public class UrlPsiReference extends PsiReferenceBase { - public UrlPsiReference(PsiElement element) { - super(element); - } - - protected String getUrl() { - return getValue(); - } - - public PsiElement resolve() { - return new FakePsiElement() { - public PsiElement getParent() { - return getElement(); - } - - @Override - public String getName() { - return getUrl(); - } - - @Override - public void navigate(boolean requestFocus) { - BrowserUtil.browse(getUrl()); - } - }; - } - - @NotNull - public Object[] getVariants() { - return EMPTY_ARRAY; - } - - @Override - public boolean isSoft() { - return true; - } -} \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 8f4fa6e21aaf..7ff6ad4872f3 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -921,7 +921,7 @@ updates.more.info.button=&More Info... updates.ignore.update.button=&Ignore This Update updates.remind.later.button=&Remind Me Later updates.buy.online.button=&Buy Upgrade Online -updates.new.version.available=A new version of {0} is available! +updates.new.version.available=A new version of {0} is available! updates.current.version=Current version: updates.available.version=New version: updates.patch.label=Patch size: diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java index 3f5e4ba42b0b..525e260f0da5 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/deployment/ServerRuntimeInstance.java @@ -40,6 +40,11 @@ public abstract class ServerRuntimeInstance { void addDeployment(@NotNull String deploymentName, @Nullable DeploymentRuntime deploymentRuntime); + void addDeployment(@NotNull String deploymentName, + @Nullable DeploymentRuntime deploymentRuntime, + @Nullable DeploymentStatus deploymentStatus, + @Nullable String deploymentStatusText); + void succeeded(); } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java index 8636ce3edab9..40179f0effae 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionImpl.java @@ -177,7 +177,19 @@ public class ServerConnectionImpl implements @Override public void addDeployment(@NotNull String deploymentName, @Nullable DeploymentRuntime deploymentRuntime) { - myDeployments.add(new DeploymentImpl(deploymentName, DeploymentStatus.DEPLOYED, null, deploymentRuntime, null)); + addDeployment(deploymentName, deploymentRuntime, null, null); + } + + @Override + public void addDeployment(@NotNull String deploymentName, + @Nullable DeploymentRuntime deploymentRuntime, + @Nullable DeploymentStatus deploymentStatus, + @Nullable String deploymentStatusText) { + myDeployments.add(new DeploymentImpl(deploymentName, + deploymentStatus == null ? DeploymentStatus.DEPLOYED : deploymentStatus, + deploymentStatusText, + deploymentRuntime, + null)); } @Override diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudApplicationRuntime.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudApplicationRuntime.java index 093cfb50bcc0..c62bbbc6fd97 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudApplicationRuntime.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudApplicationRuntime.java @@ -16,6 +16,8 @@ package com.intellij.remoteServer.util; import com.intellij.remoteServer.runtime.deployment.DeploymentRuntime; +import com.intellij.remoteServer.runtime.deployment.DeploymentStatus; +import org.jetbrains.annotations.Nullable; public abstract class CloudApplicationRuntime extends DeploymentRuntime { @@ -28,4 +30,14 @@ public abstract class CloudApplicationRuntime extends DeploymentRuntime { public String getApplicationName() { return myApplicationName; } + + @Nullable + public DeploymentStatus getStatus() { + return null; + } + + @Nullable + public String getStatusText() { + return null; + } } diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudServerRuntimeInstance.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudServerRuntimeInstance.java index 3f9aecd8ba77..e4311b8ee625 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudServerRuntimeInstance.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudServerRuntimeInstance.java @@ -95,7 +95,7 @@ public abstract class CloudServerRuntimeInstance public void run() throws Exception { try { for (CloudApplicationRuntime application : getApplications()) { - callback.addDeployment(application.getApplicationName(), application); + callback.addDeployment(application.getApplicationName(), application, application.getStatus(), application.getStatusText()); } callback.succeeded(); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java index b37c10143636..be33189ee486 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchUtil.java @@ -2,7 +2,6 @@ package com.intellij.structuralsearch; import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.*; -import com.intellij.openapi.fileTypes.impl.AbstractFileType; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.impl.matcher.MatchUtils; import com.intellij.structuralsearch.plugin.ui.Configuration; @@ -67,7 +66,7 @@ public class StructuralSearchUtil { ourDefaultFileType = StdFileTypes.XML; } } - assert isValidFileType(ourDefaultFileType) : "file type not valid for structural search: " + ourDefaultFileType.getName(); + assert ourDefaultFileType instanceof LanguageFileType : "file type not valid for structural search: " + ourDefaultFileType.getName(); return ourDefaultFileType; } @@ -116,7 +115,7 @@ public class StructuralSearchUtil { List result = new ArrayList(); for (FileType fileType : allFileTypes) { - if (isValidFileType(fileType)) { + if (fileType instanceof LanguageFileType) { result.add(fileType); } } @@ -124,19 +123,6 @@ public class StructuralSearchUtil { return result.toArray(new FileType[result.size()]); } - private static boolean isValidFileType(FileType fileType) { - return fileType != StdFileTypes.GUI_DESIGNER_FORM && - fileType != StdFileTypes.IDEA_MODULE && - fileType != StdFileTypes.IDEA_PROJECT && - fileType != StdFileTypes.IDEA_WORKSPACE && - fileType != FileTypes.ARCHIVE && - fileType != FileTypes.UNKNOWN && - fileType != FileTypes.PLAIN_TEXT && - !(fileType instanceof AbstractFileType) && - !fileType.isBinary() && - !fileType.isReadOnly(); - } - public static String shieldSpecialChars(String word) { final StringBuilder buf = new StringBuilder(word.length()); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index 92b6568c28c0..678b99cf2146 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -145,10 +145,7 @@ public class MatcherImpl { visitor.matchContext(matchedNodes); } finally { matchedNodes.reset(); - final MatchOptions options = matchContext.getOptions(); - if (options != null) { - options.setScope(null); - } + context.getOptions().setScope(null); } } diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 12aa4bd41979..73d6780e2429 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -2446,10 +2446,11 @@ public class StructuralSearchTest extends StructuralSearchTestCase { assertEquals("Find all annotations", 4, findMatchesCount(source2, "@'_Annotation")); String source3 = "class A {\n" + - " @HH final String s = (@HH String) new Object();\n" + + " @HH final String s = (@HH String) new @HH Object();\n" + " final String t = (String) new Object();\n" + "}\n"; assertEquals("Find annotated casts", 1, findMatchesCount(source3, "(@'_A 'Cast) '_Expression")); + assertEquals("Find annotated new expressions", 1, findMatchesCount(source3, "new @'_A 'Type()")); } public void testBoxingAndUnboxing() { @@ -2954,6 +2955,9 @@ public class StructuralSearchTest extends StructuralSearchTestCase { String pattern5 = "()->{/*comment*/}"; assertEquals("should find lambdas with comment body", 1, findMatchesCount(source, pattern5)); + + String pattern6 = "('_Parameter+) -> System.out.println()"; + assertEquals("should find lambdas with at least one parameter and matching body", 0, findMatchesCount(source, pattern6)); } public void testFindDefaultMethods() { diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index 62d9c5924aed..0eeadb43594d 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -19,6 +19,7 @@ import com.intellij.BundleBase; import com.intellij.icons.AllIcons; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -57,6 +58,7 @@ import javax.swing.undo.UndoManager; import java.awt.*; import java.awt.event.*; import java.awt.font.FontRenderContext; +import java.awt.geom.GeneralPath; import java.awt.im.InputContext; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; @@ -590,6 +592,26 @@ public class UIUtil { } } + public static void drawWave(Graphics2D g, Rectangle rectangle) { + GraphicsConfig config = GraphicsUtil.setupAAPainting(g); + Stroke oldStroke = g.getStroke(); + try { + g.setStroke(new BasicStroke(0.7F)); + double cycle = 4; + final double wavedAt = rectangle.y + (double)rectangle.height /2 - .5; + GeneralPath wavePath = new GeneralPath(); + wavePath.moveTo(rectangle.x, wavedAt - Math.cos(rectangle.x * 2 * Math.PI / cycle)); + for (int x = rectangle.x + 1; x <= rectangle.x + rectangle.width; x++) { + wavePath.lineTo(x, wavedAt - Math.cos(x * 2 * Math.PI / cycle) ); + } + g.draw(wavePath); + } + finally { + config.restore(); + g.setStroke(oldStroke); + } + } + @NotNull public static String[] splitText(String text, FontMetrics fontMetrics, int widthLimit, char separator) { ArrayList lines = new ArrayList(); diff --git a/plugins/coverage/lib/jacocoagent.jar b/plugins/coverage/lib/jacocoagent.jar index f934c847aa43..29f58bd8f972 100644 Binary files a/plugins/coverage/lib/jacocoagent.jar and b/plugins/coverage/lib/jacocoagent.jar differ diff --git a/plugins/coverage/lib/jacocoant.jar b/plugins/coverage/lib/jacocoant.jar index a4fa857fd557..ccadf0f87844 100644 Binary files a/plugins/coverage/lib/jacocoant.jar and b/plugins/coverage/lib/jacocoant.jar differ diff --git a/plugins/coverage/src/com/intellij/coverage/JaCoCoCoverageRunner.java b/plugins/coverage/src/com/intellij/coverage/JaCoCoCoverageRunner.java index 9d862cee0b7a..dc5c21dc0695 100644 --- a/plugins/coverage/src/com/intellij/coverage/JaCoCoCoverageRunner.java +++ b/plugins/coverage/src/com/intellij/coverage/JaCoCoCoverageRunner.java @@ -99,6 +99,7 @@ public class JaCoCoCoverageRunner extends JavaCoverageRunner { for (int i = firstLine; i <= lastLine; i++) { final ILine methodLine = method.getLine(i); final int methodLineStatus = methodLine.getStatus(); + if (methodLineStatus == ICounter.EMPTY) continue; final LineData lineData = new LineData(i , desc) { @Override public int getStatus() { diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.form b/plugins/git4idea/src/git4idea/config/GitVcsPanel.form index 5251889065c1..015def1cfd1f 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.form +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.form @@ -91,7 +91,7 @@ - + @@ -99,27 +99,9 @@ - - - - - - - - - - - - - - - - - - - + @@ -128,7 +110,7 @@ - + @@ -136,7 +118,7 @@ - + @@ -145,7 +127,7 @@ - + @@ -154,7 +136,7 @@ - + @@ -162,12 +144,45 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java index 7027dab4401f..eab386ebc604 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java @@ -22,12 +22,15 @@ import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.ui.EnumComboBoxModel; import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.execution.ParametersListUtil; +import com.intellij.util.ui.UIUtil; import git4idea.GitVcs; import git4idea.i18n.GitBundle; import git4idea.repo.GitRepositoryManager; @@ -36,6 +39,8 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.util.List; /** @@ -61,6 +66,7 @@ public class GitVcsPanel { private JCheckBox myEnableForcePush; private TextFieldWithBrowseButton myProtectedBranchesButton; private JBLabel myProtectedBranchesLabel; + private JComboBox myUpdateMethodComboBox; public GitVcsPanel(@NotNull Project project) { myVcs = GitVcs.getInstance(project); @@ -81,6 +87,13 @@ public class GitVcsPanel { mySyncControl.setVisible(repositoryManager != null && repositoryManager.moreThanOneRoot()); mySyncControl.setToolTipText(DvcsBundle.message("sync.setting.description", "Git")); myProtectedBranchesLabel.setLabelFor(myProtectedBranchesButton); + myEnableForcePush.addItemListener(new ItemListener() { + @Override + public void itemStateChanged(ItemEvent e) { + UIUtil.setEnabled(myProtectedBranchesButton, myEnableForcePush.isSelected(), true); + UIUtil.setEnabled(myProtectedBranchesLabel, myEnableForcePush.isSelected(), false); + } + }); } /** @@ -135,6 +148,7 @@ public class GitVcsPanel { myWarnAboutCrlf.setSelected(settings.warnAboutCrlf()); myWarnAboutDetachedHead.setSelected(settings.warnAboutDetachedHead()); myEnableForcePush.setSelected(settings.isForcePushAllowed()); + myUpdateMethodComboBox.setSelectedItem(settings.getUpdateType()); myProtectedBranchesButton.setText(ParametersListUtil.COLON_LINE_JOINER.fun(sharedSettings.getForcePushProhibitedPatterns())); } @@ -152,6 +166,7 @@ public class GitVcsPanel { settings.warnAboutCrlf() != myWarnAboutCrlf.isSelected() || settings.warnAboutDetachedHead() != myWarnAboutDetachedHead.isSelected() || settings.isForcePushAllowed() != myEnableForcePush.isSelected() || + settings.getUpdateType() != myUpdateMethodComboBox.getModel().getSelectedItem() || !ContainerUtil.sorted(sharedSettings.getForcePushProhibitedPatterns()).equals( ContainerUtil.sorted(getProtectedBranchesPatterns()))); } @@ -174,6 +189,7 @@ public class GitVcsPanel { settings.setWarnAboutCrlf(myWarnAboutCrlf.isSelected()); settings.setWarnAboutDetachedHead(myWarnAboutDetachedHead.isSelected()); settings.setForcePushAllowed(myEnableForcePush.isSelected()); + settings.setUpdateType((UpdateMethod)myUpdateMethodComboBox.getSelectedItem()); sharedSettings.setForcePushProhibitedPatters(getProtectedBranchesPatterns()); } @@ -191,5 +207,6 @@ public class GitVcsPanel { } }); myProtectedBranchesButton.setButtonIcon(AllIcons.Actions.ShowViewer); + myUpdateMethodComboBox = new ComboBox(new EnumComboBoxModel(UpdateMethod.class)); } } diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java index faf29b0e15a0..c9de244b20ca 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java @@ -68,6 +68,7 @@ public class GitVcsSettings implements PersistentStateComponent RECENT_BRANCH_BY_REPOSITORY = new HashMap(); @@ -96,8 +97,9 @@ public class GitVcsSettings implements PersistentStateComponent { - - private static final UpdateMethod DEFAULT_UPDATE_METHOD = UpdateMethod.MERGE; - - private State myState = new State(); - - public static class State { - public boolean myUpdateAllRoots = true; - public UpdateMethod myUpdateMethod = DEFAULT_UPDATE_METHOD; - } - - public static GitPushSettings getInstance(Project project) { - return ServiceManager.getService(project, GitPushSettings.class); - } - - @Override - public State getState() { - return myState; - } - - @Override - public void loadState(State state) { - myState = state; - } - - public boolean shouldUpdateAllRoots() { - return myState.myUpdateAllRoots; - } - - public void setUpdateAllRoots(boolean updateAllRoots) { - myState.myUpdateAllRoots = updateAllRoots; - } - - @NotNull - public UpdateMethod getUpdateMethod() { - return ObjectUtils.notNull(myState.myUpdateMethod, DEFAULT_UPDATE_METHOD); - } - - public void setUpdateMethod(@NotNull UpdateMethod updateMethod) { - myState.myUpdateMethod = updateMethod; - } - -} diff --git a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java index eb69f1d0fa86..8f1882e09269 100644 --- a/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java +++ b/plugins/git4idea/tests/git4idea/push/GitPushOperationSingleRepoTest.java @@ -29,7 +29,6 @@ import com.intellij.util.containers.ContainerUtil; import git4idea.branch.GitBranchUtil; import git4idea.config.UpdateMethod; import git4idea.repo.GitRepository; -import git4idea.settings.GitPushSettings; import git4idea.test.TestDialogHandler; import git4idea.test.TestMessageHandler; import git4idea.update.GitRebaseOverMergeProblem; @@ -255,13 +254,7 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { } public void test_warn_if_rebasing_over_merge() throws IOException { - pushCommitFromBro(); - cd(myRepository); - git("checkout -b branch1"); - makeCommit("branch1.txt"); - git("checkout master"); - makeCommit("master.txt"); - git("merge branch1"); + generateUnpushedMergedCommitProblem(); final Ref rebaseOverMergeProblemDetected = Ref.create(false); myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { @@ -276,16 +269,10 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { } public void test_warn_if_silently_rebasing_over_merge() throws IOException { - pushCommitFromBro(); - cd(myRepository); - git("checkout -b branch1"); - makeCommit("branch1.txt"); - git("checkout master"); - makeCommit("master.txt"); - git("merge branch1"); + generateUnpushedMergedCommitProblem(); myGitSettings.setAutoUpdateIfPushRejected(true); - GitPushSettings.getInstance(myProject).setUpdateMethod(UpdateMethod.REBASE); + myGitSettings.setUpdateType(UpdateMethod.REBASE); final Ref rebaseOverMergeProblemDetected = Ref.create(false); myDialogManager.registerMessageHandler(new TestMessageHandler() { @@ -299,6 +286,35 @@ public class GitPushOperationSingleRepoTest extends GitPushOperationBaseTest { assertTrue(rebaseOverMergeProblemDetected.get()); } + public void test_dont_overwrite_rebase_setting_when_chose_to_merge_due_to_unpushed_merge_commits() throws IOException { + generateUnpushedMergedCommitProblem(); + + myGitSettings.setUpdateType(UpdateMethod.REBASE); + + final Ref rebaseOverMergeProblemDetected = Ref.create(false); + myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler() { + @Override + public int handleDialog(@NotNull GitRejectedPushUpdateDialog dialog) { + rebaseOverMergeProblemDetected.set(dialog.warnsAboutRebaseOverMerge()); + return GitRejectedPushUpdateDialog.MERGE_EXIT_CODE; + } + }); + push("master", "origin/master"); + assertTrue(rebaseOverMergeProblemDetected.get()); + assertEquals("Update method was overwritten by temporary update-via-merge decision", + UpdateMethod.REBASE, myGitSettings.getUpdateType()); + } + + private void generateUnpushedMergedCommitProblem() throws IOException { + pushCommitFromBro(); + cd(myRepository); + git("checkout -b branch1"); + makeCommit("branch1.txt"); + git("checkout master"); + makeCommit("master.txt"); + git("merge branch1"); + } + @NotNull private GitPushResult push(@NotNull String from, @NotNull String to) { return push(from, to, false); diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index d1edefd03f21..453f8b7e4512 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -56,6 +56,12 @@ public class JUnitConfiguration extends ModuleBasedConfiguration implem private JComboBox myTypeChooser; private JBLabel mySearchForTestsLabel; private JPanel myScopesPanel; - @NonNls private static final String NONE = "none"; - @NonNls private static final String METHOD = "method"; - @NonNls private static final String KLASS = "class"; - private static final String[] FORK_MODE_ALL = {NONE, METHOD, KLASS}; - private static final String[] FORK_MODE = {NONE, METHOD}; + private static final String[] FORK_MODE_ALL = {JUnitConfiguration.FORK_NONE, JUnitConfiguration.FORK_METHOD, JUnitConfiguration.FORK_KLASS}; + private static final String[] FORK_MODE = {JUnitConfiguration.FORK_NONE, JUnitConfiguration.FORK_METHOD}; private Project myProject; private JComponent anchor; @@ -273,7 +269,7 @@ public class JUnitConfigurable extends SettingsEditor implem private void changePanel () { String selectedItem = (String)myForkCb.getSelectedItem(); if (selectedItem == null) { - selectedItem = NONE; + selectedItem = JUnitConfiguration.FORK_NONE; } final Integer selectedType = (Integer)myTypeChooser.getSelectedItem(); if (selectedType == JUnitConfigurationModel.ALL_IN_PACKAGE) { @@ -309,7 +305,7 @@ public class JUnitConfigurable extends SettingsEditor implem myMethod.setVisible(false); myForkCb.setEnabled(true); myForkCb.setModel(new DefaultComboBoxModel(FORK_MODE)); - myForkCb.setSelectedItem(selectedItem != KLASS ? selectedItem : METHOD); + myForkCb.setSelectedItem(selectedItem != JUnitConfiguration.FORK_KLASS ? selectedItem : JUnitConfiguration.FORK_METHOD); } else if (selectedType == JUnitConfigurationModel.METHOD){ myPackagePanel.setVisible(false); @@ -320,7 +316,7 @@ public class JUnitConfigurable extends SettingsEditor implem myCategory.setVisible(false); myMethod.setVisible(true); myForkCb.setEnabled(false); - myForkCb.setSelectedItem(NONE); + myForkCb.setSelectedItem(JUnitConfiguration.FORK_NONE); } else if (selectedType == JUnitConfigurationModel.CATEGORY) { myPackagePanel.setVisible(false); myScopesPanel.setVisible(true); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java index d7a4ca4bae4f..b0cdaff874a3 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/MavenUrlConverter.java @@ -15,10 +15,10 @@ */ package org.jetbrains.idea.maven.dom.converters; +import com.intellij.openapi.paths.WebReference; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.UrlPsiReference; import com.intellij.util.xml.ConvertContext; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -35,6 +35,6 @@ public class MavenUrlConverter extends MavenReferenceConverter { } protected PsiReference createReference(PsiElement element, String text, TextRange range) { - return new UrlPsiReference(element); + return new WebReference(element, range); } } \ No newline at end of file diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java index b85120a5f881..3223ba6125e6 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/converters/repositories/MavenRepositoryConverter.java @@ -18,10 +18,10 @@ package org.jetbrains.idea.maven.dom.converters.repositories; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.module.Module; +import com.intellij.openapi.paths.WebReference; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.UrlPsiReference; import com.intellij.util.xml.ConvertContext; import com.intellij.util.xml.GenericDomValue; import com.intellij.util.xml.ResolvingConverter; @@ -76,8 +76,7 @@ public abstract class MavenRepositoryConverter extends ResolvingConverterSettings->IPython Notebook"); + showWarning(fileEditor, "Please, specify IPython Notebook URL in Settings->Tools->IPython Notebook", + new HyperlinkAdapter() { + @Override + protected void hyperlinkActivated(HyperlinkEvent e) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, "IPython Notebook"); + } + }); return; } if (startConnection(codePanel, path, url, false)) { @@ -78,20 +89,33 @@ public final class IpnbConnectionManager implements ProjectComponent { IpnbSettings.getInstance(myProject).setURL(url); boolean connectionStarted = startConnection(codePanel, path, url, false); if (!connectionStarted) { - final boolean serverStarted = startIpythonServer(url, fileEditor); - if (!serverStarted) { - return; - } - - waitForIpythonServer(); - final Notification notification = - new Notification("IPythonNotebook", "", "IPython notebook started at " + url + "", NotificationType.INFORMATION, - NotificationListener.URL_OPENING_LISTENER); - notification.notify(myProject); - IpnbSettings.getInstance(myProject).setURL(url); + final String finalUrl = url; + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { + @Override + public void run() { + final boolean serverStarted = startIpythonServer(finalUrl, fileEditor); + if (!serverStarted) { + return; + } + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + new Alarm(Alarm.ThreadToUse.SWING_THREAD).addRequest(new Runnable() { + @Override + public void run() { + final Notification notification = + new Notification("IPythonNotebook", "", "IPython notebook started at " + finalUrl + "", NotificationType.INFORMATION, + NotificationListener.URL_OPENING_LISTENER); + notification.notify(myProject); + startConnection(codePanel, path, finalUrl, true); + } + }, 3000); + } + }); + } + }); } - startConnection(codePanel, path, url, true); } else { final IpnbConnection connection = myKernels.get(path); @@ -102,52 +126,25 @@ public final class IpnbConnectionManager implements ProjectComponent { } } - private void waitForIpythonServer() { - final long startTime = System.currentTimeMillis(); - - final InputStream stream = myProcessHandler.getProcess().getErrorStream(); - final BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - - try { - long time = System.currentTimeMillis() - startTime; - while (time < 50000) { - final String line = reader.readLine(); - if (line != null && line.contains("The IPython Notebook is running")) { - break; - } - time = System.currentTimeMillis() - startTime; - } - } - catch (IOException ignored) { - } - finally { - try { - reader.close(); - } - catch (IOException ignored) { - } - } - } - private static String showDialogUrl(@NotNull final String initialUrl) { final String url = Messages.showInputDialog("IPython Notebook URL:", "Start IPython Notebook", null, initialUrl, - new InputValidator() { - @Override - public boolean checkInput(String inputString) { - try { - new URL(inputString); + new InputValidator() { + @Override + public boolean checkInput(String inputString) { + try { + new URL(inputString); + } + catch (MalformedURLException e) { + return false; + } + return !inputString.isEmpty(); } - catch (MalformedURLException e) { - return false; - } - return !inputString.isEmpty(); - } - @Override - public boolean canClose(String inputString) { - return true; - } - }); + @Override + public boolean canClose(String inputString) { + return true; + } + }); return url == null ? null : StringUtil.trimEnd(url, "/"); } @@ -176,7 +173,13 @@ public final class IpnbConnectionManager implements ProjectComponent { } catch (URISyntaxException e) { if (showNotification) - showWarning(codePanel.getFileEditor(), "Please, check IPython Notebook URL in Settings->IPython Notebook"); + showWarning(codePanel.getFileEditor(), "Please, check IPython Notebook URL in Settings->Tools->IPython Notebook", + new HyperlinkAdapter() { + @Override + protected void hyperlinkActivated(HyperlinkEvent e) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, "IPython Notebook"); + } + }); LOG.warn("IPython Notebook URI Syntax Error: " + e.getMessage()); return false; } @@ -189,13 +192,18 @@ public final class IpnbConnectionManager implements ProjectComponent { return true; } - private static void showWarning(@NotNull final IpnbFileEditor fileEditor, @NotNull final String message) { + private static void showWarning(@NotNull final IpnbFileEditor fileEditor, @NotNull final String message, + @Nullable final HyperlinkAdapter listener) { BalloonBuilder balloonBuilder = JBPopupFactory.getInstance().createHtmlTextBalloonBuilder( - message, null, MessageType.WARNING.getPopupBackground(), null); + message, null, MessageType.WARNING.getPopupBackground(), listener); final Balloon balloon = balloonBuilder.createBalloon(); balloon.showInCenterOf(fileEditor.getRunCellButton()); } + private static void showWarning(@NotNull final IpnbFileEditor fileEditor, @NotNull final String message) { + showWarning(fileEditor, message, null); + } + private boolean startIpythonServer(@NotNull final String url, @NotNull final IpnbFileEditor fileEditor) { final Module module = ProjectFileIndex.SERVICE.getInstance(myProject).getModuleForFile(fileEditor.getVirtualFile()); if (module == null) return false; diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParser.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParser.java index f5946f8763b2..53e0de51af83 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParser.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/psi/IpnbPyParser.java @@ -22,7 +22,19 @@ public class IpnbPyParser extends PyParser { @NotNull @Override public ASTNode parse(IElementType root, PsiBuilder builder) { + final PsiBuilder.Marker rootMarker = builder.mark(); + myIPythonStartSymbol = PyConsoleParser.startsWithIPythonSpecialSymbol(builder); - return super.parse(root, builder); + + ParsingContext context = createParsingContext(builder, LanguageLevel.getDefault(), null); + + StatementParsing statementParser = context.getStatementParser(); + builder.setTokenTypeRemapper(statementParser); + + while (!builder.eof()) { + statementParser.parseStatement(context.emptyParsingScope()); + } + rootMarker.done(root); + return builder.getTreeBuilt(); } } diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java index 1c3406b211d9..4b533d813c08 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java @@ -45,6 +45,11 @@ public class PyCustomMember { boolean myFunction = false; + /** + * Force resolving to {@link MyInstanceElement} even if element is function + */ + private boolean myAlwaysResolveToCustomElement; + public PyCustomMember(@NotNull final String name, @Nullable final String type, final boolean resolveToInstance) { myName = name; myResolveToInstance = resolveToInstance; @@ -82,6 +87,7 @@ public class PyCustomMember { myTypeName = typeName; myTypeCallback = null; } + public PyCustomMember(@NotNull final String name, @Nullable final PsiElement target) { this(name, target, null); } @@ -96,6 +102,15 @@ public class PyCustomMember { return this; } + /** + * Force resolving to {@link MyInstanceElement} even if element is function + */ + @NotNull + public final PyCustomMember alwaysResolveToCustomElement() { + myAlwaysResolveToCustomElement = true; + return this; + } + public PyCustomMember toClass(String name) { myPsiPath = new PyPsiPath.ToClass(myPsiPath, name); return this; @@ -156,7 +171,7 @@ public class PyCustomMember { PyClass targetClass = myTypeName != null && myTypeName.indexOf('.') > 0 ? PyPsiFacade.getInstance(context.getProject()).findClass(myTypeName) : null; final PsiElement resolveTarget = findResolveTarget(context); - if (resolveTarget instanceof PyFunction) { + if (resolveTarget instanceof PyFunction && !myAlwaysResolveToCustomElement) { return resolveTarget; } if (resolveTarget != null || targetClass != null) { @@ -211,4 +226,4 @@ public class PyCustomMember { return null; } } -} +} \ No newline at end of file diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java index 6b2dcc2e3610..99f59355f969 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassMembersProvider.java @@ -30,7 +30,7 @@ public interface PyClassMembersProvider { ExtensionPointName EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider"); @NotNull - Collection getMembers(PyClassType clazz, @Nullable PsiElement location); + Collection getMembers(final PyClassType clazz, PsiElement location); @Nullable PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location); diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java index 21653178781d..368059138d9f 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyTypeProviderBase.java @@ -102,6 +102,7 @@ public class PyTypeProviderBase implements PyTypeProvider { return null; } + @Nullable @Override public PyType getCallType(@NotNull PyFunction function, @Nullable PyCallSiteExpression callSite, @NotNull TypeEvalContext context) { ReturnTypeDescriptor descriptor; diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java index 54af2a23e3c4..41a2a16c82cb 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java +++ b/python/psi-api/src/com/jetbrains/python/psi/types/TypeEvalContext.java @@ -191,7 +191,7 @@ public class TypeEvalContext { } } final PyType type = element.getType(this, Key.INSTANCE); - assertValid(type, element); + assertValid(type, element); synchronized (myEvaluated) { myEvaluated.put(element, type); } diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index 89608bf54456..574bb835de66 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -850,5 +850,4 @@ remote.interpreter.configure.path.label=Python interpreter path: remote.interpreter.configure.temp.files.path.label=PyCharm helpers path: # Message we display for inspection if user uses custom class type members that do not exist -custom.type.name=Dynamic class custom.type.mimic.name=Dynamic class based on {0} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/PyCustomMembersType.java b/python/src/com/jetbrains/python/PyCustomMembersType.java deleted file mode 100644 index ca6bc5368eb5..000000000000 --- a/python/src/com/jetbrains/python/PyCustomMembersType.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jetbrains.python; - -import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiElement; -import com.intellij.util.ArrayUtil; -import com.intellij.util.ProcessingContext; -import com.jetbrains.python.codeInsight.PyCustomMember; -import com.jetbrains.python.codeInsight.PyCustomMemberUtils; -import com.jetbrains.python.psi.AccessDirection; -import com.jetbrains.python.psi.PyCallSiteExpression; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.resolve.PyResolveContext; -import com.jetbrains.python.psi.resolve.RatedResolveResult; -import com.jetbrains.python.psi.types.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -/** - * Custom (aka dynamic) type that has some members you pass to it. To be used for cases like "type()" - * This class can also mimic any other class (optionally). When mimics, it has all methods from this class and its own. - * @author Ilya.Kazakevich - */ -public class PyCustomMembersType implements PyClassLikeType { - @NotNull - private final Map myMembers; - @Nullable - private final PyClassType myTypeToMimic; - - /** - * @param typeToMimic this type may mimic some other class-based type. Pass it to have all members from this class + custom. - * Check class manual for more info. - * @param members custom members - */ - public PyCustomMembersType(@Nullable final PyClassType typeToMimic, @NotNull final PyCustomMember... members) { - myTypeToMimic = typeToMimic; - - myMembers = new HashMap(members.length); - for (final PyCustomMember member : members) { - myMembers.put(member.getName(), member); - } - } - - /** - * @return class we mimic (if any). Check class manual for more info. - */ - @Nullable - public PyClassType getTypeToMimic() { - return myTypeToMimic; - } - - @Override - public boolean isDefinition() { - return false; - } - - @Override - public PyClassLikeType toInstance() { - return this; - } - - @Nullable - @Override - public String getClassQName() { - return null; - } - - @NotNull - @Override - public List getSuperClassTypes(@NotNull TypeEvalContext context) { - return Collections.emptyList(); - } - - @Nullable - @Override - public List resolveMember(@NotNull final String name, - @Nullable final PyExpression location, - @NotNull final AccessDirection direction, - @NotNull final PyResolveContext resolveContext, - final boolean inherited) { - if (myMembers.containsKey(name)) { - PsiElement context = null; - if (location != null) { - context = location; - } - if (context == null) { - context = resolveContext.getTypeEvalContext().getOrigin(); - } - if (context != null) { - final PsiElement resolveResult = myMembers.get(name).resolve(context); - if (resolveResult != null) { - return Collections.singletonList(new RatedResolveResult(0, resolveResult)); - } - } - } - if (myTypeToMimic != null) { - return myTypeToMimic.resolveMember(name, location, direction, resolveContext, inherited); - } - return null; - } - - @Override - public boolean isValid() { - return true; - } - - @Nullable - @Override - public PyClassLikeType getMetaClassType(@NotNull TypeEvalContext context, boolean inherited) { - return null; - } - - @Override - public boolean isCallable() { - return true; - } - - @Nullable - @Override - public PyType getReturnType(@NotNull TypeEvalContext context) { - return null; - } - - @Nullable - @Override - public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) { - return this; - } - - @Nullable - @Override - public List getParameters(@NotNull TypeEvalContext context) { - return null; - } - - @Nullable - @Override - public List resolveMember(@NotNull final String name, - @Nullable final PyExpression location, - @NotNull final AccessDirection direction, - @NotNull final PyResolveContext resolveContext) { - return resolveMember(name, location, direction, resolveContext, true); - } - - @Override - public Object[] getCompletionVariants(final String completionPrefix, final PsiElement location, final ProcessingContext context) { - final Collection lookupElements = new ArrayList(myMembers.size()); - for (final PyCustomMember member : myMembers.values()) { - lookupElements.add(PyCustomMemberUtils.toLookUpElement(member, member.getShortType())); - } - return ArrayUtil.mergeArrays(ArrayUtil.toObjectArray(lookupElements), - ((myTypeToMimic != null) - ? myTypeToMimic.getCompletionVariants(completionPrefix, location, context) - : PsiElement.EMPTY_ARRAY)); - } - - - @Nullable - @Override - public String getName() { - String mimicName = null; - if (myTypeToMimic != null) { - mimicName = myTypeToMimic.getName(); - } - if (mimicName != null) { - return PyBundle.message("custom.type.mimic.name", mimicName); - } - return PyBundle.message("custom.type.name"); - } - - @Override - public boolean isBuiltin() { - return false; - } - - @Override - public void assertValid(final String message) { - - } - - /** - * @param name name to check - * @return True if this class (not the one it mimics!) has member with passed name - */ - public boolean hasMember(@NotNull final String name) { - return myMembers.containsKey(name); - } -} diff --git a/python/src/com/jetbrains/python/PyCustomType.java b/python/src/com/jetbrains/python/PyCustomType.java new file mode 100644 index 000000000000..09d9bee8bc56 --- /dev/null +++ b/python/src/com/jetbrains/python/PyCustomType.java @@ -0,0 +1,245 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.python; + +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; +import com.intellij.util.ProcessingContext; +import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.resolve.RatedResolveResult; +import com.jetbrains.python.psi.types.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * Custom (aka dynamic) type that delegates calls to some classes you pass to it. + * We say this this class mimics such classes. + * To be used for cases like "type()". + * It optionally filters methods using {@link ParentsMemberFilter} + * + * @author Ilya.Kazakevich + */ +public class PyCustomType implements PyClassLikeType, Predicate { + + @NotNull + private final List myTypesToMimic = new ArrayList(); + + @Nullable + private final ParentsMemberFilter myFilter; + + private final boolean myInstanceType; + + + /** + * @param filter filter to filter methods from classes (may be null to do no filtering) + * @param instanceType if true, then this class implements instance (it reports it is not definition and returns "this + * for {@link #toInstance()} call). + * @param typesToMimic types to "mimic": delegate calls to (must be one at least!) + */ + public PyCustomType(@Nullable final ParentsMemberFilter filter, + final boolean instanceType, + @NotNull final PyClassLikeType... typesToMimic) { + Preconditions.checkArgument(typesToMimic.length > 0, "Provide at least one class"); + myFilter = filter; + myTypesToMimic.addAll(Arrays.asList(typesToMimic)); + myInstanceType = instanceType; + } + + /** + * @return class we mimic (if any). Check class manual for more info. + */ + @NotNull + public final List getTypesToMimic() { + return Collections.unmodifiableList(myTypesToMimic); + } + + @Override + public final boolean isDefinition() { + return !myInstanceType; + } + + @Override + public final PyClassLikeType toInstance() { + return myInstanceType ? this : new PyCustomType(myFilter, true, myTypesToMimic.toArray(new PyClassLikeType[myTypesToMimic.size()])); + } + + + @Nullable + @Override + public final String getClassQName() { + return null; + } + + @NotNull + @Override + public final List getSuperClassTypes(@NotNull final TypeEvalContext context) { + return Collections.emptyList(); + } + + @Nullable + @Override + public final List resolveMember(@NotNull final String name, + @Nullable final PyExpression location, + @NotNull final AccessDirection direction, + @NotNull final PyResolveContext resolveContext, + final boolean inherited) { + final List globalResult = new ArrayList(); + + // Delegate calls to classes, we mimic but filter if filter is set. + for (final PyClassLikeType parentType : myTypesToMimic) { + final List results = parentType.resolveMember(name, location, direction, resolveContext, inherited); + if (results != null) { + globalResult.addAll(Collections2.filter(results, this)); + } + } + return globalResult; + } + + @Override + public final boolean isValid() { + return true; + } + + @Nullable + @Override + public final PyClassLikeType getMetaClassType(@NotNull final TypeEvalContext context, final boolean inherited) { + return null; + } + + @Override + public final boolean isCallable() { + return true; // We do not know, actually + } + + @Nullable + @Override + public final PyType getReturnType(@NotNull final TypeEvalContext context) { + return (myInstanceType ? null : toInstance()); + } + + @Nullable + @Override + public final PyType getCallType(@NotNull final TypeEvalContext context, @NotNull final PyCallSiteExpression callSite) { + return getReturnType(context); + } + + @Nullable + @Override + public final List getParameters(@NotNull final TypeEvalContext context) { + return null; + } + + @Nullable + @Override + public final List resolveMember(@NotNull final String name, + @Nullable final PyExpression location, + @NotNull final AccessDirection direction, + @NotNull final PyResolveContext resolveContext) { + return resolveMember(name, location, direction, resolveContext, true); + } + + @Override + public final Object[] getCompletionVariants(final String completionPrefix, final PsiElement location, final ProcessingContext context) { + final Collection lookupElements = new ArrayList(); + + for (final PyClassLikeType parentType : myTypesToMimic) { + lookupElements.addAll(Collections2.filter(Arrays.asList(parentType.getCompletionVariants(completionPrefix, location, context)), + new CompletionFilter())); + } + return lookupElements.toArray(new Object[lookupElements.size()]); + } + + + @Nullable + @Override + public final String getName() { + final Collection classNames = new ArrayList(myTypesToMimic.size()); + for (final PyClassLikeType type : myTypesToMimic) { + String name = type.getName(); + if (name == null && (type instanceof PyClassType)) { + name = ((PyClassType)type).getPyClass().getName(); + } + if (name != null) { + classNames.add(name); + } + } + + + return PyBundle.message("custom.type.mimic.name", StringUtil.join(classNames, ",")); + } + + @Override + public final boolean isBuiltin() { + return false; + } + + @Override + public final void assertValid(final String message) { + for (final PyClassLikeType type : myTypesToMimic) { + type.assertValid(message); + } + } + + + @Override + public final boolean apply(@Nullable final RatedResolveResult input) { + if (input == null) { + return false; + } + if (myFilter == null) { + return true; // No need to check + } + final PyElement pyElement = PyUtil.as(input.getElement(), PyElement.class); + if (pyElement == null) { + return false; + } + return myFilter.acceptMember(pyElement); + } + + public interface ParentsMemberFilter { + boolean acceptMember(@NotNull PyElement element); + } + + /** + * Predicate that filters completion using {@link #myFilter} + */ + private class CompletionFilter implements Predicate { + @Override + public final boolean apply(@Nullable final Object input) { + if (input == null) { + return false; + } + if (myFilter == null) { + return true; // No need to check + } + if (!(input instanceof LookupElement)) { + return true; // Do not know how to check + } + final PyElement pyElement = PyUtil.as(((LookupElement)input).getPsiElement(), PyElement.class); + if (pyElement == null) { + return false; + } + return myFilter.acceptMember(pyElement); + } + } +} diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index 781ad21bb88b..693b8dce7a47 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -38,7 +38,7 @@ import com.intellij.util.PlatformUtils; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; -import com.jetbrains.python.PyCustomMembersType; +import com.jetbrains.python.PyCustomType; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; import com.jetbrains.python.codeInsight.PyCustomMember; @@ -607,13 +607,15 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } /** - * Checks if type is custom-member based and has custom member with certain name + * Checks if type is custom type and has custom member with certain name * @param refName name to check * @param type type * @return true if has one */ private static boolean isHasCustomMember(@NotNull final String refName, @NotNull final PyType type) { - return (type instanceof PyCustomMembersType) && ((PyCustomMembersType)type).hasMember(refName); + // TODO: check + return false; + /*return (type instanceof PyCustomType) && ((PyCustomType)type).hasMember(refName);*/ } /** @@ -713,11 +715,15 @@ public class PyUnresolvedReferencesInspection extends PyInspection { return true; } } - if (type instanceof PyCustomMembersType) { + if (type instanceof PyCustomType) { // Skip custom member types that mimics another class with fuzzy parents - PyClassType mimic = ((PyCustomMembersType)type).getTypeToMimic(); - if (mimic != null && PyUtil.hasUnresolvedAncestors(mimic.getPyClass(), myTypeEvalContext)) { - return true; + for (final PyClassLikeType mimic : ((PyCustomType)type).getTypesToMimic()) { + if (!(mimic instanceof PyClassType)) { + continue; + } + if (PyUtil.hasUnresolvedAncestors(((PyClassType)mimic).getPyClass(), myTypeEvalContext)) { + return true; + } } } if (type instanceof PyClassTypeImpl) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java index c0ac149f527f..13c8a417c8ca 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java +++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java @@ -360,6 +360,9 @@ public class PyCallExpressionHelper { } } } + else if (qtype instanceof PyClassLikeType) { + return ((PyClassLikeType)qtype).isDefinition(); //Any definition means callable is classmethod + } return false; } @@ -522,6 +525,10 @@ public class PyCallExpressionHelper { final Callable callable = (Callable)target; return Ref.create(callable.getCallType(context, call)); } + /*PyCallExpression.PyMarkedCallee markedCallee = call.resolveCallee(PyResolveContext.defaultContext().withTypeEvalContext(context)); + if (markedCallee != null) { + return Ref.create(markedCallee.getCallable().getCallType(context, call)); + }*/ return null; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index c03fe346b6e3..29e590bac898 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -1219,6 +1219,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla } else { for (PyExpression expression : getSuperClassExpressions()) { + context.getType(expression); expression = unfoldClass(expression); if (expression instanceof PyKeywordArgument) { continue; diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java index 37e2d63f9f99..fc60a5f056ba 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java @@ -420,7 +420,9 @@ public class PyReferenceExpressionImpl extends PyElementImpl implements PyRefere @Nullable PsiElement anchor) { for (PyTypeProvider provider : Extensions.getExtensions(PyTypeProvider.EP_NAME)) { final PyType result = provider.getReferenceType(target, context, anchor); - if (result != null) return result; + if (result != null) { + return result; + } } return null; diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index a7b0d548ea23..79fdf3c51c3d 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -32,6 +32,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.hash.HashMap; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.PyCustomMember; import com.jetbrains.python.codeInsight.PyCustomMemberUtils; @@ -138,7 +139,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } resolving.add(key); try { - return doResolveMember(name, location, direction, resolveContext, inherited); + return doResolveMember(name, location, direction, resolveContext, inherited, null); } finally { resolving.remove(key); @@ -146,14 +147,16 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } @Nullable - private List doResolveMember(@NotNull String name, - @Nullable PyExpression location, - @NotNull AccessDirection direction, - @NotNull PyResolveContext resolveContext, - boolean inherited) { + public List doResolveMember(@NotNull String name, + @Nullable PyExpression location, + @NotNull AccessDirection direction, + @NotNull PyResolveContext resolveContext, + boolean inherited, + @Nullable PyClassMembersProvider providerToSkip) { final TypeEvalContext context = resolveContext.getTypeEvalContext(); PsiElement classMember = - resolveByOverridingMembersProviders(this, name, location); //overriding members provers have priority to normal resolve + resolveByOverridingMembersProviders(this, name, location, + providerToSkip); //overriding members provers have priority to normal resolve if (classMember != null) { return ResolveResultList.to(classMember); } @@ -188,7 +191,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return ResolveResultList.to(classMember); } - classMember = resolveByOverridingAncestorsMembersProviders(this, name, location); + classMember = resolveByOverridingAncestorsMembersProviders(this, name, location, providerToSkip); if (classMember != null) { return ResolveResultList.to(classMember); } @@ -225,7 +228,8 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { if (inherited) { classMember = - resolveByMembersProviders(this, name, location); //ask providers after real class introspection as providers have less priority + resolveByMembersProviders(this, name, location, + providerToSkip); //ask providers after real class introspection as providers have less priority } if (classMember != null) { @@ -236,7 +240,7 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { for (PyClassLikeType type : myClass.getAncestorTypes(context)) { if (type instanceof PyClassType) { final PyClass pyClass = ((PyClassType)type).getPyClass(); - PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location); + PsiElement superMember = resolveByMembersProviders(new PyClassTypeImpl(pyClass, isDefinition()), name, location, providerToSkip); if (superMember != null) { return ResolveResultList.to(superMember); @@ -345,8 +349,13 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } @Nullable - private static PsiElement resolveByMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location) { + private static PsiElement resolveByMembersProviders(PyClassType aClass, String name, + @Nullable PsiElement location, + @Nullable PyClassMembersProvider providerToSkip) { for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { + if (provider == providerToSkip) { + continue; + } final PsiElement resolveResult = provider.resolveMember(aClass, name, location); if (resolveResult != null) return resolveResult; } @@ -355,9 +364,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } @Nullable - private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location) { + private static PsiElement resolveByOverridingMembersProviders(PyClassType aClass, String name, @Nullable PsiElement location, + @Nullable PyClassMembersProvider providerToSkip) { for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { - if (provider instanceof PyOverridingClassMembersProvider) { + if (provider instanceof PyOverridingClassMembersProvider && provider != providerToSkip) { final PsiElement resolveResult = provider.resolveMember(aClass, name, location); if (resolveResult != null) return resolveResult; } @@ -367,9 +377,10 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } @Nullable - private static PsiElement resolveByOverridingAncestorsMembersProviders(PyClassType type, String name, @Nullable PyExpression location) { + private static PsiElement resolveByOverridingAncestorsMembersProviders(PyClassType type, String name, @Nullable PyExpression location, + @Nullable PyClassMembersProvider providerToSkip) { for (PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { - if (provider instanceof PyOverridingAncestorsClassMembersProvider) { + if (provider instanceof PyOverridingAncestorsClassMembersProvider && !(provider == providerToSkip)) { final PsiElement resolveResult = provider.resolveMember(type, name, location); if (resolveResult != null) return resolveResult; } @@ -409,28 +420,50 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { if (namesAlready == null) { namesAlready = new HashSet(); } - List ret = new ArrayList(); + + // TODO: Doc + final Map> usedNames = new HashMap>(); + boolean suppressParentheses = context.get(CTX_SUPPRESS_PARENTHESES) != null; - addOwnClassMembers(location, namesAlready, suppressParentheses, ret); + addOwnClassMembers(location, namesAlready, suppressParentheses, usedNames); + namesAlready.addAll(usedNames.keySet()); PsiFile origin = (location != null) ? CompletionUtil.getOriginalOrSelf(location) .getContainingFile() : null; final TypeEvalContext typeEvalContext = TypeEvalContext.codeCompletion(myClass.getProject(), origin); - addInheritedMembers(prefix, location, namesAlready, context, ret, typeEvalContext); + final List inheritedMembers = addInheritedMembers(prefix, location, namesAlready, context, usedNames, typeEvalContext); + namesAlready.addAll(usedNames.keySet()); + + // Move to func + // TODO: Override only if Overriding // from providers for (final PyClassMembersProvider provider : Extensions.getExtensions(PyClassMembersProvider.EP_NAME)) { for (final PyCustomMember member : provider.getMembers(this, location)) { final String name = member.getName(); - if (!namesAlready.contains(name)) { - ret.add(PyCustomMemberUtils.toLookUpElement(member, getName())); + final LookupElementBuilder element = PyCustomMemberUtils.toLookUpElement(member, getName()); + + final Pair usedNameInfo = usedNames.get(name); + // TODO: Doc + if (usedNameInfo == null || + (usedNameInfo.first == ElementType.INHERITED && provider instanceof PyOverridingAncestorsClassMembersProvider) || + (usedNameInfo.first == ElementType.OWN && provider instanceof PyOverridingClassMembersProvider)) { + usedNames.put(name, Pair.create(ElementType.BY_PROVIDER, element)); + } else { + int i = 1; } } } + + final List ret = new ArrayList(getElementsFromUsedNames(usedNames)); + namesAlready.addAll(usedNames.keySet()); + ret.addAll(inheritedMembers); + + if (!myClass.isNewStyleClass()) { final PyBuiltinCache cache = PyBuiltinCache.getInstance(myClass); final PyClassType classobjType = cache.getOldstyleClassobjType(); @@ -449,7 +482,11 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return ret.toArray(); } - private void addOwnClassMembers(PsiElement expressionHook, Set namesAlready, boolean suppressParentheses, List ret) { + + private void addOwnClassMembers(PsiElement expressionHook, + Set namesAlready, + boolean suppressParentheses, + @NotNull final Map> usedNames) { PyClass containingClass = PsiTreeUtil.getParentOfType(expressionHook, PyClass.class); if (containingClass != null) { containingClass = CompletionUtil.getOriginalElement(containingClass); @@ -475,12 +512,12 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { if (namesAlready.contains(name)) continue; if (!withinOurClass && isClassPrivate(name)) continue; namesAlready.add(name); - ret.add(le); + usedNames.put(name, Pair.create(ElementType.OWN, le)); } if (slots != null) { for (String name : slots) { if (!namesAlready.contains(name)) { - ret.add(LookupElementBuilder.create(name)); + usedNames.put(name, Pair.create(ElementType.OWN, LookupElementBuilder.create(name))); } } } @@ -494,12 +531,14 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return false; } - private void addInheritedMembers(String name, + @NotNull + private List addInheritedMembers(String name, PsiElement expressionHook, Set namesAlready, ProcessingContext context, - List ret, + @NotNull final Map> usedNames, @NotNull TypeEvalContext typeEvalContext) { + final List ret = new ArrayList(); for (PyExpression expression : myClass.getSuperClassExpressions()) { final PsiReference reference = expression.getReference(); PsiElement element = null; @@ -521,13 +560,14 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { for (Object ob : ancestry) { String inheritedName = ob.toString(); if (!namesAlready.contains(inheritedName) && !isClassPrivate(inheritedName)) { - ret.add(ob); + usedNames.put(inheritedName, Pair.create(ElementType.INHERITED, ob)); namesAlready.add(inheritedName); } } ContainerUtil.addAll(ret, ancestry); } } + return ret; } private static boolean isClassPrivate(String lookup_string) { @@ -607,4 +647,20 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } return new PyClassTypeImpl(pyClass, isDefinition); } + + // TOOD: Doc + private static List getElementsFromUsedNames(@NotNull final Map> usedNames) { + final List ret = new ArrayList(); + for (final Pair objectPair : usedNames.values()) { + ret.add(objectPair.second); + } + return ret; + } + + // TODO: Doc + private enum ElementType { + OWN, + INHERITED, + BY_PROVIDER + } } diff --git a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java index 4eb1a1118e16..422d5408e2b3 100644 --- a/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java +++ b/xml/impl/src/com/intellij/xml/util/XmlReferenceContributor.java @@ -18,12 +18,12 @@ package com.intellij.xml.util; import com.intellij.codeInsight.daemon.impl.analysis.encoding.XmlEncodingReferenceProvider; import com.intellij.html.impl.providers.MicrodataReferenceProvider; import com.intellij.html.impl.util.MicrodataUtil; +import com.intellij.openapi.paths.WebReference; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.*; import com.intellij.psi.filters.*; import com.intellij.psi.filters.position.NamespaceFilter; import com.intellij.psi.filters.position.ParentElementFilter; -import com.intellij.psi.impl.UrlPsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.*; import com.intellij.psi.xml.*; import com.intellij.util.ProcessingContext; @@ -116,7 +116,7 @@ public class XmlReferenceContributor extends PsiReferenceContributor { @Override public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { - return new PsiReference[] { new UrlPsiReference(element) }; + return new PsiReference[] { new WebReference(element) }; } }); }