mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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<VirtualFile> 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);
|
||||
|
||||
+1
-4
@@ -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) {
|
||||
|
||||
+19
-3
@@ -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
|
||||
|
||||
@@ -215,7 +215,9 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
@Override
|
||||
public Collection<PsiElement> 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()
|
||||
|
||||
+6
@@ -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;
|
||||
|
||||
@@ -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<String> names = new HashSet<String>();
|
||||
cache.getAllClassNames(names);
|
||||
|
||||
+2
@@ -1,4 +1,6 @@
|
||||
import <symbolName descr="null" type="CLASS_NAME">java.io</symbolName>.*; // highlight on demand import as class name
|
||||
import static <symbolName descr="null" type="CLASS_NAME">java.io.File</symbolName>.<symbolName descr="null" type="STATIC_FINAL_FIELD">pathSeparator</symbolName>;
|
||||
import static <symbolName descr="null" type="CLASS_NAME">java.io.File</symbolName>.*;
|
||||
|
||||
class <symbolName descr="null" type="CLASS_NAME">a</symbolName> {
|
||||
void <symbolName descr="null" type="METHOD_DECLARATION">method</symbolName>() {
|
||||
|
||||
+1
-1
@@ -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),
|
||||
|
||||
+118
-61
@@ -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
|
||||
|
||||
@@ -26,6 +26,10 @@ import org.jetbrains.annotations.NotNull;
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class WebReference extends PsiReferenceBase<PsiElement> {
|
||||
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<PsiElement> {
|
||||
return new MyFakePsiElement();
|
||||
}
|
||||
|
||||
protected String getUrl() {
|
||||
return getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
@@ -43,25 +51,31 @@ public class WebReference extends PsiReferenceBase<PsiElement> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
-13
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PsiElement> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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=<b>A new version of {0} is available!</b>
|
||||
updates.new.version.available=<b>A new version of {0} is <a href=\"#\">available</a>!</b>
|
||||
updates.current.version=Current version:
|
||||
updates.available.version=New version:
|
||||
updates.patch.label=Patch size:
|
||||
|
||||
+5
@@ -40,6 +40,11 @@ public abstract class ServerRuntimeInstance<D extends DeploymentConfiguration> {
|
||||
|
||||
void addDeployment(@NotNull String deploymentName, @Nullable DeploymentRuntime deploymentRuntime);
|
||||
|
||||
void addDeployment(@NotNull String deploymentName,
|
||||
@Nullable DeploymentRuntime deploymentRuntime,
|
||||
@Nullable DeploymentStatus deploymentStatus,
|
||||
@Nullable String deploymentStatusText);
|
||||
|
||||
void succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-1
@@ -177,7 +177,19 @@ public class ServerConnectionImpl<D extends DeploymentConfiguration> 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
|
||||
|
||||
+12
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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();
|
||||
}
|
||||
|
||||
+2
-16
@@ -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<FileType> result = new ArrayList<FileType>();
|
||||
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());
|
||||
|
||||
|
||||
+1
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -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() {
|
||||
|
||||
@@ -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<String> lines = new ArrayList<String>();
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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() {
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<grid id="4d15a" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="4d15a" layout-manager="GridLayoutManager" row-count="7" column-count="8" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -99,27 +99,9 @@
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="9d661" class="javax.swing.JCheckBox" binding="myAutoUpdateIfPushRejected">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<iconTextGap value="4"/>
|
||||
<text value="Auto-update if &push of the current branch was rejected"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="2e80d" class="com.intellij.ui.components.JBCheckBox" binding="mySyncControl">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="sync.setting"/>
|
||||
<toolTipText value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5a98" class="javax.swing.JCheckBox" binding="myAutoCommitOnCherryPick">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="1" column="0" row-span="1" col-span="8" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<iconTextGap value="4"/>
|
||||
@@ -128,7 +110,7 @@
|
||||
</component>
|
||||
<component id="1ad55" class="com.intellij.ui.components.JBCheckBox" binding="myWarnAboutCrlf" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="2" column="0" row-span="1" col-span="8" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Warn if &CRLF line separators are about to be committed"/>
|
||||
@@ -136,7 +118,7 @@
|
||||
</component>
|
||||
<component id="29d5c" class="javax.swing.JCheckBox" binding="myWarnAboutDetachedHead">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="3" column="0" row-span="1" col-span="8" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
@@ -145,7 +127,7 @@
|
||||
</component>
|
||||
<component id="885e3" class="javax.swing.JCheckBox" binding="myEnableForcePush">
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<selected value="true"/>
|
||||
@@ -154,7 +136,7 @@
|
||||
</component>
|
||||
<component id="b0317" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myProtectedBranchesButton" custom-create="true" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="5" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="7" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
@@ -162,12 +144,45 @@
|
||||
</component>
|
||||
<component id="e7b92" class="com.intellij.ui.components.JBLabel" binding="myProtectedBranchesLabel">
|
||||
<constraints>
|
||||
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
<grid row="6" column="6" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value="Protected branches:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="2e80d" class="com.intellij.ui.components.JBCheckBox" binding="mySyncControl">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="8" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="sync.setting"/>
|
||||
<toolTipText value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="5884f" class="com.intellij.ui.components.JBLabel">
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<labelFor value="840a6"/>
|
||||
<text value="Update method:"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="9d661" class="javax.swing.JCheckBox" binding="myAutoUpdateIfPushRejected">
|
||||
<constraints>
|
||||
<grid row="5" column="0" row-span="1" col-span="8" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<iconTextGap value="4"/>
|
||||
<text value="Auto-update if &push of the current branch was rejected"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="840a6" class="javax.swing.JComboBox" binding="myUpdateMethodComboBox" custom-create="true" default-binding="true">
|
||||
<constraints>
|
||||
<grid row="4" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
</children>
|
||||
</grid>
|
||||
</children>
|
||||
|
||||
@@ -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>(UpdateMethod.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
|
||||
public UpdateChangesPolicy UPDATE_CHANGES_POLICY = UpdateChangesPolicy.STASH;
|
||||
public UpdateMethod UPDATE_TYPE = UpdateMethod.BRANCH_DEFAULT;
|
||||
public boolean PUSH_AUTO_UPDATE = false;
|
||||
public boolean PUSH_UPDATE_ALL_ROOTS = true;
|
||||
public Value ROOT_SYNC = Value.NOT_DECIDED;
|
||||
public String RECENT_GIT_ROOT_PATH = null;
|
||||
public Map<String, String> RECENT_BRANCH_BY_REPOSITORY = new HashMap<String, String>();
|
||||
@@ -96,8 +97,9 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
|
||||
return PeriodicalTasksCloser.getInstance().safeGetService(project, GitVcsSettings.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public UpdateMethod getUpdateType() {
|
||||
return myState.UPDATE_TYPE;
|
||||
return ObjectUtils.notNull(myState.UPDATE_TYPE, UpdateMethod.BRANCH_DEFAULT);
|
||||
}
|
||||
|
||||
public void setUpdateType(UpdateMethod updateType) {
|
||||
@@ -146,6 +148,14 @@ public class GitVcsSettings implements PersistentStateComponent<GitVcsSettings.S
|
||||
myState.PUSH_AUTO_UPDATE = autoUpdate;
|
||||
}
|
||||
|
||||
public boolean shouldUpdateAllRootsIfPushRejected() {
|
||||
return myState.PUSH_UPDATE_ALL_ROOTS;
|
||||
}
|
||||
|
||||
public void setUpdateAllRootsIfPushRejected(boolean updateAllRoots) {
|
||||
myState.PUSH_UPDATE_ALL_ROOTS = updateAllRoots;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Value getSyncSetting() {
|
||||
return myState.ROOT_SYNC;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package git4idea.config;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
/**
|
||||
* The type of update to perform
|
||||
*/
|
||||
@@ -30,5 +32,10 @@ public enum UpdateMethod {
|
||||
/**
|
||||
* Rebase local commits upon the fetched branch
|
||||
*/
|
||||
REBASE
|
||||
REBASE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return StringUtil.capitalize(StringUtil.toLowerCase(name().replace('_', ' ')));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ import git4idea.merge.MergeChangeCollector;
|
||||
import git4idea.repo.GitBranchTrackInfo;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import git4idea.settings.GitPushSettings;
|
||||
import git4idea.update.GitRebaseOverMergeProblem;
|
||||
import git4idea.update.GitUpdateProcess;
|
||||
import git4idea.update.GitUpdateResult;
|
||||
@@ -80,7 +79,6 @@ public class GitPushOperation {
|
||||
private final Git myGit;
|
||||
private final ProgressIndicator myProgressIndicator;
|
||||
private final GitVcsSettings mySettings;
|
||||
private final GitPushSettings myPushSettings;
|
||||
private final GitPlatformFacade myPlatformFacade;
|
||||
private final GitRepositoryManager myRepositoryManager;
|
||||
|
||||
@@ -97,7 +95,6 @@ public class GitPushOperation {
|
||||
myGit = ServiceManager.getService(Git.class);
|
||||
myProgressIndicator = ObjectUtils.notNull(ProgressManager.getInstance().getProgressIndicator(), new EmptyProgressIndicator());
|
||||
mySettings = GitVcsSettings.getInstance(myProject);
|
||||
myPushSettings = GitPushSettings.getInstance(myProject);
|
||||
myPlatformFacade = ServiceManager.getService(project, GitPlatformFacade.class);
|
||||
myRepositoryManager = ServiceManager.getService(myProject, GitRepositoryManager.class);
|
||||
|
||||
@@ -154,7 +151,7 @@ public class GitPushOperation {
|
||||
updateSettings = showDialogAndGetExitCode(result.rejected.keySet(), updateSettings,
|
||||
rebaseOverMergeProblemDetected.booleanValue());
|
||||
if (updateSettings != null) {
|
||||
savePushUpdateSettings(updateSettings);
|
||||
savePushUpdateSettings(updateSettings, rebaseOverMergeProblemDetected.booleanValue());
|
||||
}
|
||||
else {
|
||||
shouldUpdate = false;
|
||||
@@ -383,16 +380,18 @@ public class GitPushOperation {
|
||||
});
|
||||
}
|
||||
|
||||
private void savePushUpdateSettings(@NotNull PushUpdateSettings settings) {
|
||||
private void savePushUpdateSettings(@NotNull PushUpdateSettings settings, boolean rebaseOverMergeDetected) {
|
||||
UpdateMethod updateMethod = settings.getUpdateMethod();
|
||||
myPushSettings.setUpdateAllRoots(settings.shouldUpdateAllRoots());
|
||||
myPushSettings.setUpdateMethod(updateMethod);
|
||||
mySettings.setUpdateAllRootsIfPushRejected(settings.shouldUpdateAllRoots());
|
||||
if (!rebaseOverMergeDetected) { // don't overwrite explicit "rebase" with temporary "merge" caused by merge commits
|
||||
mySettings.setUpdateType(updateMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PushUpdateSettings readPushUpdateSettings() {
|
||||
boolean updateAllRoots = myPushSettings.shouldUpdateAllRoots();
|
||||
UpdateMethod updateMethod = myPushSettings.getUpdateMethod();
|
||||
boolean updateAllRoots = mySettings.shouldUpdateAllRootsIfPushRejected();
|
||||
UpdateMethod updateMethod = mySettings.getUpdateType();
|
||||
return new PushUpdateSettings(updateAllRoots, updateMethod);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,18 +73,28 @@ class GitRejectedPushUpdateDialog extends DialogWrapper {
|
||||
|
||||
myMergeAction = new MergeAction();
|
||||
myRebaseAction = new RebaseAction();
|
||||
getDefaultAction(initialSettings.getUpdateMethod()).putValue(DEFAULT_ACTION, Boolean.TRUE);
|
||||
getCancelAction().putValue(FOCUSED_ACTION, Boolean.TRUE);
|
||||
|
||||
setDefaultAndFocusedActions(initialSettings.getUpdateMethod());
|
||||
init();
|
||||
setTitle("Push Rejected");
|
||||
}
|
||||
|
||||
private AbstractAction getDefaultAction(@Nullable UpdateMethod updateMethod) {
|
||||
if (updateMethod == UpdateMethod.REBASE && !myRebaseOverMergeProblemDetected) {
|
||||
return myRebaseAction;
|
||||
private void setDefaultAndFocusedActions(@Nullable UpdateMethod updateMethod) {
|
||||
Action defaultAction;
|
||||
Action focusedAction;
|
||||
if (myRebaseOverMergeProblemDetected) {
|
||||
defaultAction = myMergeAction;
|
||||
focusedAction = getCancelAction();
|
||||
}
|
||||
return myMergeAction;
|
||||
else if (updateMethod == UpdateMethod.REBASE) {
|
||||
defaultAction = myRebaseAction;
|
||||
focusedAction = myMergeAction;
|
||||
}
|
||||
else {
|
||||
defaultAction = myMergeAction;
|
||||
focusedAction = myRebaseAction;
|
||||
}
|
||||
defaultAction.putValue(DEFAULT_ACTION, Boolean.TRUE);
|
||||
focusedAction.putValue(FOCUSED_ACTION, Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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 git4idea.settings;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import git4idea.config.UpdateMethod;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
@State(name = "Git.Push.Settings", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)})
|
||||
public class GitPushSettings implements PersistentStateComponent<GitPushSettings.State> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Boolean> rebaseOverMergeProblemDetected = Ref.create(false);
|
||||
myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler<GitRejectedPushUpdateDialog>() {
|
||||
@@ -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<Boolean> 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<Boolean> rebaseOverMergeProblemDetected = Ref.create(false);
|
||||
myDialogManager.registerDialogHandler(GitRejectedPushUpdateDialog.class, new TestDialogHandler<GitRejectedPushUpdateDialog>() {
|
||||
@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);
|
||||
|
||||
@@ -56,6 +56,12 @@ public class JUnitConfiguration extends ModuleBasedConfiguration<JavaRunConfigur
|
||||
@NonNls public static final String TEST_DIRECTORY = "directory";
|
||||
@NonNls public static final String TEST_CATEGORY = "category";
|
||||
@NonNls public static final String TEST_METHOD = "method";
|
||||
|
||||
//fork modes
|
||||
@NonNls public static final String FORK_NONE = "none";
|
||||
@NonNls public static final String FORK_METHOD = "method";
|
||||
@NonNls public static final String FORK_KLASS = "class";
|
||||
|
||||
@NonNls private static final String PATTERN_EL_NAME = "pattern";
|
||||
@NonNls public static final String TEST_PATTERN = PATTERN_EL_NAME;
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@ public class TestClassConfigurationProducer extends JUnitConfigurationProducer {
|
||||
final Module originalModule = configuration.getConfigurationModule().getModule();
|
||||
configuration.beClassConfiguration(testClass);
|
||||
configuration.restoreOriginalModule(originalModule);
|
||||
final String forkMode = configuration.getForkMode();
|
||||
if (JUnitConfiguration.FORK_KLASS.equals(forkMode)) {
|
||||
configuration.setForkMode(JUnitConfiguration.FORK_NONE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ public class TestMethodConfigurationProducer extends JUnitConfigurationProducer
|
||||
configuration.beMethodConfiguration(methodLocation);
|
||||
configuration.restoreOriginalModule(originalModule);
|
||||
JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, contextLocation);
|
||||
configuration.setForkMode(JUnitConfiguration.FORK_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+5
-9
@@ -53,7 +53,6 @@ import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.TextFieldCompletionProvider;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.TIntArrayList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -105,11 +104,8 @@ public class JUnitConfigurable extends SettingsEditor<JUnitConfiguration> 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<JUnitConfiguration> 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<JUnitConfiguration> 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<JUnitConfiguration> 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);
|
||||
|
||||
+2
-2
@@ -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<String> {
|
||||
}
|
||||
|
||||
protected PsiReference createReference(PsiElement element, String text, TextRange range) {
|
||||
return new UrlPsiReference(element);
|
||||
return new WebReference(element, range);
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -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 ResolvingConverter<String
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] createReferences(GenericDomValue value, final PsiElement element, final ConvertContext context) {
|
||||
return new PsiReference[]{new UrlPsiReference(element) {
|
||||
|
||||
return new PsiReference[]{new WebReference(element) {
|
||||
@NotNull
|
||||
@Override
|
||||
public Object[] getVariants() {
|
||||
|
||||
+71
-63
@@ -8,9 +8,11 @@ import com.intellij.execution.process.KillableColoredProcessHandler;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ProjectComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
@@ -23,6 +25,8 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.HyperlinkAdapter;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.jetbrains.python.PythonHelpersLocator;
|
||||
import com.jetbrains.python.packaging.PyPackage;
|
||||
import com.jetbrains.python.packaging.PyPackageManager;
|
||||
@@ -35,11 +39,12 @@ import org.jetbrains.plugins.ipnb.format.cells.output.IpnbOutputCell;
|
||||
import org.jetbrains.plugins.ipnb.protocol.IpnbConnection;
|
||||
import org.jetbrains.plugins.ipnb.protocol.IpnbConnectionListenerBase;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -67,7 +72,13 @@ public final class IpnbConnectionManager implements ProjectComponent {
|
||||
if (!myKernels.containsKey(path)) {
|
||||
String url = IpnbSettings.getInstance(myProject).getURL();
|
||||
if (StringUtil.isEmptyOrSpaces(url)) {
|
||||
showWarning(fileEditor, "Please, specify IPython Notebook URL in <a href=\"\">Settings->IPython Notebook</a>");
|
||||
showWarning(fileEditor, "Please, specify IPython Notebook URL in <a href=\"\">Settings->Tools->IPython Notebook</a>",
|
||||
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", "", "<html>IPython notebook started at <a href=\"" + url +
|
||||
"\">" + url + "</a></html>", 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", "", "<html>IPython notebook started at <a href=\"" + finalUrl +
|
||||
"\">" + finalUrl + "</a></html>", 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 <a href=\"\">Settings->Tools->IPython Notebook</a>",
|
||||
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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public interface PyClassMembersProvider {
|
||||
ExtensionPointName<PyClassMembersProvider> EP_NAME = ExtensionPointName.create("Pythonid.pyClassMembersProvider");
|
||||
|
||||
@NotNull
|
||||
Collection<PyCustomMember> getMembers(PyClassType clazz, @Nullable PsiElement location);
|
||||
Collection<PyCustomMember> getMembers(final PyClassType clazz, PsiElement location);
|
||||
|
||||
@Nullable
|
||||
PsiElement resolveMember(PyClassType clazz, String name, @Nullable PsiElement location);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
@@ -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<String, PyCustomMember> 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<String, PyCustomMember>(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<PyClassLikeType> getSuperClassTypes(@NotNull TypeEvalContext context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> 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<PyCallableParameter> getParameters(@NotNull TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<? extends RatedResolveResult> 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<LookupElement> lookupElements = new ArrayList<LookupElement>(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);
|
||||
}
|
||||
}
|
||||
@@ -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 <strong>mimics</strong> 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<RatedResolveResult> {
|
||||
|
||||
@NotNull
|
||||
private final List<PyClassLikeType> myTypesToMimic = new ArrayList<PyClassLikeType>();
|
||||
|
||||
@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<PyClassLikeType> 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<PyClassLikeType> getSuperClassTypes(@NotNull final TypeEvalContext context) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public final List<? extends RatedResolveResult> resolveMember(@NotNull final String name,
|
||||
@Nullable final PyExpression location,
|
||||
@NotNull final AccessDirection direction,
|
||||
@NotNull final PyResolveContext resolveContext,
|
||||
final boolean inherited) {
|
||||
final List<RatedResolveResult> globalResult = new ArrayList<RatedResolveResult>();
|
||||
|
||||
// Delegate calls to classes, we mimic but filter if filter is set.
|
||||
for (final PyClassLikeType parentType : myTypesToMimic) {
|
||||
final List<? extends RatedResolveResult> 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<PyCallableParameter> getParameters(@NotNull final TypeEvalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public final List<? extends RatedResolveResult> 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<Object> lookupElements = new ArrayList<Object>();
|
||||
|
||||
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<String> classNames = new ArrayList<String>(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<Object> {
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-7
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1219,6 +1219,7 @@ public class PyClassImpl extends PyBaseElementImpl<PyClassStub> implements PyCla
|
||||
}
|
||||
else {
|
||||
for (PyExpression expression : getSuperClassExpressions()) {
|
||||
context.getType(expression);
|
||||
expression = unfoldClass(expression);
|
||||
if (expression instanceof PyKeywordArgument) {
|
||||
continue;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<? extends RatedResolveResult> doResolveMember(@NotNull String name,
|
||||
@Nullable PyExpression location,
|
||||
@NotNull AccessDirection direction,
|
||||
@NotNull PyResolveContext resolveContext,
|
||||
boolean inherited) {
|
||||
public List<? extends RatedResolveResult> 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<String>();
|
||||
}
|
||||
List<Object> ret = new ArrayList<Object>();
|
||||
|
||||
// TODO: Doc
|
||||
final Map<String, Pair<ElementType, Object>> usedNames = new HashMap<String, Pair<ElementType, Object>>();
|
||||
|
||||
|
||||
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<Object> 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<ElementType, Object> 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.<ElementType, Object>create(ElementType.BY_PROVIDER, element));
|
||||
} else {
|
||||
int i = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final List<Object> ret = new ArrayList<Object>(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<String> namesAlready, boolean suppressParentheses, List<Object> ret) {
|
||||
|
||||
private void addOwnClassMembers(PsiElement expressionHook,
|
||||
Set<String> namesAlready,
|
||||
boolean suppressParentheses,
|
||||
@NotNull final Map<String, Pair<ElementType, Object>> 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.<ElementType, Object>create(ElementType.OWN, le));
|
||||
}
|
||||
if (slots != null) {
|
||||
for (String name : slots) {
|
||||
if (!namesAlready.contains(name)) {
|
||||
ret.add(LookupElementBuilder.create(name));
|
||||
usedNames.put(name, Pair.<ElementType, Object>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<Object> addInheritedMembers(String name,
|
||||
PsiElement expressionHook,
|
||||
Set<String> namesAlready,
|
||||
ProcessingContext context,
|
||||
List<Object> ret,
|
||||
@NotNull final Map<String, Pair<ElementType, Object>> usedNames,
|
||||
@NotNull TypeEvalContext typeEvalContext) {
|
||||
final List<Object> ret = new ArrayList<Object>();
|
||||
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<Object> getElementsFromUsedNames(@NotNull final Map<String, Pair<ElementType, Object>> usedNames) {
|
||||
final List<Object> ret = new ArrayList<Object>();
|
||||
for (final Pair<ElementType, Object> objectPair : usedNames.values()) {
|
||||
ret.add(objectPair.second);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: Doc
|
||||
private enum ElementType {
|
||||
OWN,
|
||||
INHERITED,
|
||||
BY_PROVIDER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user