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:
@@ -22,29 +22,19 @@ import com.intellij.debugger.engine.evaluation.*;
|
||||
import com.intellij.debugger.engine.evaluation.expression.*;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
|
||||
import com.intellij.debugger.impl.*;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx;
|
||||
import com.intellij.debugger.jdi.LocalVariableProxyImpl;
|
||||
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
|
||||
import com.intellij.debugger.ui.DebuggerExpressionComboBox;
|
||||
import com.intellij.debugger.ui.EditorEvaluationCommand;
|
||||
import com.intellij.debugger.ui.impl.DebuggerTreeRenderer;
|
||||
import com.intellij.debugger.ui.impl.watch.*;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorListenerAdapter;
|
||||
import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.ui.SimpleColoredComponent;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.xdebugger.frame.XValueModifier;
|
||||
import com.sun.jdi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
|
||||
/*
|
||||
@@ -255,14 +245,14 @@ public class JavaValueModifier extends XValueModifier {
|
||||
}
|
||||
}
|
||||
|
||||
private Value preprocessValue(EvaluationContextImpl context, Value value, Type varType) throws EvaluateException {
|
||||
private static Value preprocessValue(EvaluationContextImpl context, Value value, Type varType) throws EvaluateException {
|
||||
if (value != null && JAVA_LANG_STRING.equals(varType.name()) && !(value instanceof StringReference)) {
|
||||
String v = DebuggerUtilsEx.getValueAsString(context, value);
|
||||
String v = DebuggerUtils.getValueAsString(context, value);
|
||||
if (v != null) {
|
||||
value = context.getSuspendContext().getDebugProcess().getVirtualMachineProxy().mirrorOf(v);
|
||||
}
|
||||
}
|
||||
if(value instanceof DoubleValue) {
|
||||
if (value instanceof DoubleValue) {
|
||||
double dValue = ((DoubleValue) value).doubleValue();
|
||||
if(varType instanceof FloatType && Float.MIN_VALUE <= dValue && dValue <= Float.MAX_VALUE){
|
||||
value = context.getSuspendContext().getDebugProcess().getVirtualMachineProxy().mirrorOf((float)dValue);
|
||||
@@ -274,8 +264,7 @@ public class JavaValueModifier extends XValueModifier {
|
||||
value = (Value)new UnBoxingEvaluator(new IdentityEvaluator(value)).evaluate(context);
|
||||
}
|
||||
}
|
||||
else if (UnBoxingEvaluator.isTypeUnboxable(varType.name())) {
|
||||
// variable is not primitive and boxing/unboxing is applicable
|
||||
else if (varType instanceof ReferenceType) {
|
||||
if (value instanceof PrimitiveValue) {
|
||||
value = (Value)new BoxingEvaluator(new IdentityEvaluator(value)).evaluate(context);
|
||||
}
|
||||
|
||||
@@ -530,8 +530,19 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio
|
||||
return null;
|
||||
}
|
||||
final int line = Math.min(finalRangeBegin + 1, finalRangeEnd);
|
||||
final SourcePosition candidatePosition = positionLine == line? position : SourcePosition.createFromLine(position.getFile(), line);
|
||||
return classToFind.equals(JVMNameUtil.getClassAt(candidatePosition)) ? fromClass : null;
|
||||
Set<PsiClass> lineClasses = getLineClasses(position.getFile(), line);
|
||||
if (lineClasses.size() > 1) {
|
||||
// if there's more than one class on the line - try to match by name
|
||||
for (PsiClass aClass : lineClasses) {
|
||||
if (classToFind.equals(aClass)) {
|
||||
return fromClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!lineClasses.isEmpty()){
|
||||
return classToFind.equals(lineClasses.iterator().next())? fromClass : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+5
-3
@@ -650,10 +650,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return true;
|
||||
}
|
||||
|
||||
// track "x" property state only inside "if (getX() != null) ..."
|
||||
if (dfaLeft instanceof DfaVariableValue && ((DfaVariableValue)dfaLeft).containsCalls() && (!isNull(dfaRight) || !isNegated)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dfaLeft == dfaRight) {
|
||||
if (dfaLeft instanceof DfaVariableValue && ((DfaVariableValue)dfaLeft).containsCalls()) {
|
||||
return true;
|
||||
}
|
||||
return !isNegated;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -27,7 +27,6 @@ package com.intellij.codeInspection.dataFlow.instructions;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -126,7 +125,7 @@ public class MethodCallInstruction extends Instruction {
|
||||
|
||||
private boolean isPureCall() {
|
||||
if (myTargetMethod == null) return false;
|
||||
return ControlFlowAnalyzer.isPure(myTargetMethod) || PropertyUtil.isSimplePropertyGetter(myTargetMethod);
|
||||
return ControlFlowAnalyzer.isPure(myTargetMethod);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+16
-11
@@ -21,6 +21,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
|
||||
import com.intellij.psi.util.PropertyUtil;
|
||||
@@ -41,18 +42,21 @@ public class DfaExpressionFactory {
|
||||
|
||||
private static Condition<String> parseFalseGetters() {
|
||||
try {
|
||||
final Pattern pattern = Pattern.compile(Registry.stringValue("ide.dfa.getters.with.side.effects"));
|
||||
return new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String s) {
|
||||
return pattern.matcher(s).matches();
|
||||
}
|
||||
};
|
||||
String regex = Registry.stringValue("ide.dfa.getters.with.side.effects").trim();
|
||||
if (!StringUtil.isEmpty(regex)) {
|
||||
final Pattern pattern = Pattern.compile(regex);
|
||||
return new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String s) {
|
||||
return pattern.matcher(s).matches();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error(e);
|
||||
return Conditions.alwaysFalse();
|
||||
}
|
||||
return Conditions.alwaysFalse();
|
||||
}
|
||||
|
||||
private final DfaValueFactory myFactory;
|
||||
@@ -152,10 +156,11 @@ public class DfaExpressionFactory {
|
||||
return (PsiVariable)target;
|
||||
}
|
||||
if (target instanceof PsiMethod) {
|
||||
if (PropertyUtil.isSimplePropertyGetter((PsiMethod)target)) {
|
||||
String qName = PsiUtil.getMemberQualifiedName((PsiMethod)target);
|
||||
PsiMethod method = (PsiMethod)target;
|
||||
if (PropertyUtil.isSimplePropertyGetter(method) && !(method.getReturnType() instanceof PsiPrimitiveType)) {
|
||||
String qName = PsiUtil.getMemberQualifiedName(method);
|
||||
if (qName == null || !FALSE_GETTERS.value(qName)) {
|
||||
return (PsiMethod)target;
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
<orderEntry type="module" module-name="java-structure-view" exported="" />
|
||||
<orderEntry type="module" module-name="spellchecker" />
|
||||
<orderEntry type="library" name="nekohtml" level="project" />
|
||||
<orderEntry type="module" module-name="built-in-server" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
<setting name="state" value="1" />
|
||||
</Base>
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -17,9 +17,11 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.LambdaHighlightingUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
import static com.intellij.patterns.PsiJavaPatterns.psiElement;
|
||||
|
||||
@@ -28,14 +30,14 @@ public class Java18CompletionData extends Java15CompletionData {
|
||||
.afterLeaf(psiElement(JavaTokenType.DOUBLE_COLON));
|
||||
|
||||
@Override
|
||||
public void fillCompletions(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
public void fillCompletions(final CompletionParameters parameters, final Consumer<LookupElement> result) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
|
||||
if (!inComment(position)) {
|
||||
if (AFTER_DOUBLE_COLON.accepts(position)) {
|
||||
PsiMethodReferenceExpression parent = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiMethodReferenceExpression.class);
|
||||
TailType tail = parent != null && !LambdaHighlightingUtil.insertSemicolon(parent.getParent()) ? TailType.SEMICOLON : TailType.NONE;
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), tail));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), tail));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,7 +45,7 @@ public class Java18CompletionData extends Java15CompletionData {
|
||||
PsiElement scope = position.getParent();
|
||||
while (scope != null && !(scope instanceof PsiFile)) {
|
||||
if (scope instanceof PsiClass && ((PsiClass)scope).isInterface()) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.DEFAULT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.DEFAULT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
break;
|
||||
}
|
||||
scope = scope.getParent();
|
||||
|
||||
@@ -86,6 +86,4 @@ public class JavaAwareCompletionData extends CompletionData{
|
||||
}
|
||||
}
|
||||
|
||||
public void fillCompletions(CompletionParameters parameters, CompletionResultSet result) {
|
||||
}
|
||||
}
|
||||
|
||||
+24
-3
@@ -241,6 +241,8 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
|
||||
addKeywords(parameters, result);
|
||||
|
||||
addExpressionVariants(parameters, position, result);
|
||||
|
||||
Set<String> usedWords = addReferenceVariants(parameters, result, inheritors);
|
||||
|
||||
if (psiElement().inside(PsiLiteralExpression.class).accepts(position)) {
|
||||
@@ -264,6 +266,16 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
result.stopHere();
|
||||
}
|
||||
|
||||
private void addExpressionVariants(@NotNull CompletionParameters parameters, PsiElement position, CompletionResultSet result) {
|
||||
if (JavaSmartCompletionContributor.INSIDE_EXPRESSION.accepts(position) &&
|
||||
!JavaCompletionData.AFTER_DOT.accepts(position)) {
|
||||
JavaCompletionData.addExpectedTypeMembers(parameters, result);
|
||||
if (SameSignatureCallParametersProvider.IN_CALL_ARGUMENT.accepts(position)) {
|
||||
new SameSignatureCallParametersProvider().addCompletions(parameters, new ProcessingContext(), result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInJavaContext(PsiElement position) {
|
||||
return PsiUtilCore.findLanguageFromElement(position).isKindOf(JavaLanguage.INSTANCE);
|
||||
}
|
||||
@@ -382,17 +394,26 @@ public class JavaCompletionContributor extends CompletionContributor {
|
||||
return usedWords;
|
||||
}
|
||||
|
||||
private static void addKeywords(CompletionParameters parameters, CompletionResultSet result) {
|
||||
private static void addKeywords(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
Consumer<LookupElement> noMiddleMatches = new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
if (element.getLookupString().startsWith(result.getPrefixMatcher().getPrefix())) {
|
||||
result.addElement(element);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PsiElement position = parameters.getPosition();
|
||||
final Set<LookupElement> lookupSet = new LinkedHashSet<LookupElement>();
|
||||
final Set<CompletionVariant> keywordVariants = new HashSet<CompletionVariant>();
|
||||
final JavaCompletionData completionData = getCompletionData(PsiUtil.getLanguageLevel(position));
|
||||
completionData.addKeywordVariants(keywordVariants, position, parameters.getOriginalFile());
|
||||
completionData.completeKeywordsBySet(lookupSet, keywordVariants, position, result.getPrefixMatcher(), parameters.getOriginalFile());
|
||||
completionData.fillCompletions(parameters, result);
|
||||
completionData.fillCompletions(parameters, noMiddleMatches);
|
||||
|
||||
for (final LookupElement item : lookupSet) {
|
||||
result.addElement(item);
|
||||
noMiddleMatches.consume(item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.intellij.psi.jsp.JspElementType;
|
||||
import com.intellij.psi.templateLanguages.OuterLanguageElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
@@ -368,19 +369,19 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addStatementKeywords(CompletionResultSet variant, PsiElement position) {
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.SWITCH), TailTypes.SWITCH_LPARENTH));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.WHILE), TailTypes.WHILE_LPARENTH));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.DO), TailTypes.DO_LBRACE));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FOR), TailTypes.FOR_LPARENTH));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.IF), TailTypes.IF_LPARENTH));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.TRY), TailTypes.TRY_LBRACE));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.THROW), TailType.INSERT_SPACE));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.SYNCHRONIZED), TailTypes.SYNCHRONIZED_LPARENTH));
|
||||
private static void addStatementKeywords(Consumer<LookupElement> variant, PsiElement position) {
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.SWITCH), TailTypes.SWITCH_LPARENTH));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.WHILE), TailTypes.WHILE_LPARENTH));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.DO), TailTypes.DO_LBRACE));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.FOR), TailTypes.FOR_LPARENTH));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.IF), TailTypes.IF_LPARENTH));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.TRY), TailTypes.TRY_LBRACE));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.THROW), TailType.INSERT_SPACE));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.SYNCHRONIZED), TailTypes.SYNCHRONIZED_LPARENTH));
|
||||
|
||||
if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_4)) {
|
||||
variant.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.ASSERT), TailType.INSERT_SPACE));
|
||||
variant.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.ASSERT), TailType.INSERT_SPACE));
|
||||
}
|
||||
|
||||
TailType returnTail = getReturnTail(position);
|
||||
@@ -388,11 +389,10 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
if (returnTail != TailType.NONE) {
|
||||
ret = new OverrideableSpace(ret, returnTail);
|
||||
}
|
||||
variant.addElement(ret);
|
||||
variant.consume(ret);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillCompletions(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
public void fillCompletions(CompletionParameters parameters, final Consumer<LookupElement> result) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
|
||||
return;
|
||||
@@ -407,15 +407,15 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
if (!psiElement().withSuperParent(2, PsiSwitchStatement.class).afterLeaf("{").accepts(statement)) {
|
||||
PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(prevLeaf, PsiTryStatement.class);
|
||||
if (tryStatement == null || tryStatement.getCatchSections().length > 0 || tryStatement.getFinallyBlock() != null) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isStatementPosition(position)) {
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class) != null) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON));
|
||||
if (START_SWITCH.accepts(position)) {
|
||||
return;
|
||||
}
|
||||
@@ -431,7 +431,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
final boolean insideInheritorClass = PsiUtil.isLanguageLevel8OrHigher(position) && isInsideInheritorClass(position);
|
||||
if (!afterDot || insideQualifierClass || insideInheritorClass) {
|
||||
if (!afterDot || insideQualifierClass) {
|
||||
result.addElement(createKeyword(position, PsiKeyword.THIS));
|
||||
result.consume(createKeyword(position, PsiKeyword.THIS));
|
||||
}
|
||||
|
||||
final LookupItem superItem = (LookupItem)createKeyword(position, PsiKeyword.SUPER);
|
||||
@@ -453,18 +453,18 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
});
|
||||
}
|
||||
|
||||
result.addElement(superItem);
|
||||
result.consume(superItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (isExpressionPosition(position)) {
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) == null) {
|
||||
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
|
||||
result.addElement(createKeyword(position, PsiKeyword.NULL));
|
||||
result.consume(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
|
||||
result.consume(createKeyword(position, PsiKeyword.NULL));
|
||||
}
|
||||
if (mayExpectBoolean(parameters)) {
|
||||
result.addElement(createKeyword(position, PsiKeyword.TRUE));
|
||||
result.addElement(createKeyword(position, PsiKeyword.FALSE));
|
||||
result.consume(createKeyword(position, PsiKeyword.TRUE));
|
||||
result.consume(createKeyword(position, PsiKeyword.FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,22 +473,22 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
!(file instanceof PsiJavaCodeReferenceCodeFragment) &&
|
||||
!(file instanceof PsiTypeCodeFragment)) {
|
||||
if (prevLeaf == null) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
else if (END_OF_BLOCK.isAcceptable(position, position) && PsiTreeUtil.getParentOfType(position, PsiMember.class) == null) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
if ((isInsideParameterList(position) || isAtResourceVariableStart(position) || isAtCatchVariableStart(position)) &&
|
||||
!psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position) &&
|
||||
!AFTER_DOT.accepts(position)) {
|
||||
result.addElement(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(TailTypeDecorator.withTail(createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
|
||||
if (isInstanceofPlace(position)) {
|
||||
result.addElement(LookupElementDecorator.withInsertHandler(
|
||||
result.consume(LookupElementDecorator.withInsertHandler(
|
||||
createKeyword(position, PsiKeyword.INSTANCEOF),
|
||||
new InsertHandler<LookupElementDecorator<LookupElement>>() {
|
||||
@Override
|
||||
@@ -497,7 +497,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
if (tailType.isApplicable(context)) {
|
||||
tailType.processTail(context.getEditor(), context.getTailOffset());
|
||||
}
|
||||
|
||||
|
||||
if ('!' == context.getCompletionChar()) {
|
||||
context.setAddCompletionChar(false);
|
||||
context.commitDocument();
|
||||
@@ -515,13 +515,13 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
|
||||
if (isSuitableForClass(position)) {
|
||||
for (String s : ModifierChooser.getKeywords(position)) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiCodeBlock.class, true, PsiMember.class) == null) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_5)) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.ENUM), TailType.INSERT_SPACE));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.ENUM), TailType.INSERT_SPACE));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,22 +529,14 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
addPrimitiveTypes(result, position);
|
||||
|
||||
if (isAfterTypeDot(position)) {
|
||||
result.addElement(createKeyword(position, PsiKeyword.CLASS));
|
||||
result.consume(createKeyword(position, PsiKeyword.CLASS));
|
||||
}
|
||||
|
||||
addUnfinishedMethodTypeParameters(position, result);
|
||||
|
||||
if (JavaSmartCompletionContributor.INSIDE_EXPRESSION.accepts(position) &&
|
||||
!AFTER_DOT.accepts(position)) {
|
||||
addExpectedTypeMembers(parameters, result);
|
||||
if (SameSignatureCallParametersProvider.IN_CALL_ARGUMENT.accepts(position)) {
|
||||
new SameSignatureCallParametersProvider().addCompletions(parameters, new ProcessingContext(), result);
|
||||
}
|
||||
}
|
||||
|
||||
if (JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN.accepts(position)) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.EXTENDS), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.SUPER), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.EXTENDS), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.SUPER), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +600,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
}
|
||||
}
|
||||
|
||||
private static void addUnfinishedMethodTypeParameters(PsiElement position, CompletionResultSet result) {
|
||||
private static void addUnfinishedMethodTypeParameters(PsiElement position, final Consumer<LookupElement> result) {
|
||||
final ProcessingContext context = new ProcessingContext();
|
||||
if (psiElement().inside(
|
||||
psiElement(PsiTypeElement.class).afterLeaf(
|
||||
@@ -621,7 +613,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
}
|
||||
if (current instanceof PsiClass) {
|
||||
for (PsiTypeParameter typeParameter : list.getTypeParameters()) {
|
||||
result.addElement(new JavaPsiClassReferenceElement(typeParameter));
|
||||
result.consume(new JavaPsiClassReferenceElement(typeParameter));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,7 +635,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
isAfterPrimitiveOrArrayType(position);
|
||||
}
|
||||
|
||||
private static void addPrimitiveTypes(CompletionResultSet result, PsiElement position) {
|
||||
private static void addPrimitiveTypes(final Consumer<LookupElement> result, PsiElement position) {
|
||||
if (AFTER_DOT.accepts(position)) {
|
||||
return;
|
||||
}
|
||||
@@ -653,9 +645,9 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
if (afterNew) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(position.getProject());
|
||||
for (String primitiveType : PRIMITIVE_TYPES) {
|
||||
result.addElement(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText(primitiveType + "[]", null), null));
|
||||
result.consume(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText(primitiveType + "[]", null), null));
|
||||
}
|
||||
result.addElement(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText("void[]", null), null));
|
||||
result.consume(PsiTypeLookupItem.createLookupItem(factory.createTypeFromText("void[]", null), null));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -677,14 +669,14 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
expressionPosition ||
|
||||
isStatementPosition(position)) {
|
||||
for (String primitiveType : PRIMITIVE_TYPES) {
|
||||
result.addElement(createKeyword(position, primitiveType));
|
||||
result.consume(createKeyword(position, primitiveType));
|
||||
}
|
||||
}
|
||||
if (declaration) {
|
||||
result.addElement(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
result.consume(new OverrideableSpace(createKeyword(position, PsiKeyword.VOID), TailType.HUMBLE_SPACE_BEFORE_WORD));
|
||||
}
|
||||
else if (typeFragment && ((PsiTypeCodeFragment)position.getContainingFile()).isVoidValid()) {
|
||||
result.addElement(createKeyword(position, PsiKeyword.VOID));
|
||||
result.consume(createKeyword(position, PsiKeyword.VOID));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,7 +688,7 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
return psiElement().insideStarting(psiElement(PsiTypeElement.class).withParent(PsiCatchSection.class)).accepts(position);
|
||||
}
|
||||
|
||||
private static void addBreakContinue(CompletionResultSet result, PsiElement position) {
|
||||
private static void addBreakContinue(Consumer<LookupElement> result, PsiElement position) {
|
||||
PsiLoopStatement loop = PsiTreeUtil.getParentOfType(position, PsiLoopStatement.class);
|
||||
|
||||
LookupElement br = createKeyword(position, PsiKeyword.BREAK);
|
||||
@@ -714,11 +706,11 @@ public class JavaCompletionData extends JavaAwareCompletionData {
|
||||
cont = TailTypeDecorator.withTail(cont, tailType);
|
||||
|
||||
if (loop != null && new InsideElementFilter(new ClassFilter(PsiStatement.class)).isAcceptable(position, loop)) {
|
||||
result.addElement(br);
|
||||
result.addElement(cont);
|
||||
result.consume(br);
|
||||
result.consume(cont);
|
||||
}
|
||||
if (psiElement().inside(PsiSwitchStatement.class).accepts(position)) {
|
||||
result.addElement(br);
|
||||
result.consume(br);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-4
@@ -50,8 +50,16 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
InheritorsHolder holder = new InheritorsHolder(parameters.getPosition(), result);
|
||||
for (CompletionResult plainResult : plainResults) {
|
||||
Object o = plainResult.getLookupElement().getObject();
|
||||
if (o instanceof PsiClass) {
|
||||
holder.registerClass((PsiClass)o);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty) {
|
||||
delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result));
|
||||
delegate(parameters, JavaCompletionSorting.addJavaSorting(parameters, result), holder);
|
||||
} else if (Registry.is("ide.completion.show.better.matching.classes")) {
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() <= 1 &&
|
||||
@@ -59,7 +67,6 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
JavaCompletionContributor.isClassNamePossible(parameters) &&
|
||||
!JavaSmartCompletionContributor.AFTER_NEW.accepts(parameters.getPosition())) {
|
||||
result = result.withPrefixMatcher(new BetterPrefixMatcher(result.getPrefixMatcher(), BetterPrefixMatcher.getBestMatchingDegree(plainResults)));
|
||||
InheritorsHolder holder = new InheritorsHolder(parameters.getPosition(), result);
|
||||
for (CompletionResult plainResult : plainResults) {
|
||||
LookupElement element = plainResult.getLookupElement();
|
||||
if (element instanceof TypeArgumentCompletionProvider.TypeArgsLookupElement) {
|
||||
@@ -86,7 +93,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void delegate(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
private static void delegate(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritorsHolder) {
|
||||
if (parameters.getCompletionType() == CompletionType.BASIC) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
suggestCollectionUtilities(parameters, result, position);
|
||||
@@ -94,7 +101,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
|
||||
if (parameters.getInvocationCount() <= 1 &&
|
||||
(JavaCompletionContributor.mayStartClassName(result) || suggestMetaAnnotations(parameters)) &&
|
||||
JavaCompletionContributor.isClassNamePossible(parameters)) {
|
||||
suggestNonImportedClasses(parameters, result, null);
|
||||
suggestNonImportedClasses(parameters, result, inheritorsHolder);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ipp.trivialif.MergeIfAndIntention;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -57,7 +58,7 @@ public class SurroundWithIfFix implements LocalQuickFix {
|
||||
PsiFile file = element.getContainingFile();
|
||||
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
|
||||
Document document = documentManager.getDocument(file);
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
|
||||
if (document == null || !FileModificationService.getInstance().prepareFileForWrite(file)) return;
|
||||
PsiElement[] elements = {anchorStatement};
|
||||
PsiElement prev = PsiTreeUtil.skipSiblingsBackward(anchorStatement, PsiWhiteSpace.class);
|
||||
if (prev instanceof PsiComment && JavaSuppressionUtil.getSuppressedInspectionIdsIn(prev) != null) {
|
||||
@@ -71,6 +72,11 @@ public class SurroundWithIfFix implements LocalQuickFix {
|
||||
document.replaceString(textRange.getStartOffset(), textRange.getEndOffset(),newText);
|
||||
|
||||
editor.getCaretModel().moveToOffset(textRange.getEndOffset() + newText.length());
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
new MergeIfAndIntention().invoke(project, editor, file);
|
||||
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -50,11 +50,14 @@ import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.Url;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.builtInWebServer.BuiltInWebBrowserUrlProvider;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -684,7 +687,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<String> findUrlForClass(PsiClass aClass) {
|
||||
public static List<String> findUrlForClass(@NotNull PsiClass aClass) {
|
||||
String qName = aClass.getQualifiedName();
|
||||
if (qName == null) return null;
|
||||
|
||||
@@ -696,18 +699,18 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
|
||||
|
||||
String packageName = ((PsiJavaFile)file).getPackageName();
|
||||
String relPath;
|
||||
if (packageName.length() > 0) {
|
||||
relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION;
|
||||
if (packageName.isEmpty()) {
|
||||
relPath = qName + HTML_EXTENSION;
|
||||
}
|
||||
else {
|
||||
relPath = qName + HTML_EXTENSION;
|
||||
relPath = packageName.replace('.', '/') + '/' + qName.substring(packageName.length() + 1) + HTML_EXTENSION;
|
||||
}
|
||||
|
||||
return findUrlForVirtualFile(file.getProject(), virtualFile, relPath);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<String> findUrlForVirtualFile(final Project project, final VirtualFile virtualFile, final String relPath) {
|
||||
public static List<String> findUrlForVirtualFile(@NotNull Project project, @NotNull VirtualFile virtualFile, @NotNull String relPath) {
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
Module module = fileIndex.getModuleForFile(virtualFile);
|
||||
if (module == null) {
|
||||
@@ -728,11 +731,25 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
|
||||
}
|
||||
}
|
||||
|
||||
final List<OrderEntry> orderEntries = fileIndex.getOrderEntriesForFile(virtualFile);
|
||||
for (OrderEntry orderEntry : orderEntries) {
|
||||
final String[] files = JavadocOrderRootType.getUrls(orderEntry);
|
||||
final List<String> httpRoot = PlatformDocumentationUtil.getHttpRoots(files, relPath);
|
||||
if (httpRoot != null) return httpRoot;
|
||||
for (OrderEntry orderEntry : fileIndex.getOrderEntriesForFile(virtualFile)) {
|
||||
for (VirtualFile root : orderEntry.getFiles(JavadocOrderRootType.getInstance())) {
|
||||
if (root.getFileSystem() == JarFileSystem.getInstance()) {
|
||||
VirtualFile file = root.findFileByRelativePath(relPath);
|
||||
List<Url> urls = file == null ? null : BuiltInWebBrowserUrlProvider.getUrls(file, project, null);
|
||||
if (!ContainerUtil.isEmpty(urls)) {
|
||||
List<String> result = new SmartList<String>();
|
||||
for (Url url : urls) {
|
||||
result.add(url.toExternalForm());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> httpRoot = PlatformDocumentationUtil.getHttpRoots(JavadocOrderRootType.getUrls(orderEntry), relPath);
|
||||
if (httpRoot != null) {
|
||||
return httpRoot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.projectRoots;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
|
||||
|
||||
public class JavaLanguageTestDataChecker implements LanguageTestDataChecker {
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public FileType getFileType() {
|
||||
return StdFileTypes.JAVA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTestData(@NotNull Project project, @NotNull VirtualFile virtualFile) {
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
return !index.isUnderSourceRootOfType(virtualFile, JavaModuleSourceRootTypes.SOURCES);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
class Foo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Inne<caret>x
|
||||
}
|
||||
|
||||
private static final class Inner { }
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Surround with 'if (i != null)'" "true"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class A {
|
||||
void foo(@Nullable String i) {
|
||||
if (i != null && i.length() > 0) {
|
||||
if (i != "a") {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Surround with 'if (i != null)'" "true"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class A {
|
||||
void foo(@Nullable String i) {
|
||||
if (i.le<caret>ngth() > 0) {
|
||||
if (i != "a") {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class A {
|
||||
private String s;
|
||||
private int next = 0;
|
||||
|
||||
public A(final String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
private char getChar() {
|
||||
return s.charAt(next++);
|
||||
}
|
||||
|
||||
private void foo() {
|
||||
char c = getChar();
|
||||
if (c == 'a') {
|
||||
if (getChar() == 'b') {
|
||||
System.out.println("ab");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1599,7 +1599,7 @@ class Foo {
|
||||
myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
|
||||
myFixture.type('a')
|
||||
joinAutopopup()
|
||||
myFixture.type('\na')
|
||||
myFixture.type('\nf')
|
||||
joinCompletion()
|
||||
assert lookup
|
||||
}
|
||||
|
||||
+8
-2
@@ -389,7 +389,7 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase {
|
||||
checkResult()
|
||||
}
|
||||
|
||||
public void testFieldType() throws Throwable { doTest('\n'); }
|
||||
public void testFieldType() { doTest(); }
|
||||
|
||||
public void testPackageInAnnoParam() throws Throwable {
|
||||
doTest();
|
||||
@@ -903,7 +903,7 @@ public class ListUtils {
|
||||
checkResult();
|
||||
}
|
||||
|
||||
public void testSecondAnonymousClassParameter() throws Throwable { doTest('\n'); }
|
||||
public void testSecondAnonymousClassParameter() { doTest(); }
|
||||
|
||||
public void testSpaceAfterReturn() throws Throwable {
|
||||
configure()
|
||||
@@ -1269,6 +1269,12 @@ class XInternalError {}
|
||||
assert LookupElementPresentation.renderElement(items[0]).tailText == ' (java.lang)'
|
||||
}
|
||||
|
||||
public void testDuplicateInnerClass() {
|
||||
configure()
|
||||
def items = myFixture.lookupElements.findAll { it.lookupString == 'Inner' }
|
||||
assert items.size() == 1
|
||||
}
|
||||
|
||||
public void testSameSignature() {
|
||||
configure()
|
||||
myFixture.assertPreferredCompletionItems(0, 's', 's, file', 's, file, a')
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class VariablesCompletionTest extends LightFixtureCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testLocals3() throws Exception {
|
||||
doSelectTest("TestSource3.java", "TestResult3.java");
|
||||
doTest("TestSource3.java", "TestResult3.java");
|
||||
}
|
||||
|
||||
public void testLocals4() throws Exception {
|
||||
@@ -53,7 +53,7 @@ public class VariablesCompletionTest extends LightFixtureCompletionTestCase {
|
||||
}
|
||||
|
||||
public void testLocals5() throws Exception {
|
||||
doSelectTest("TestSource5.java", "TestResult5.java");
|
||||
doTest("TestSource5.java", "TestResult5.java");
|
||||
}
|
||||
|
||||
public void testLocals6() throws Exception {
|
||||
|
||||
@@ -271,6 +271,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testUnusedCallDoesNotMakeUnknown() { doTest(); }
|
||||
public void testEmptyCallDoesNotMakeNullable() { doTest(); }
|
||||
public void testGettersAndPureNoFlushing() { doTest(); }
|
||||
public void testFalseGetters() { doTest(); }
|
||||
|
||||
public void testNotNullAfterDereference() { doTest(); }
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.SmartTypeCompletionDfaTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.AddAssertStatementFixTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.ReplaceFromOfNullableFixTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.ReplaceWithOfNullableFixTest;
|
||||
import com.intellij.codeInsight.daemon.quickFix.SurroundWithIfFixTest;
|
||||
import com.intellij.slicer.SliceBackwardTest;
|
||||
import com.intellij.slicer.SliceTreeTest;
|
||||
import junit.framework.Test;
|
||||
@@ -49,6 +50,7 @@ public class DataFlowInspectionTestSuite {
|
||||
suite.addTestSuite(NullableStuffInspection14Test.class);
|
||||
|
||||
suite.addTestSuite(AddAssertStatementFixTest.class);
|
||||
suite.addTestSuite(SurroundWithIfFixTest.class);
|
||||
suite.addTestSuite(ReplaceWithOfNullableFixTest.class);
|
||||
suite.addTestSuite(ReplaceFromOfNullableFixTest.class);
|
||||
return suite;
|
||||
|
||||
+57
-1
@@ -33,6 +33,8 @@ import com.intellij.openapi.util.NotNullLazyValue;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PairFunction;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
@@ -207,7 +209,8 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
|
||||
DirectoryInfo info = directoryIndex.getInfoForFile(file);
|
||||
// we serve excluded files
|
||||
if (!info.isExcluded() && !info.isInProject()) {
|
||||
return null;
|
||||
// javadoc jars is "not under project", but actually is, so, let's check project library table
|
||||
return file.getFileSystem() == JarFileSystem.getInstance() ? getInfoForDocJar(file, project) : null;
|
||||
}
|
||||
|
||||
VirtualFile root = info.getSourceRoot();
|
||||
@@ -245,6 +248,59 @@ final class DefaultWebServerRootsProvider extends WebServerRootsProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PathInfo getInfoForDocJar(@NotNull final VirtualFile file, @NotNull Project project) {
|
||||
final OrderRootType javaDocRootType = JavadocOrderRootType.getInstance();
|
||||
if (javaDocRootType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
class LibraryProcessor implements Processor<Library> {
|
||||
PathInfo result;
|
||||
String moduleName;
|
||||
|
||||
@Override
|
||||
public boolean process(Library library) {
|
||||
for (VirtualFile root : library.getFiles(javaDocRootType)) {
|
||||
if (VfsUtilCore.isAncestor(root, file, false)) {
|
||||
result = new PathInfo(file, root, moduleName, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LibraryProcessor processor = new LibraryProcessor();
|
||||
AccessToken token = ReadAction.start();
|
||||
try {
|
||||
ModuleManager moduleManager = ModuleManager.getInstance(project);
|
||||
for (Module module : moduleManager.getModules()) {
|
||||
if (module.isDisposed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
processor.moduleName = module.getName();
|
||||
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary(processor);
|
||||
if (processor.result != null) {
|
||||
return processor.result;
|
||||
}
|
||||
}
|
||||
|
||||
processor.moduleName = null;
|
||||
for (Library library : LibraryTablesRegistrar.getInstance().getLibraryTable(project).getLibraries()) {
|
||||
if (!processor.process(library)) {
|
||||
return processor.result;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getModuleNameQualifier(@NotNull Project project, @Nullable Module module) {
|
||||
if (module != null &&
|
||||
|
||||
+12
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -19,10 +19,11 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -30,7 +31,6 @@ import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class PlatformDocumentationUtil {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.documentation.PlatformDocumentationUtil");
|
||||
|
||||
private static final @NonNls Pattern ourLtFixupPattern = Pattern.compile("<([^/^\\w^!])");
|
||||
@@ -38,19 +38,23 @@ public class PlatformDocumentationUtil {
|
||||
private static final @NonNls String LT_ENTITY = "<";
|
||||
|
||||
@Nullable
|
||||
public static List<String> getHttpRoots(final String[] roots, String relPath) {
|
||||
final ArrayList<String> result = new ArrayList<String>();
|
||||
public static List<String> getHttpRoots(@NotNull String[] roots, String relPath) {
|
||||
List<String> result = new SmartList<String>();
|
||||
for (String root : roots) {
|
||||
final VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
|
||||
VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
|
||||
if (virtualFile != null) {
|
||||
if (virtualFile.getFileSystem() instanceof HttpFileSystem) {
|
||||
String url = virtualFile.getUrl();
|
||||
if (!url.endsWith("/")) url += "/";
|
||||
if (!url.endsWith("/")) {
|
||||
url += "/";
|
||||
}
|
||||
result.add(url + relPath);
|
||||
}
|
||||
else {
|
||||
VirtualFile file = virtualFile.findFileByRelativePath(relPath);
|
||||
if (file != null) result.add(file.getUrl());
|
||||
if (file != null) {
|
||||
result.add(file.getUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.util.Function;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -139,4 +140,26 @@ public class BackgroundTaskUtil {
|
||||
result.run();
|
||||
indicator.stop();
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
@Nullable
|
||||
public static <T> T tryComputeFast(@NotNull final Function<ProgressIndicator, T> backgroundTask,
|
||||
final int waitMillis) {
|
||||
final Ref<T> resultRef = new Ref<T>();
|
||||
ProgressIndicator indicator = executeAndTryWait(new Function<ProgressIndicator, Runnable>() {
|
||||
@Override
|
||||
public Runnable fun(final ProgressIndicator indicator) {
|
||||
final T result = backgroundTask.fun(indicator);
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultRef.set(result);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, null, waitMillis, false);
|
||||
indicator.cancel();
|
||||
|
||||
return resultRef.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,6 +656,12 @@ public class DiffUtil {
|
||||
return document.getImmutableCharSequence().subSequence(otherRange.getStartOffset(), otherRange.getEndOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return affected range, without non-internal newlines
|
||||
* <p/>
|
||||
* we consider '\n' not as a part of line, but a separator between lines
|
||||
* ex: if last line is not empty, the last symbol will not be '\n'
|
||||
*/
|
||||
@NotNull
|
||||
public static TextRange getLinesRange(@NotNull Document document, int line1, int line2) {
|
||||
if (line1 == line2) {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.projectRoots;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Files for which #isTestData returns true won't be processed by
|
||||
* Optimize Imports, Reformat Code and Rearrange Code actions during before-commit stage.
|
||||
*
|
||||
* When developing language plugin it is improperly to perform any modification actions
|
||||
* for language test data files (files that looks like source code, but are used only as test data)
|
||||
* on commit, even if appropriate checkboxes in commit dialog are turned on.
|
||||
*/
|
||||
public interface LanguageTestDataChecker {
|
||||
|
||||
ExtensionPointName<LanguageTestDataChecker> EP_NAME =
|
||||
new ExtensionPointName<LanguageTestDataChecker>("com.intellij.languageTestDataChecker");
|
||||
|
||||
@NotNull
|
||||
FileType getFileType();
|
||||
|
||||
boolean isTestData(@NotNull Project project, @NotNull VirtualFile virtualFile);
|
||||
|
||||
}
|
||||
+25
-23
@@ -705,33 +705,35 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
if (myElement != null) {
|
||||
final PsiElement element = myElement.getElement();
|
||||
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
|
||||
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
|
||||
boolean processed = false;
|
||||
if (provider instanceof CompositeDocumentationProvider) {
|
||||
for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) {
|
||||
if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)p).handleExternal(element, originalElement)) {
|
||||
processed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (myElement == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!processed) {
|
||||
final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext());
|
||||
final List<String> urls;
|
||||
if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) {
|
||||
urls = Collections.singletonList(myEffectiveExternalUrl);
|
||||
} else {
|
||||
urls = provider.getUrlFor(element, originalElement);
|
||||
assert urls != null : provider;
|
||||
assert !urls.isEmpty() : provider;
|
||||
final PsiElement element = myElement.getElement();
|
||||
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
|
||||
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
|
||||
boolean processed = false;
|
||||
if (provider instanceof CompositeDocumentationProvider) {
|
||||
for (DocumentationProvider p : ((CompositeDocumentationProvider)provider).getAllProviders()) {
|
||||
if (p instanceof ExternalDocumentationHandler && ((ExternalDocumentationHandler)p).handleExternal(element, originalElement)) {
|
||||
processed = true;
|
||||
break;
|
||||
}
|
||||
ExternalJavaDocAction.showExternalJavadoc(urls, component);
|
||||
}
|
||||
}
|
||||
|
||||
if (!processed) {
|
||||
List<String> urls;
|
||||
if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) {
|
||||
urls = Collections.singletonList(myEffectiveExternalUrl);
|
||||
}
|
||||
else {
|
||||
urls = provider.getUrlFor(element, originalElement);
|
||||
assert urls != null : provider;
|
||||
assert !urls.isEmpty() : provider;
|
||||
}
|
||||
ExternalJavaDocAction.showExternalJavadoc(urls, PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -35,11 +35,13 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ExternalJavaDocAction extends AnAction {
|
||||
|
||||
@@ -90,8 +92,8 @@ public class ExternalJavaDocAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showExternalJavadoc(List<String> urls, Component component) {
|
||||
final HashSet<String> set = new HashSet<String>(urls);
|
||||
public static void showExternalJavadoc(@NotNull List<String> urls, Component component) {
|
||||
Set<String> set = new THashSet<String>(urls);
|
||||
if (set.size() > 1) {
|
||||
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>("Choose external documentation root", ArrayUtil.toStringArray(set)) {
|
||||
@Override
|
||||
|
||||
+1
-2
@@ -48,7 +48,6 @@ import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.IJSwingUtilities;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.util.ui.table.JBListTable;
|
||||
import com.intellij.util.ui.table.JBTableRowEditor;
|
||||
@@ -689,7 +688,7 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
|
||||
|
||||
protected abstract class ParametersListTable extends JBListTable {
|
||||
public ParametersListTable() {
|
||||
super(myParametersTable);
|
||||
super(myParametersTable, ChangeSignatureDialogBase.this.getDisposable());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -137,10 +137,6 @@ public class BrowserLauncherAppless extends BrowserLauncher {
|
||||
private void openOrBrowse(@NotNull String url, boolean browse, @Nullable Project project) {
|
||||
url = url.trim();
|
||||
|
||||
if (url.startsWith("jar:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri;
|
||||
if (BrowserUtil.isAbsoluteURL(url)) {
|
||||
uri = VfsUtil.toUri(url);
|
||||
|
||||
@@ -85,38 +85,94 @@ public final class EmptyAction extends AnAction {
|
||||
}
|
||||
|
||||
public static AnAction wrap(final AnAction action) {
|
||||
return action instanceof ActionGroup ? new ActionGroup() {
|
||||
{
|
||||
setPopup(((ActionGroup)action).isPopup());
|
||||
copyFrom(action);
|
||||
setShortcutSet(new CustomShortcutSet());
|
||||
}
|
||||
final boolean isDumbAware = action.isDumbAware();
|
||||
final boolean isEnabledInModalContext = action.isEnabledInModalContext();
|
||||
final boolean inInjectedContext = action.isInInjectedContext();
|
||||
final boolean isTransparentUpdate = action.isTransparentUpdate();
|
||||
if (action instanceof ActionGroup) {
|
||||
final ActionGroup group = ((ActionGroup)action);
|
||||
final boolean isHideIfNoVisibleChildren = group.hideIfNoVisibleChildren();
|
||||
final boolean isDisableIfNoVisibleChildren = group.disableIfNoVisibleChildren();
|
||||
return new ActionGroup() {
|
||||
{
|
||||
setPopup(group.isPopup());
|
||||
copyFrom(group);
|
||||
setShortcutSet(new CustomShortcutSet());
|
||||
setEnabledInModalContext(isEnabledInModalContext);
|
||||
setInjectedContext(inInjectedContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
action.update(e);
|
||||
}
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
group.update(e);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable final AnActionEvent e) {
|
||||
return ((ActionGroup)action).getChildren(e);
|
||||
}
|
||||
} : new AnAction() {
|
||||
{
|
||||
copyFrom(action);
|
||||
setShortcutSet(new CustomShortcutSet());
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
public AnAction[] getChildren(@Nullable final AnActionEvent e) {
|
||||
return group.getChildren(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
action.actionPerformed(e);
|
||||
}
|
||||
@Override
|
||||
public boolean canBePerformed(DataContext context) {
|
||||
return group.canBePerformed(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
action.update(e);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
group.actionPerformed(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDumbAware() {
|
||||
return isDumbAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransparentUpdate() {
|
||||
return isTransparentUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideIfNoVisibleChildren() {
|
||||
return isHideIfNoVisibleChildren;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean disableIfNoVisibleChildren() {
|
||||
return isDisableIfNoVisibleChildren;
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
return new AnAction() {
|
||||
{
|
||||
copyFrom(action);
|
||||
setShortcutSet(new CustomShortcutSet());
|
||||
setEnabledInModalContext(isEnabledInModalContext);
|
||||
setInjectedContext(inInjectedContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
action.actionPerformed(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final AnActionEvent e) {
|
||||
action.update(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDumbAware() {
|
||||
return isDumbAware;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTransparentUpdate() {
|
||||
return isTransparentUpdate;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,11 +67,13 @@ public class EditorOptionsTopHitProvider extends OptionsTopHitProvider {
|
||||
editorCode("Appearance: " + messageApp("checkbox.show.small.icons.in.gutter"), "SHOW_SMALL_ICONS_IN_GUTTER"),
|
||||
option("Appearance: " + messageApp("checkbox.show.code.folding.outline"), "IS_FOLDING_OUTLINE_SHOWN", "editor.preferences.folding"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.editor.tabs.in.single.row"), "SCROLL_TAB_LAYOUT_IN_EDITOR"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.editor.scroll.if.need"), "HIDE_TABS_IF_NEED"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.hide.file.extension.in.editor.tabs"), "HIDE_KNOWN_EXTENSION_IN_TABS"),
|
||||
editorTabs("Tabs: Show directory in editor tabs for non-unique filenames", "SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.editor.tabs.show.close.button"), "SHOW_CLOSE_BUTTON"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.mark.modified.tabs.with.asterisk"), "MARK_MODIFIED_TABS_WITH_ASTERISK"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.show.tabs.tooltips"), "SHOW_TABS_TOOLTIPS"),
|
||||
editorTabs("Tabs: " + messageApp("checkbox.smart.tab.reuse"), "REUSE_NOT_MODIFIED_TABS"),
|
||||
editorTabs("Tabs: " + messageApp("radio.close.non.modified.files.first"), "CLOSE_NON_MODIFIED_FILES_FIRST")
|
||||
);
|
||||
|
||||
|
||||
+6
-6
@@ -93,7 +93,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
|
||||
final int tH = JBUI.scale(6);
|
||||
final int xU = (w - tW) / 2;
|
||||
final int yU = (h - tH) / 2;
|
||||
g.translate(JBUI.scale(2), 0);
|
||||
g.translate(JBUI.scale(2), JBUI.scale(1));
|
||||
final Path2D.Double path = new Path2D.Double();
|
||||
path.moveTo(xU, yU);
|
||||
path.lineTo(xU + tW, yU);
|
||||
@@ -105,7 +105,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
|
||||
//path.lineTo(xU + 1, yU + 2);
|
||||
path.closePath();
|
||||
g.fill(path);
|
||||
g.translate(-JBUI.scale(2), 0);
|
||||
g.translate(-JBUI.scale(2), -JBUI.scale(1));
|
||||
if (!isTableCellEditor(myComboBox)) {
|
||||
g.setColor(getArrowButtonFillColor(getBorderColor()));
|
||||
g.drawLine(0, -1, 0, h);
|
||||
@@ -224,7 +224,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
|
||||
protected Rectangle rectangleForCurrentValue() {
|
||||
final Rectangle r = super.rectangleForCurrentValue();
|
||||
r.x-= JBUI.scale(2);
|
||||
r.y-= isTableCellEditor(myComboBox) ? 0 : JBUI.scale(1);
|
||||
r.y-= isTableCellEditor(myComboBox) ? 0 : 0;//JBUI.scale(1);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
|
||||
final Color borderColor = getBorderColor();//ColorUtil.shift(UIUtil.getBorderColor(), 4);
|
||||
g.setColor(getArrowButtonFillColor(borderColor));
|
||||
int off = hasFocus ? 1 : 0;
|
||||
g.drawLine(xxx + JBUI.scale(5), y + JBUI.scale(1) + off, xxx + JBUI.scale(5), height - JBUI.scale(3));
|
||||
g.drawLine(xxx + JBUI.scale(5), y + JBUI.scale(1) + off, xxx + JBUI.scale(5), height - JBUI.scale(2));
|
||||
|
||||
Rectangle r = rectangleForCurrentValue();
|
||||
paintCurrentValueBackground(g, r, hasFocus);
|
||||
@@ -373,13 +373,13 @@ public class DarculaComboBoxUI extends BasicComboBoxUI implements Border {
|
||||
}
|
||||
else {
|
||||
g.setColor(borderColor);
|
||||
g.drawRoundRect(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(4), R, R);
|
||||
g.drawRoundRect(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(2), R, R);
|
||||
if (!UIUtil.isUnderDarcula() && comboBox.isEnabled()) {
|
||||
g.setColor(getArrowButtonFillColor(getBorderColor()));
|
||||
final Shape clip = g.getClip();
|
||||
final int offX = xxx + JBUI.scale(5);
|
||||
g.setClip(offX, y, width - offX, height);
|
||||
g.drawRoundRect(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(4), R, R);
|
||||
g.drawRoundRect(JBUI.scale(1), JBUI.scale(1), width - JBUI.scale(2), height - JBUI.scale(2), R, R);
|
||||
g.setClip(clip);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -40,10 +40,7 @@ public class DarculaEditorTextFieldBorder implements Border {
|
||||
final EditorTextField textField = UIUtil.getParentOfType(EditorTextField.class, c);
|
||||
if (textField == null) return;
|
||||
|
||||
final int x1 = x + 3;
|
||||
final int y1 = y + 3;
|
||||
final int width1 = width - 8;
|
||||
final int height1 = height - 6;
|
||||
final Rectangle r = new Rectangle(x + 1, y + 1, width - 2, height - 2);
|
||||
|
||||
if (c.isOpaque()) {
|
||||
g.setColor(UIUtil.getPanelBackground());
|
||||
@@ -51,26 +48,26 @@ public class DarculaEditorTextFieldBorder implements Border {
|
||||
}
|
||||
|
||||
g.setColor(c.getBackground());
|
||||
g.fillRect(x1, y1, width1, height1);
|
||||
g.fillRect(r.x, r.y, r.width, r.height);
|
||||
|
||||
if (!textField.isEnabled()) {
|
||||
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
|
||||
}
|
||||
|
||||
if (textField.isEnabled() && textField.isVisible() && textField.getFocusTarget().hasFocus()) {
|
||||
DarculaUIUtil.paintFocusRing(g, x1, y1, width1, height1);
|
||||
DarculaUIUtil.paintFocusRing(g, r.x + 1, r.y + 1, r.width - 2, r.height - 2);
|
||||
} else {
|
||||
g.setColor(new JBColor(Gray._150, Gray._100));
|
||||
g.drawRect(x1, y1, width1, height1);
|
||||
g.drawRect(r.x, r.y, r.width, r.height);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c) {
|
||||
if (isComboBoxEditor(c) /*|| isCellEditor(c)*/) {
|
||||
return new InsetsUIResource(2,3,2,3);
|
||||
return new InsetsUIResource(2, 3, 2, 3);
|
||||
}
|
||||
return new InsetsUIResource(6, 7, 6, 7);
|
||||
return new InsetsUIResource(4, 7, 4, 7);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -533,7 +533,13 @@ public abstract class FinderRecursivePanel<T> extends JBSplitter implements Data
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> void mergeListItems(@NotNull CollectionListModel<T> listModel, @NotNull List<T> newItems) {
|
||||
static <T> void mergeListItems(@NotNull CollectionListModel<T> listModel, @NotNull List<T> newItems) {
|
||||
boolean isEmptyList = listModel.getSize() == 0;
|
||||
if (isEmptyList) {
|
||||
listModel.add(newItems);
|
||||
return;
|
||||
}
|
||||
|
||||
// remove items
|
||||
for (int i = listModel.getSize() - 1; i >= 0; i--) {
|
||||
if (!newItems.contains(listModel.getElementAt(i))) {
|
||||
@@ -574,7 +580,8 @@ public abstract class FinderRecursivePanel<T> extends JBSplitter implements Data
|
||||
final FinderRecursivePanel childPanel = (FinderRecursivePanel)myChild;
|
||||
if (withUpdatePanel) {
|
||||
childPanel.init();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
childPanel.initWithoutUpdatePanel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +254,7 @@
|
||||
<extensionPoint name="useScopeOptimizer" interface="com.intellij.psi.search.UseScopeOptimizer"/>
|
||||
|
||||
<extensionPoint name="generatedSourcesFilter" interface="com.intellij.openapi.roots.GeneratedSourcesFilter"/>
|
||||
<extensionPoint name="languageTestDataChecker" interface="com.intellij.openapi.projectRoots.LanguageTestDataChecker"/>
|
||||
|
||||
<extensionPoint name="gotoClassContributor"
|
||||
interface="com.intellij.navigation.ChooseByNameContributor"/>
|
||||
|
||||
@@ -294,7 +294,7 @@ ide.structural.navigation.visit.fields.description=Whether fields should be stop
|
||||
ide.non.english.keyboard.layout.fix=false
|
||||
ide.non.english.keyboard.layout.fix.description=Enables a fix for key codes with non-English keyboard layouts
|
||||
|
||||
ide.dfa.getters.with.side.effects=java\\.nio\\..*ByteBuffer\\.get.*
|
||||
ide.dfa.getters.with.side.effects=
|
||||
ide.dfa.getters.with.side.effects.description=A regex on qualified names of methods that look like getters but are not. For Constant Conditions & Exception inspection
|
||||
|
||||
ide.dfa.time.limit.online=1000
|
||||
@@ -368,6 +368,7 @@ show.flex.debug.design.view=false
|
||||
|
||||
diff.patience.alg=false
|
||||
diff.status.tracker.skip.spaces=true
|
||||
diff.status.tracker.byword.delay=200
|
||||
diff.verify.iterable=false
|
||||
diff.unimportant.line.char.count=3
|
||||
diff.unimportant.line.char.count.description=Threshold number of non-space characters to mark line as unimportant
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
package com.intellij.openapi.vcs.checkin;
|
||||
|
||||
import com.intellij.openapi.components.StorageScheme;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ex.ProjectEx;
|
||||
import com.intellij.openapi.projectRoots.LanguageTestDataChecker;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
@@ -30,7 +30,6 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -67,7 +66,8 @@ public class CheckinHandlerUtil {
|
||||
|
||||
for (VirtualFile file : selectedFiles) {
|
||||
if (file.isValid()) {
|
||||
if (isUnderProjectFileDir(projectFileDir, file) || !isFileUnderSourceRoot(project, file)) {
|
||||
if (isUnderProjectFileDir(projectFileDir, file) || !isFileUnderSourceRoot(project, file)
|
||||
|| isLanguageTestData(project, file)) {
|
||||
continue;
|
||||
}
|
||||
PsiFile psiFile = psiManager.findFile(file);
|
||||
@@ -83,12 +83,17 @@ public class CheckinHandlerUtil {
|
||||
|
||||
private static boolean isFileUnderSourceRoot(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(project).getFileIndex();
|
||||
if (StdFileTypes.JAVA == file.getFileType()) {
|
||||
return index.isUnderSourceRootOfType(file, JavaModuleSourceRootTypes.SOURCES) && !index.isInLibrarySource(file);
|
||||
}
|
||||
else {
|
||||
return index.isInContent(file) && !index.isInLibrarySource(file) ;
|
||||
return index.isInContent(file) && !index.isInLibrarySource(file);
|
||||
}
|
||||
|
||||
private static boolean isLanguageTestData(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
for (LanguageTestDataChecker checker : LanguageTestDataChecker.EP_NAME.getExtensions()) {
|
||||
if (checker.getFileType() == file.getFileType()
|
||||
&& checker.isTestData(project, file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void disableWhenDumb(@NotNull Project project, @NotNull JCheckBox checkBox, @NotNull String tooltip) {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.ex;
|
||||
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.UndoConstants;
|
||||
@@ -41,14 +42,15 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.diff.util.DiffUtil.getLineCount;
|
||||
|
||||
/**
|
||||
* @author irengrig
|
||||
* author: lesya
|
||||
@@ -60,7 +62,6 @@ public class LineStatusTracker {
|
||||
private static final Key<CanNotCalculateDiffPanel> PANEL_KEY =
|
||||
new Key<CanNotCalculateDiffPanel>("LineStatusTracker.CanNotCalculateDiffPanel");
|
||||
|
||||
private final Object myLock = new Object();
|
||||
private boolean myInitialized;
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@@ -103,51 +104,50 @@ public class LineStatusTracker {
|
||||
myRanges = new ArrayList<Range>();
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public void initialize(@NotNull final String vcsContent, @NotNull RevisionPack baseRevisionNumber) {
|
||||
myApplication.assertIsDispatchThread();
|
||||
if (myReleased) return;
|
||||
|
||||
synchronized (myLock) {
|
||||
try {
|
||||
if (myReleased) return;
|
||||
if (myBaseRevisionNumber != null && myBaseRevisionNumber.contains(baseRevisionNumber)) return;
|
||||
try {
|
||||
if (myBaseRevisionNumber != null && myBaseRevisionNumber.contains(baseRevisionNumber)) return;
|
||||
|
||||
myBaseRevisionNumber = baseRevisionNumber;
|
||||
myBaseRevisionNumber = baseRevisionNumber;
|
||||
|
||||
myVcsDocument.setReadOnly(false);
|
||||
myVcsDocument.setText(vcsContent);
|
||||
myVcsDocument.setReadOnly(true);
|
||||
reinstallRanges();
|
||||
myVcsDocument.setReadOnly(false);
|
||||
myVcsDocument.setText(vcsContent);
|
||||
myVcsDocument.setReadOnly(true);
|
||||
reinstallRanges();
|
||||
|
||||
if (myDocumentListener == null) {
|
||||
myDocumentListener = new MyDocumentListener();
|
||||
myDocument.addDocumentListener(myDocumentListener);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myInitialized = true;
|
||||
if (myDocumentListener == null) {
|
||||
myDocumentListener = new MyDocumentListener();
|
||||
myDocument.addDocumentListener(myDocumentListener);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void reinstallRanges() {
|
||||
myApplication.assertIsDispatchThread();
|
||||
|
||||
synchronized (myLock) {
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
try {
|
||||
myRanges = new RangesBuilder(myDocument, myVcsDocument, myMode).getRanges();
|
||||
}
|
||||
catch (FilesTooBigForDiffException e) {
|
||||
installAnathema();
|
||||
return;
|
||||
}
|
||||
for (final Range range : myRanges) {
|
||||
range.setHighlighter(createHighlighter(range));
|
||||
}
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
try {
|
||||
myRanges = new RangesBuilder(myDocument, myVcsDocument, myMode).getRanges();
|
||||
}
|
||||
catch (FilesTooBigForDiffException e) {
|
||||
installAnathema();
|
||||
return;
|
||||
}
|
||||
for (final Range range : myRanges) {
|
||||
range.setHighlighter(createHighlighter(range));
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void installAnathema() {
|
||||
myAnathemaThrown = true;
|
||||
final FileEditor[] editors = myFileEditorManager.getAllEditors(myVirtualFile);
|
||||
@@ -161,6 +161,7 @@ public class LineStatusTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void removeAnathema() {
|
||||
if (!myAnathemaThrown) return;
|
||||
myAnathemaThrown = false;
|
||||
@@ -174,15 +175,15 @@ public class LineStatusTracker {
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public void setMode(@NotNull Mode mode) {
|
||||
synchronized (myLock) {
|
||||
if (myMode == mode) return;
|
||||
myMode = mode;
|
||||
reinstallRanges();
|
||||
}
|
||||
if (myMode == mode) return;
|
||||
myMode = mode;
|
||||
reinstallRanges();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@CalledInAwt
|
||||
private RangeHighlighter createHighlighter(@NotNull Range range) {
|
||||
myApplication.assertIsDispatchThread();
|
||||
|
||||
@@ -225,31 +226,35 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
public void release() {
|
||||
synchronized (myLock) {
|
||||
myReleased = true;
|
||||
if (myDocumentListener != null) {
|
||||
myDocument.removeDocumentListener(myDocumentListener);
|
||||
}
|
||||
myApplication.runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myReleased) return;
|
||||
myReleased = true;
|
||||
if (myDocumentListener != null) {
|
||||
myDocument.removeDocumentListener(myDocumentListener);
|
||||
}
|
||||
|
||||
if (myApplication.isDispatchThread()) {
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
if (myApplication.isDispatchThread()) {
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
else {
|
||||
invalidateRanges();
|
||||
myApplication.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
invalidateRanges();
|
||||
myApplication.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Project getProject() {
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
|
||||
@@ -269,51 +274,46 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@CalledWithReadLock
|
||||
public List<Range> getRanges() {
|
||||
synchronized (myLock) {
|
||||
return myRanges;
|
||||
}
|
||||
return Collections.unmodifiableList(myRanges);
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public void startBulkUpdate() {
|
||||
synchronized (myLock) {
|
||||
if (myReleased) return;
|
||||
if (myReleased) return;
|
||||
|
||||
myBulkUpdate = true;
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
myBulkUpdate = true;
|
||||
removeAnathema();
|
||||
removeHighlightersFromMarkupModel();
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
private void removeHighlightersFromMarkupModel() {
|
||||
myApplication.assertIsDispatchThread();
|
||||
|
||||
synchronized (myLock) {
|
||||
for (Range range : myRanges) {
|
||||
if (range.getHighlighter() != null) {
|
||||
range.getHighlighter().dispose();
|
||||
}
|
||||
range.invalidate();
|
||||
for (Range range : myRanges) {
|
||||
if (range.getHighlighter() != null) {
|
||||
range.getHighlighter().dispose();
|
||||
}
|
||||
myRanges.clear();
|
||||
range.invalidate();
|
||||
}
|
||||
myRanges.clear();
|
||||
}
|
||||
|
||||
@CalledWithReadLock
|
||||
private void invalidateRanges() {
|
||||
synchronized (myLock) {
|
||||
for (Range range : myRanges) {
|
||||
range.invalidate();
|
||||
}
|
||||
for (Range range : myRanges) {
|
||||
range.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public void finishBulkUpdate() {
|
||||
synchronized (myLock) {
|
||||
if (myReleased) return;
|
||||
if (myReleased) return;
|
||||
|
||||
myBulkUpdate = false;
|
||||
reinstallRanges();
|
||||
}
|
||||
myBulkUpdate = false;
|
||||
reinstallRanges();
|
||||
}
|
||||
|
||||
private void markFileUnchanged() {
|
||||
@@ -321,11 +321,7 @@ public class LineStatusTracker {
|
||||
@Override
|
||||
public void run() {
|
||||
FileDocumentManager.getInstance().saveDocument(myDocument);
|
||||
boolean stillEmpty;
|
||||
synchronized (myLock) {
|
||||
stillEmpty = myRanges.isEmpty();
|
||||
}
|
||||
if (stillEmpty) {
|
||||
if (myRanges.isEmpty()) {
|
||||
// file was modified, and now it's not -> dirty local change
|
||||
myVcsDirtyScopeManager.fileDirty(myVirtualFile);
|
||||
}
|
||||
@@ -346,27 +342,25 @@ public class LineStatusTracker {
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
myApplication.assertIsDispatchThread();
|
||||
if (myReleased) return;
|
||||
|
||||
synchronized (myLock) {
|
||||
if (myReleased) return;
|
||||
if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || !myInitialized) return;
|
||||
assert myDocument == e.getDocument();
|
||||
if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || !myInitialized) return;
|
||||
assert myDocument == e.getDocument();
|
||||
|
||||
try {
|
||||
myLine1 = myDocument.getLineNumber(e.getOffset());
|
||||
if (e.getOldLength() == 0) {
|
||||
myBeforeChangedLines = 1;
|
||||
}
|
||||
else {
|
||||
int line1 = myLine1;
|
||||
int line2 = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
|
||||
myBeforeChangedLines = line2 - line1 + 1;
|
||||
}
|
||||
|
||||
myBeforeTotalLines = getLineCount(myDocument);
|
||||
try {
|
||||
myLine1 = myDocument.getLineNumber(e.getOffset());
|
||||
if (e.getOldLength() == 0) {
|
||||
myBeforeChangedLines = 1;
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
else {
|
||||
int line1 = myLine1;
|
||||
int line2 = myDocument.getLineNumber(e.getOffset() + e.getOldLength());
|
||||
myBeforeChangedLines = line2 - line1 + 1;
|
||||
}
|
||||
|
||||
myBeforeTotalLines = getLineCount(myDocument);
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,32 +368,30 @@ public class LineStatusTracker {
|
||||
public void documentChanged(final DocumentEvent e) {
|
||||
myApplication.assertIsDispatchThread();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (myReleased) return;
|
||||
if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || !myInitialized) return;
|
||||
assert myDocument == e.getDocument();
|
||||
if (myReleased) return;
|
||||
if (myBulkUpdate || mySuppressUpdate || myAnathemaThrown || !myInitialized) return;
|
||||
assert myDocument == e.getDocument();
|
||||
|
||||
int afterChangedLines;
|
||||
if (e.getNewLength() == 0) {
|
||||
afterChangedLines = 1;
|
||||
}
|
||||
else {
|
||||
int line1 = myLine1;
|
||||
int line2 = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
|
||||
afterChangedLines = line2 - line1 + 1;
|
||||
}
|
||||
|
||||
int linesShift = afterChangedLines - myBeforeChangedLines;
|
||||
|
||||
int line1 = myLine1;
|
||||
int line2 = line1 + myBeforeChangedLines;
|
||||
|
||||
int[] fixed = fixRanges(e, line1, line2);
|
||||
line1 = fixed[0];
|
||||
line2 = fixed[1];
|
||||
|
||||
doUpdateRanges(line1, line2, linesShift, myBeforeTotalLines);
|
||||
int afterChangedLines;
|
||||
if (e.getNewLength() == 0) {
|
||||
afterChangedLines = 1;
|
||||
}
|
||||
else {
|
||||
int line1 = myLine1;
|
||||
int line2 = myDocument.getLineNumber(e.getOffset() + e.getNewLength());
|
||||
afterChangedLines = line2 - line1 + 1;
|
||||
}
|
||||
|
||||
int linesShift = afterChangedLines - myBeforeChangedLines;
|
||||
|
||||
int line1 = myLine1;
|
||||
int line2 = line1 + myBeforeChangedLines;
|
||||
|
||||
int[] fixed = fixRanges(e, line1, line2);
|
||||
line1 = fixed[0];
|
||||
line2 = fixed[1];
|
||||
|
||||
doUpdateRanges(line1, line2, linesShift, myBeforeTotalLines);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,10 +515,10 @@ public class LineStatusTracker {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
if (changedLine1 == changedLine2) {
|
||||
return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2, Range.DELETED));
|
||||
return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2));
|
||||
}
|
||||
if (vcsLine1 == vcsLine2) {
|
||||
return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2, Range.INSERTED));
|
||||
return Collections.singletonList(new Range(changedLine1, changedLine2, vcsLine1, vcsLine2));
|
||||
}
|
||||
|
||||
List<String> lines = new DocumentWrapper(myDocument).getLines(changedLine1, changedLine2 - 1);
|
||||
@@ -676,109 +668,73 @@ public class LineStatusTracker {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Range getNextRange(final Range range) {
|
||||
synchronized (myLock) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index == myRanges.size() - 1) return null;
|
||||
return myRanges.get(index + 1);
|
||||
}
|
||||
@CalledWithReadLock
|
||||
public Range getNextRange(Range range) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index == myRanges.size() - 1) return null;
|
||||
return myRanges.get(index + 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Range getPrevRange(final Range range) {
|
||||
synchronized (myLock) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index <= 0) return null;
|
||||
return myRanges.get(index - 1);
|
||||
}
|
||||
@CalledWithReadLock
|
||||
public Range getPrevRange(Range range) {
|
||||
final int index = myRanges.indexOf(range);
|
||||
if (index <= 0) return null;
|
||||
return myRanges.get(index - 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getNextRange(final int line) {
|
||||
synchronized (myLock) {
|
||||
for (Range range : myRanges) {
|
||||
if (line < range.getLine2() && !range.isSelectedByLine(line)) {
|
||||
return range;
|
||||
}
|
||||
@CalledWithReadLock
|
||||
public Range getNextRange(int line) {
|
||||
for (Range range : myRanges) {
|
||||
if (line < range.getLine2() && !range.isSelectedByLine(line)) {
|
||||
return range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getPrevRange(final int line) {
|
||||
synchronized (myLock) {
|
||||
for (int i = myRanges.size() - 1; i >= 0; i--) {
|
||||
Range range = myRanges.get(i);
|
||||
if (line > range.getLine1() && !range.isSelectedByLine(line)) {
|
||||
return range;
|
||||
}
|
||||
@CalledWithReadLock
|
||||
public Range getPrevRange(int line) {
|
||||
for (int i = myRanges.size() - 1; i >= 0; i--) {
|
||||
Range range = myRanges.get(i);
|
||||
if (line > range.getLine1() && !range.isSelectedByLine(line)) {
|
||||
return range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Range getRangeForLine(final int line) {
|
||||
synchronized (myLock) {
|
||||
for (final Range range : myRanges) {
|
||||
if (range.isSelectedByLine(line)) return range;
|
||||
}
|
||||
return null;
|
||||
@CalledWithReadLock
|
||||
public Range getRangeForLine(int line) {
|
||||
for (final Range range : myRanges) {
|
||||
if (range.isSelectedByLine(line)) return range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
private void doRollbackRange(@NotNull Range range) {
|
||||
if (range.getType() == Range.MODIFIED) {
|
||||
TextRange currentTextRange = getCurrentTextRange(range);
|
||||
int offset1 = currentTextRange.getStartOffset();
|
||||
int offset2 = currentTextRange.getEndOffset();
|
||||
|
||||
CharSequence vcsContent = getVcsContent(range);
|
||||
myDocument.replaceString(offset1, offset2, vcsContent);
|
||||
}
|
||||
else if (range.getType() == Range.INSERTED) {
|
||||
TextRange currentTextRange = getCurrentTextRange(range);
|
||||
int offset1 = currentTextRange.getStartOffset();
|
||||
int offset2 = currentTextRange.getEndOffset();
|
||||
|
||||
if (offset1 > 0) {
|
||||
offset1--;
|
||||
}
|
||||
else if (offset2 < myDocument.getTextLength()) {
|
||||
offset2++;
|
||||
}
|
||||
myDocument.deleteString(offset1, offset2);
|
||||
}
|
||||
else if (range.getType() == Range.DELETED) {
|
||||
CharSequence content = getVcsContent(range);
|
||||
if (range.getLine2() == getLineCount(myDocument)) {
|
||||
myDocument.insertString(myDocument.getTextLength(), "\n" + content);
|
||||
}
|
||||
else {
|
||||
myDocument.insertString(myDocument.getLineStartOffset(range.getLine2()), content + "\n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown range type: " + range.getType());
|
||||
}
|
||||
DiffUtil.applyModification(myDocument, range.getLine1(), range.getLine2(), myVcsDocument, range.getVcsLine1(), range.getVcsLine2());
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
public void rollbackChanges(@NotNull Range range) {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (myBulkUpdate) return;
|
||||
if (myBulkUpdate) return;
|
||||
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Rollback of invalid range");
|
||||
return;
|
||||
}
|
||||
|
||||
doRollbackRange(range);
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Rollback of invalid range");
|
||||
return;
|
||||
}
|
||||
|
||||
doRollbackRange(range);
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
public void rollbackChanges(@NotNull final BitSet lines) {
|
||||
runBulkRollback(new Runnable() {
|
||||
@Override
|
||||
@@ -793,14 +749,7 @@ public class LineStatusTracker {
|
||||
break;
|
||||
}
|
||||
|
||||
boolean check;
|
||||
if (range.getLine1() == range.getLine2()) {
|
||||
check = lines.get(range.getLine1());
|
||||
}
|
||||
else {
|
||||
int next = lines.nextSetBit(range.getLine1());
|
||||
check = next != -1 && next < range.getLine2();
|
||||
}
|
||||
boolean check = DiffUtil.isSelectedByLine(lines, range.getLine1(), range.getLine2());
|
||||
|
||||
if (check) {
|
||||
if (first == null) {
|
||||
@@ -829,6 +778,7 @@ public class LineStatusTracker {
|
||||
});
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
public void rollbackAllChanges() {
|
||||
runBulkRollback(new Runnable() {
|
||||
@Override
|
||||
@@ -843,88 +793,74 @@ public class LineStatusTracker {
|
||||
});
|
||||
}
|
||||
|
||||
@CalledWithWriteLock
|
||||
private void runBulkRollback(@NotNull Runnable task) {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (myBulkUpdate) return;
|
||||
if (myBulkUpdate) return;
|
||||
|
||||
try {
|
||||
mySuppressUpdate = true;
|
||||
try {
|
||||
mySuppressUpdate = true;
|
||||
|
||||
task.run();
|
||||
}
|
||||
catch (Error e) {
|
||||
reinstallRanges();
|
||||
throw e;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
reinstallRanges();
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
mySuppressUpdate = false;
|
||||
}
|
||||
task.run();
|
||||
}
|
||||
catch (Error e) {
|
||||
reinstallRanges();
|
||||
throw e;
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
reinstallRanges();
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
mySuppressUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@CalledWithReadLock
|
||||
public CharSequence getCurrentContent(@NotNull Range range) {
|
||||
TextRange textRange = getCurrentTextRange(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = textRange.getEndOffset();
|
||||
return myDocument.getImmutableCharSequence().subSequence(startOffset, endOffset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@CalledWithReadLock
|
||||
public CharSequence getVcsContent(@NotNull Range range) {
|
||||
synchronized (myLock) {
|
||||
TextRange textRange = getVcsRange(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = textRange.getEndOffset();
|
||||
return myVcsDocument.getCharsSequence().subSequence(startOffset, endOffset);
|
||||
}
|
||||
TextRange textRange = getVcsTextRange(range);
|
||||
final int startOffset = textRange.getStartOffset();
|
||||
final int endOffset = textRange.getEndOffset();
|
||||
return myVcsDocument.getImmutableCharSequence().subSequence(startOffset, endOffset);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
TextRange getCurrentTextRange(@NotNull Range range) {
|
||||
myApplication.assertReadAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Current TextRange of invalid range");
|
||||
}
|
||||
|
||||
return getRange(range.getLine1(), range.getLine2(), myDocument);
|
||||
@CalledWithReadLock
|
||||
public TextRange getCurrentTextRange(@NotNull Range range) {
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Current TextRange of invalid range");
|
||||
}
|
||||
|
||||
return DiffUtil.getLinesRange(myDocument, range.getLine1(), range.getLine2());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
TextRange getVcsRange(@NotNull Range range) {
|
||||
synchronized (myLock) {
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Vcs TextRange of invalid range");
|
||||
}
|
||||
|
||||
return getRange(range.getVcsLine1(), range.getVcsLine2(), myVcsDocument);
|
||||
@CalledWithReadLock
|
||||
public TextRange getVcsTextRange(@NotNull Range range) {
|
||||
if (!range.isValid()) {
|
||||
LOG.warn("Vcs TextRange of invalid range");
|
||||
}
|
||||
|
||||
return DiffUtil.getLinesRange(myVcsDocument, range.getVcsLine1(), range.getVcsLine2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return affected range, without non-internal '\n'
|
||||
* so if last line is not empty, the last symbol will be not '\n'
|
||||
* <p/>
|
||||
* So we consider '\n' not as a part of line, but a separator between lines
|
||||
*/
|
||||
@NotNull
|
||||
private static TextRange getRange(int line1, int line2, @NotNull Document document) {
|
||||
if (line1 == line2) {
|
||||
int lineStartOffset = line1 < getLineCount(document) ? document.getLineStartOffset(line1) : document.getTextLength();
|
||||
return new TextRange(lineStartOffset, lineStartOffset);
|
||||
}
|
||||
else {
|
||||
int startOffset = document.getLineStartOffset(line1);
|
||||
int endOffset = document.getLineEndOffset(line2 - 1);
|
||||
return new TextRange(startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
public static LineStatusTracker createOn(@NotNull VirtualFile virtualFile, @NotNull final Document doc, final Project project,
|
||||
public static LineStatusTracker createOn(@NotNull VirtualFile virtualFile, @NotNull final Document document, final Project project,
|
||||
@NotNull Mode mode) {
|
||||
final Document document = new DocumentImpl("", true);
|
||||
document.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
|
||||
return new LineStatusTracker(doc, document, project, virtualFile, mode);
|
||||
final Document vcsDocument = new DocumentImpl("", true);
|
||||
vcsDocument.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
|
||||
return new LineStatusTracker(document, vcsDocument, project, virtualFile, mode);
|
||||
}
|
||||
|
||||
public static class RevisionPack {
|
||||
@@ -965,13 +901,9 @@ public class LineStatusTracker {
|
||||
}
|
||||
}
|
||||
|
||||
public static class CanNotCalculateDiffPanel extends EditorNotificationPanel {
|
||||
private static class CanNotCalculateDiffPanel extends EditorNotificationPanel {
|
||||
public CanNotCalculateDiffPanel() {
|
||||
myLabel.setText("Can not highlight changed lines. File is too big and there are too many changes.");
|
||||
}
|
||||
}
|
||||
|
||||
private static int getLineCount(@NotNull Document document) {
|
||||
return Math.max(document.getLineCount(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,14 @@ package com.intellij.openapi.vcs.ex;
|
||||
import com.intellij.codeInsight.hint.EditorFragmentComponent;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.hint.HintManagerImpl;
|
||||
import com.intellij.diff.comparison.ByWord;
|
||||
import com.intellij.diff.comparison.ComparisonPolicy;
|
||||
import com.intellij.diff.comparison.DiffTooBigException;
|
||||
import com.intellij.diff.fragments.DiffFragment;
|
||||
import com.intellij.diff.util.BackgroundTaskUtil;
|
||||
import com.intellij.diff.util.DiffDrawUtil;
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.diff.util.TextDiffType;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.diff.DiffColors;
|
||||
@@ -32,8 +40,11 @@ import com.intellij.openapi.editor.highlighter.EditorHighlighter;
|
||||
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
|
||||
import com.intellij.openapi.editor.markup.ActiveGutterRenderer;
|
||||
import com.intellij.openapi.editor.markup.LineMarkerRenderer;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vcs.actions.ShowNextChangeMarkerAction;
|
||||
import com.intellij.openapi.vcs.actions.ShowPrevChangeMarkerAction;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -41,6 +52,7 @@ import com.intellij.ui.ColoredSideBorder;
|
||||
import com.intellij.ui.HintHint;
|
||||
import com.intellij.ui.HintListener;
|
||||
import com.intellij.ui.LightweightHint;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -49,6 +61,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventObject;
|
||||
import java.util.List;
|
||||
|
||||
@@ -256,7 +269,7 @@ public class LineStatusTrackerDrawing {
|
||||
|
||||
component.add(toolbarPanel, BorderLayout.NORTH);
|
||||
|
||||
|
||||
final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
|
||||
if (range.getType() != Range.INSERTED) {
|
||||
final DocumentEx doc = (DocumentEx)tracker.getVcsDocument();
|
||||
final EditorEx uEditor = (EditorEx)EditorFactory.getInstance().createViewer(doc, tracker.getProject());
|
||||
@@ -265,6 +278,36 @@ public class LineStatusTrackerDrawing {
|
||||
EditorHighlighterFactory.getInstance().createEditorHighlighter(tracker.getProject(), getFileName(tracker.getDocument()));
|
||||
uEditor.setHighlighter(highlighter);
|
||||
|
||||
try {
|
||||
if (range.getType() == Range.MODIFIED) {
|
||||
final CharSequence vcsContent = tracker.getVcsContent(range);
|
||||
final CharSequence currentContent = tracker.getCurrentContent(range);
|
||||
|
||||
List<DiffFragment> diff = BackgroundTaskUtil.tryComputeFast(new Function<ProgressIndicator, List<DiffFragment>>() {
|
||||
@Override
|
||||
public List<DiffFragment> fun(ProgressIndicator indicator) {
|
||||
return ByWord.compare(vcsContent, currentContent, ComparisonPolicy.DEFAULT, indicator);
|
||||
}
|
||||
}, Registry.intValue("diff.status.tracker.byword.delay"));
|
||||
if (diff == null) throw new DiffTooBigException();
|
||||
|
||||
int vcsStartShift = tracker.getVcsTextRange(range).getStartOffset();
|
||||
int currentStartShift = tracker.getCurrentTextRange(range).getStartOffset();
|
||||
for (DiffFragment fragment : diff) {
|
||||
int vcsStart = vcsStartShift + fragment.getStartOffset1();
|
||||
int vcsEnd = vcsStartShift + fragment.getEndOffset1();
|
||||
int currentStart = currentStartShift + fragment.getStartOffset2();
|
||||
int currentEnd = currentStartShift + fragment.getEndOffset2();
|
||||
TextDiffType type = DiffUtil.getDiffType(fragment);
|
||||
|
||||
DiffDrawUtil.createInlineHighlighter(uEditor, vcsStart, vcsEnd, type);
|
||||
highlighters.add(DiffDrawUtil.createInlineHighlighter(editor, currentStart, currentEnd, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (DiffTooBigException ignore) {
|
||||
}
|
||||
|
||||
final EditorFragmentComponent editorFragmentComponent =
|
||||
EditorFragmentComponent.createEditorFragmentComponent(uEditor, range.getVcsLine1(), range.getVcsLine2(), false, false);
|
||||
|
||||
@@ -284,6 +327,9 @@ public class LineStatusTrackerDrawing {
|
||||
actionList.remove(copyRange);
|
||||
actionList.remove(localShowPrevAction);
|
||||
actionList.remove(localShowNextAction);
|
||||
for (RangeHighlighter highlighter : highlighters) {
|
||||
highlighter.dispose();
|
||||
}
|
||||
}
|
||||
};
|
||||
hint.addHintListener(closeListener);
|
||||
|
||||
@@ -15,18 +15,14 @@
|
||||
*/
|
||||
package com.intellij.openapi.vcs.ex;
|
||||
|
||||
import com.intellij.diff.util.DiffUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.util.diff.Diff;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author: lesya
|
||||
*/
|
||||
public class Range {
|
||||
private static final Logger LOG = Logger.getInstance(Range.class);
|
||||
public static final byte EQUAL = 0;
|
||||
@@ -41,81 +37,64 @@ public class Range {
|
||||
private int myLine2;
|
||||
private final int myVcsLine1;
|
||||
private final int myVcsLine2;
|
||||
private final byte myType;
|
||||
@Nullable private RangeHighlighter myRangeHighlighter;
|
||||
|
||||
@Nullable private final List<InnerRange> myInnerRanges;
|
||||
|
||||
@Nullable private RangeHighlighter myRangeHighlighter;
|
||||
private boolean myValid = true;
|
||||
|
||||
public Range(@NotNull Range range) {
|
||||
this(range.getLine1(), range.getLine2(), range.getVcsLine1(), range.getVcsLine2(), range.getType());
|
||||
this(range.getLine1(), range.getLine2(), range.getVcsLine1(), range.getVcsLine2());
|
||||
}
|
||||
|
||||
public Range(int line1, int line2, int vcsLine1, int vcsLine2, byte type) {
|
||||
this(line1, line2, vcsLine1, vcsLine2, type, null);
|
||||
public Range(int line1, int line2, int vcsLine1, int vcsLine2) {
|
||||
this(line1, line2, vcsLine1, vcsLine2, null);
|
||||
}
|
||||
|
||||
public Range(int line1, int line2, int vcsLine1, int vcsLine2, byte type, @Nullable List<InnerRange> innerRanges) {
|
||||
public Range(int line1, int line2, int vcsLine1, int vcsLine2, @Nullable List<InnerRange> innerRanges) {
|
||||
assert line1 != line2 || vcsLine1 != vcsLine2;
|
||||
|
||||
myLine1 = line1;
|
||||
myLine2 = line2;
|
||||
myVcsLine1 = vcsLine1;
|
||||
myVcsLine2 = vcsLine2;
|
||||
myType = type;
|
||||
myInnerRanges = innerRanges;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return myVcsLine1 ^ myVcsLine2 ^ myType ^ myLine1 ^ myLine2;
|
||||
return myVcsLine1 ^ myVcsLine2 ^ myLine1 ^ myLine2;
|
||||
}
|
||||
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof Range)) return false;
|
||||
Range other = (Range)object;
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
if (myInnerRanges != null) {
|
||||
if (other.myInnerRanges == null) return false;
|
||||
if (myInnerRanges.size() != other.myInnerRanges.size()) return false;
|
||||
Range range = (Range)o;
|
||||
|
||||
for (int i = 0; i < myInnerRanges.size(); i++) {
|
||||
if (!myInnerRanges.get(i).equals(other.myInnerRanges.get(i))) return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (other.myInnerRanges != null) return false;
|
||||
if (myLine1 != range.myLine1) return false;
|
||||
if (myLine2 != range.myLine2) return false;
|
||||
if (myVcsLine1 != range.myVcsLine1) return false;
|
||||
if (myVcsLine2 != range.myVcsLine2) return false;
|
||||
|
||||
if (myInnerRanges == null) return range.myInnerRanges == null;
|
||||
if (range.myInnerRanges == null) return false;
|
||||
|
||||
if (myInnerRanges.size() != range.myInnerRanges.size()) return false;
|
||||
for (int i = 0; i < myInnerRanges.size(); i++) {
|
||||
if (!myInnerRanges.get(i).equals(range.myInnerRanges.get(i))) return false;
|
||||
}
|
||||
|
||||
return
|
||||
(myVcsLine1 == other.myVcsLine1)
|
||||
&& (myVcsLine2 == other.myVcsLine2)
|
||||
&& (myLine1 == other.myLine1)
|
||||
&& (myLine2 == other.myLine2)
|
||||
&& (myType == other.myType);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s, %s, %s, %s, %s", myLine1, myLine2, myVcsLine1, myVcsLine2, getTypeName());
|
||||
}
|
||||
|
||||
@NonNls
|
||||
private String getTypeName() {
|
||||
switch (myType) {
|
||||
case MODIFIED:
|
||||
return "MODIFIED";
|
||||
case INSERTED:
|
||||
return "INSERTED";
|
||||
case DELETED:
|
||||
return "DELETED";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
return String.format("%s, %s, %s, %s", myLine1, myLine2, myVcsLine1, myVcsLine2);
|
||||
}
|
||||
|
||||
public byte getType() {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public int getUpToDateRangeLength() {
|
||||
return myVcsLine2 - myVcsLine1;
|
||||
if (myLine1 == myLine2) return DELETED;
|
||||
if (myVcsLine1 == myVcsLine2) return INSERTED;
|
||||
return MODIFIED;
|
||||
}
|
||||
|
||||
public void shift(int shift) {
|
||||
@@ -150,15 +129,11 @@ public class Range {
|
||||
return myVcsLine2;
|
||||
}
|
||||
|
||||
public boolean rightBefore(@NotNull Range range) {
|
||||
return myLine2 == range.myLine1;
|
||||
}
|
||||
|
||||
public boolean hasHighlighter() {
|
||||
return myRangeHighlighter != null;
|
||||
}
|
||||
|
||||
public void setHighlighter(RangeHighlighter highlighter) {
|
||||
public void setHighlighter(@Nullable RangeHighlighter highlighter) {
|
||||
myRangeHighlighter = highlighter;
|
||||
}
|
||||
|
||||
@@ -210,8 +185,8 @@ public class Range {
|
||||
|
||||
InnerRange range = (InnerRange)o;
|
||||
|
||||
if (myLine2 != range.myLine2) return false;
|
||||
if (myLine1 != range.myLine1) return false;
|
||||
if (myLine2 != range.myLine2) return false;
|
||||
if (myType != range.myType) return false;
|
||||
|
||||
return true;
|
||||
@@ -226,22 +201,7 @@ public class Range {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return String.format("%s, %s, %s", myLine1, myLine2, getTypeName());
|
||||
}
|
||||
|
||||
@NonNls
|
||||
private String getTypeName() {
|
||||
switch (myType) {
|
||||
case MODIFIED:
|
||||
return "MODIFIED";
|
||||
case INSERTED:
|
||||
return "INSERTED";
|
||||
case DELETED:
|
||||
return "DELETED";
|
||||
case EQUAL:
|
||||
return "EQUAL";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
return String.format("%s, %s, %s", myLine1, myLine2, getTypeName(myType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,12 +209,21 @@ public class Range {
|
||||
* Check, if caret at <line> is corresponds to the current range
|
||||
*/
|
||||
public boolean isSelectedByLine(int line) {
|
||||
if (getType() == DELETED && line == myLine1) {
|
||||
return true;
|
||||
return DiffUtil.isSelectedByLine(line, myLine1, myLine2);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTypeName(byte type) {
|
||||
switch (type) {
|
||||
case MODIFIED:
|
||||
return "MODIFIED";
|
||||
case INSERTED:
|
||||
return "INSERTED";
|
||||
case DELETED:
|
||||
return "DELETED";
|
||||
case EQUAL:
|
||||
return "EQUAL";
|
||||
}
|
||||
else if (line >= myLine1 && line < myLine2) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return "UNKNOWN(" + type + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,15 +101,13 @@ public class RangesBuilder {
|
||||
}
|
||||
|
||||
private static Range createOn(@NotNull Diff.Change change, int shift, int vcsShift) {
|
||||
byte type = getChangeType(change);
|
||||
|
||||
int offset1 = shift + change.line1;
|
||||
int offset2 = offset1 + change.inserted;
|
||||
|
||||
int uOffset1 = vcsShift + change.line0;
|
||||
int uOffset2 = uOffset1 + change.deleted;
|
||||
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, type);
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2);
|
||||
}
|
||||
|
||||
private static Range createOnSmart(@NotNull Diff.Change change,
|
||||
@@ -126,7 +124,7 @@ public class RangesBuilder {
|
||||
int uOffset2 = uOffset1 + change.deleted;
|
||||
|
||||
if (type != Range.MODIFIED) {
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, type, Collections.singletonList(new Range.InnerRange(offset1, offset2, type)));
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, Collections.singletonList(new Range.InnerRange(offset1, offset2, type)));
|
||||
}
|
||||
|
||||
LineWrapper[] lines1 = new LineWrapper[change.deleted];
|
||||
@@ -169,7 +167,7 @@ public class RangesBuilder {
|
||||
inner.add(new Range.InnerRange(innerStart, innerEnd, innerType));
|
||||
}
|
||||
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, type, inner);
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, inner);
|
||||
}
|
||||
|
||||
private static byte getChangeType(@NotNull Diff.Change change) {
|
||||
|
||||
+2
-3
@@ -16,7 +16,6 @@
|
||||
package com.intellij.openapi.vcs.ex;
|
||||
|
||||
import com.intellij.diff.DiffContentFactory;
|
||||
import com.intellij.diff.DiffDialogHints;
|
||||
import com.intellij.diff.DiffManager;
|
||||
import com.intellij.diff.actions.DocumentFragmentContent;
|
||||
import com.intellij.diff.contents.DiffContent;
|
||||
@@ -53,7 +52,7 @@ public class ShowLineStatusRangeDiffAction extends BaseLineStatusRangeAction {
|
||||
Range range = expand(myRange, myLineStatusTracker.getDocument(), myLineStatusTracker.getVcsDocument());
|
||||
|
||||
DiffContent vcsContent = createDiffContent(myLineStatusTracker.getVcsDocument(),
|
||||
myLineStatusTracker.getVcsRange(range),
|
||||
myLineStatusTracker.getVcsTextRange(range),
|
||||
null);
|
||||
DiffContent currentContent = createDiffContent(myLineStatusTracker.getDocument(),
|
||||
myLineStatusTracker.getCurrentTextRange(range),
|
||||
@@ -81,6 +80,6 @@ public class ShowLineStatusRangeDiffAction extends BaseLineStatusRangeAction {
|
||||
int uOffset1 = range.getVcsLine1() - (canExpandBefore ? 1 : 0);
|
||||
int offset2 = range.getLine2() + (canExpandAfter ? 1 : 0);
|
||||
int uOffset2 = range.getVcsLine2() + (canExpandAfter ? 1 : 0);
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2, range.getType());
|
||||
return new Range(offset1, offset2, uOffset1, uOffset2);
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,7 @@ import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.CalledInAwt;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -208,6 +209,7 @@ public class LineStatusTrackerManager implements ProjectComponent, LineStatusTra
|
||||
}
|
||||
}
|
||||
|
||||
@CalledInAwt
|
||||
public void updateSettings() {
|
||||
synchronized (myLock) {
|
||||
LineStatusTracker.Mode mode = getMode();
|
||||
|
||||
+11
-11
@@ -44,7 +44,7 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
|
||||
}
|
||||
return calcLineNumber(tracker, currentNumber);
|
||||
}
|
||||
|
||||
|
||||
public boolean isRangeChanged(final int start, final int end) {
|
||||
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(myProject).getLineStatusTracker(myDocument);
|
||||
if (tracker == null) {
|
||||
@@ -60,7 +60,7 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static boolean lineInRange(final Range range, final int currentNumber) {
|
||||
return range.getLine1() <= currentNumber && range.getLine2() >= currentNumber;
|
||||
}
|
||||
@@ -106,23 +106,23 @@ public class UpToDateLineNumberProviderImpl implements UpToDateLineNumberProvide
|
||||
|
||||
private static int calcLineNumber(LineStatusTracker tracker, int currentNumber){
|
||||
if (tracker == null) return -1;
|
||||
List ranges = tracker.getRanges();
|
||||
List<Range> ranges = tracker.getRanges();
|
||||
int result = currentNumber;
|
||||
|
||||
for (final Object range1 : ranges) {
|
||||
Range range = (Range)range1;
|
||||
int startOffset = range.getLine1();
|
||||
int endOffset = range.getLine2();
|
||||
for (final Range range : ranges) {
|
||||
int startLine = range.getLine1();
|
||||
int endLine = range.getLine2();
|
||||
|
||||
if ((startOffset <= currentNumber) && (endOffset > currentNumber)) {
|
||||
if ((startLine <= currentNumber) && (endLine > currentNumber)) {
|
||||
return ABSENT_LINE_NUMBER;
|
||||
}
|
||||
|
||||
if (endOffset > currentNumber) return result;
|
||||
if (endLine > currentNumber) return result;
|
||||
|
||||
int currentRangeLength = endOffset - startOffset;
|
||||
int currentRangeLength = endLine - startLine;
|
||||
int vcsRangeLength = range.getVcsLine2() - range.getVcsLine1();
|
||||
|
||||
result += range.getUpToDateRangeLength() - currentRangeLength;
|
||||
result += vcsRangeLength - currentRangeLength;
|
||||
}
|
||||
return result;
|
||||
|
||||
|
||||
+1
-2
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.plugins.groovy.lang.psi.stubs;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.stubs.PsiFileStubImpl;
|
||||
import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -34,7 +33,7 @@ public class GrFileStub extends PsiFileStubImpl<GroovyFile> {
|
||||
|
||||
public GrFileStub(GroovyFile file) {
|
||||
super(file);
|
||||
myName = StringRef.fromString(StringUtil.trimEnd(file.getName(), ".groovy"));
|
||||
myName = StringRef.fromString(file.getViewProvider().getVirtualFile().getNameWithoutExtension());
|
||||
isScript = file.isScript();
|
||||
final GrPackageDefinition definition = file.getPackageDefinition();
|
||||
if (definition != null) {
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class GrStubFileElementType extends IStubFileElementType<GrFileStub> {
|
||||
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
return super.getStubVersion() + 21;
|
||||
return super.getStubVersion() + 22;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,8 +32,7 @@ public class GroovyFileTypeLoader extends FileTypeFactory{
|
||||
public static Set<String> getCustomGroovyScriptExtensions() {
|
||||
final LinkedHashSet<String> strings = new LinkedHashSet<String>();
|
||||
strings.add("gdsl");
|
||||
strings.add("gpp");
|
||||
strings.add("grunit");
|
||||
strings.add("gy");
|
||||
for (GroovyScriptTypeDetector ep : GroovyScriptTypeDetector.EP_NAME.getExtensions()) {
|
||||
Collections.addAll(strings, ep.getExtensions());
|
||||
}
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ public class GroovyCodeFragmentFactory extends CodeFragmentFactory {
|
||||
"java.lang.Object |res = ((groovy.lang.MetaClassImpl)|emc).invokeStaticMethod(|clazz, \""
|
||||
).append(EVAL_NAME).append("\", |resVals);\n");
|
||||
}
|
||||
javaText.append("if (|res instanceof java.lang.Boolean) ((java.lang.Boolean) |res).booleanValue() else |res");
|
||||
javaText.append("|res");
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(toEval.getProject()).getElementFactory();
|
||||
|
||||
|
||||
+11
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package org.jetbrains.java.decompiler.modules.decompiler.stats;
|
||||
|
||||
import org.jetbrains.java.decompiler.code.CodeConstants;
|
||||
import org.jetbrains.java.decompiler.code.cfg.BasicBlock;
|
||||
import org.jetbrains.java.decompiler.main.TextBuffer;
|
||||
import org.jetbrains.java.decompiler.main.collectors.BytecodeMappingTracer;
|
||||
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
|
||||
@@ -84,11 +86,20 @@ public class SynchronizedStatement extends Statement {
|
||||
buf.append(ExprProcessor.jmpWrapper(body, indent + 1, true, tracer));
|
||||
|
||||
buf.appendIndent(indent).append("}").appendLineSeparator();
|
||||
mapMonitorExitInstr(tracer);
|
||||
tracer.incrementCurrentSourceLine();
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void mapMonitorExitInstr(BytecodeMappingTracer tracer) {
|
||||
BasicBlock block = body.getBasichead().getBlock();
|
||||
if (!block.getSeq().isEmpty() && block.getLastInstruction().opcode == CodeConstants.opc_monitorexit) {
|
||||
Integer offset = block.getOldOffset(block.size() - 1);
|
||||
if (offset > -1) tracer.addMapping(offset);
|
||||
}
|
||||
}
|
||||
|
||||
public void initExprents() {
|
||||
headexprent.set(0, first.getExprents().remove(first.getExprents().size() - 1));
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -3,33 +3,37 @@ package pkg;
|
||||
public class TestSynchronizedMapping {
|
||||
public int test(int var1) {
|
||||
synchronized(this) {// 8
|
||||
return var1++;// 9
|
||||
}
|
||||
++var1;// 9
|
||||
}// 10
|
||||
|
||||
return var1++;// 11
|
||||
}
|
||||
|
||||
public void test2(String var1) {
|
||||
System.out.println(var1);// 14
|
||||
}// 15
|
||||
System.out.println(var1);// 15
|
||||
}// 16
|
||||
}
|
||||
|
||||
class 'pkg/TestSynchronizedMapping' {
|
||||
method 'test (I)I' {
|
||||
3 4
|
||||
5 5
|
||||
a 5
|
||||
4 5
|
||||
8 6
|
||||
12 8
|
||||
15 8
|
||||
}
|
||||
|
||||
method 'test2 (Ljava/lang/String;)V' {
|
||||
0 10
|
||||
4 10
|
||||
7 11
|
||||
0 12
|
||||
4 12
|
||||
7 13
|
||||
}
|
||||
}
|
||||
|
||||
Lines mapping:
|
||||
8 <-> 5
|
||||
9 <-> 6
|
||||
14 <-> 11
|
||||
15 <-> 12
|
||||
Not mapped:
|
||||
10
|
||||
10 <-> 7
|
||||
11 <-> 9
|
||||
15 <-> 13
|
||||
16 <-> 14
|
||||
|
||||
@@ -6,8 +6,9 @@ import java.lang.Runnable;
|
||||
public class TestSynchronizedMapping {
|
||||
public int test(int a) {
|
||||
synchronized (this) {
|
||||
return a++;
|
||||
a++;
|
||||
}
|
||||
return a++;
|
||||
}
|
||||
|
||||
public void test2(String a) {
|
||||
|
||||
@@ -81,10 +81,11 @@ class Profiler(object):
|
||||
|
||||
self.start_profiling()
|
||||
|
||||
pydev_imports.execfile(file, globals, globals) # execute the script
|
||||
|
||||
self.stop_profiling()
|
||||
self.save_snapshot(0, generate_snapshot_filepath(base_snapshot_path, remote_run), remote_run)
|
||||
try:
|
||||
pydev_imports.execfile(file, globals, globals) # execute the script
|
||||
finally:
|
||||
self.stop_profiling()
|
||||
self.save_snapshot(0, generate_snapshot_filepath(base_snapshot_path, remote_run), remote_run)
|
||||
|
||||
def start_profiling(self):
|
||||
self.profiling_backend.enable()
|
||||
|
||||
@@ -23,6 +23,7 @@ def run_file(file, globals=None, locals=None):
|
||||
if locals is None:
|
||||
locals = globals
|
||||
|
||||
sys.path.insert(0, os.path.split(file)[0])
|
||||
|
||||
print('Running %s'%file)
|
||||
pydev_imports.execfile(file, globals, locals) # execute the script
|
||||
|
||||
@@ -61,6 +61,7 @@ import com.jetbrains.python.console.PythonDebugLanguageConsoleView;
|
||||
import com.jetbrains.python.console.pydev.PydevCompletionVariant;
|
||||
import com.jetbrains.python.debugger.pydev.*;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyImportElement;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveUtil;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
@@ -854,7 +855,11 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
|
||||
PyResolveUtil.scopeCrawlUp(new PsiScopeProcessor() {
|
||||
@Override
|
||||
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
|
||||
elementRef.set(element);
|
||||
if (!(element instanceof PyImportElement)) {
|
||||
if (elementRef.isNull()) {
|
||||
elementRef.set(element);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@ package com.jetbrains.python.inspections.quickfix;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -26,16 +29,15 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* For:
|
||||
* class B(A):
|
||||
* def __init__(self):
|
||||
* A.__init__(self) # inserted
|
||||
* print "Constructor B was called"
|
||||
*
|
||||
* def __init__(self):
|
||||
* A.__init__(self) # inserted
|
||||
* print "Constructor B was called"
|
||||
* <p/>
|
||||
* User: catherine
|
||||
*/
|
||||
public class AddCallSuperQuickFix implements LocalQuickFix {
|
||||
@@ -52,7 +54,7 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
PyFunction problemFunction = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class);
|
||||
final PyFunction problemFunction = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyFunction.class);
|
||||
if (problemFunction == null) return;
|
||||
final StringBuilder superCall = new StringBuilder();
|
||||
final PyClass klass = problemFunction.getContainingClass();
|
||||
@@ -63,35 +65,56 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
|
||||
final PyClass superClass = superClasses[0];
|
||||
final PyFunction superInit = superClass.findMethodByName(PyNames.INIT, true);
|
||||
if (superInit == null) return;
|
||||
boolean addComma = true;
|
||||
final boolean addComma;
|
||||
if (klass.isNewStyleClass()) {
|
||||
addComma = false;
|
||||
if (LanguageLevel.forElement(klass).isPy3K())
|
||||
if (LanguageLevel.forElement(klass).isPy3K()) {
|
||||
superCall.append("super().__init__(");
|
||||
else
|
||||
}
|
||||
else {
|
||||
superCall.append("super(").append(klass.getName()).append(", self).__init__(");
|
||||
}
|
||||
}
|
||||
else {
|
||||
addComma = true;
|
||||
superCall.append(superClass.getName());
|
||||
superCall.append(".__init__(self");
|
||||
}
|
||||
StringBuilder newFunction = new StringBuilder("def __init__(self");
|
||||
final StringBuilder newFunction = new StringBuilder("def __init__(self");
|
||||
|
||||
buildParameterList(problemFunction, superInit, superCall, newFunction, addComma);
|
||||
final Couple<List<String>> couple = buildNewFunctionParamsAndSuperInitCallArgs(problemFunction, superInit);
|
||||
|
||||
final List<String> newParameters = couple.getFirst();
|
||||
if (!newParameters.isEmpty()) {
|
||||
newFunction.append(", ");
|
||||
}
|
||||
StringUtil.join(newParameters, ", ", newFunction);
|
||||
newFunction.append(")");
|
||||
if (problemFunction.getAnnotation() != null) {
|
||||
newFunction.append(problemFunction.getAnnotation().getText());
|
||||
}
|
||||
newFunction.append(":\n\t");
|
||||
|
||||
final List<String> superCallArguments = couple.getSecond();
|
||||
if (addComma && !superCallArguments.isEmpty()) {
|
||||
superCall.append(", ");
|
||||
}
|
||||
StringUtil.join(superCallArguments, ", ", superCall);
|
||||
superCall.append(")");
|
||||
|
||||
final PyStatementList statementList = problemFunction.getStatementList();
|
||||
PyExpression docstring = null;
|
||||
final PyStatement[] statements = statementList.getStatements();
|
||||
if (statements.length != 0 && statements[0] instanceof PyExpressionStatement) {
|
||||
PyExpressionStatement st = (PyExpressionStatement)statements[0];
|
||||
if (st.getExpression() instanceof PyStringLiteralExpression)
|
||||
final PyExpressionStatement st = (PyExpressionStatement)statements[0];
|
||||
if (st.getExpression() instanceof PyStringLiteralExpression) {
|
||||
docstring = st.getExpression();
|
||||
}
|
||||
}
|
||||
|
||||
newFunction.append("):\n\t");
|
||||
if (docstring != null)
|
||||
if (docstring != null) {
|
||||
newFunction.append(docstring.getText()).append("\n\t");
|
||||
}
|
||||
newFunction.append(superCall).append("\n\t");
|
||||
boolean first = true;
|
||||
for (PyStatement statement : statements) {
|
||||
@@ -102,89 +125,249 @@ public class AddCallSuperQuickFix implements LocalQuickFix {
|
||||
newFunction.append(statement.getText()).append("\n\t");
|
||||
}
|
||||
|
||||
problemFunction.replace(
|
||||
PyElementGenerator.getInstance(project).createFromText(LanguageLevel.forElement(problemFunction), PyFunction.class,
|
||||
newFunction.toString()));
|
||||
final PyElementGenerator generator = PyElementGenerator.getInstance(project);
|
||||
problemFunction.replace(generator.createFromText(LanguageLevel.forElement(problemFunction), PyFunction.class, newFunction.toString()));
|
||||
}
|
||||
|
||||
private static void buildParameterList(@NotNull final PyFunction problemFunction,
|
||||
@NotNull final PyFunction superInit,
|
||||
@NotNull final StringBuilder superCall,
|
||||
@NotNull final StringBuilder newFunction, boolean addComma) {
|
||||
final PyParameter[] parameters = problemFunction.getParameterList().getParameters();
|
||||
final List<String> problemParams = new ArrayList<String>();
|
||||
final List<String> functionParams = new ArrayList<String>();
|
||||
String starName = null;
|
||||
String doubleStarName = null;
|
||||
for (int i = 1; i != parameters.length; i++) {
|
||||
PyParameter p = parameters[i];
|
||||
functionParams.add(p.getName());
|
||||
if (p.getText().startsWith("**")) {
|
||||
doubleStarName = p.getText();
|
||||
continue;
|
||||
@NotNull
|
||||
private static Couple<List<String>> buildNewFunctionParamsAndSuperInitCallArgs(@NotNull PyFunction origInit,
|
||||
@NotNull PyFunction superInit) {
|
||||
final List<String> newFunctionParams = new ArrayList<String>();
|
||||
final List<String> superCallArgs = new ArrayList<String>();
|
||||
|
||||
final ParametersInfo origInfo = new ParametersInfo(origInit.getParameterList());
|
||||
final ParametersInfo superInfo = new ParametersInfo(superInit.getParameterList());
|
||||
|
||||
// Required parameters (not-keyword)
|
||||
for (PyParameter param : origInfo.getRequiredParameters()) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
for (PyParameter param : superInfo.getRequiredParameters()) {
|
||||
// Special case as if base class has constructor __init__((a, b), c) and
|
||||
// subclass has constructor __init__(a, (b, c))
|
||||
final PyTupleParameter tupleParam = param.getAsTuple();
|
||||
if (tupleParam != null) {
|
||||
final List<String> uniqueNames = collectParameterNames(tupleParam);
|
||||
final boolean hasDuplicates = uniqueNames.removeAll(origInfo.getAllParameterNames());
|
||||
if (hasDuplicates) {
|
||||
newFunctionParams.addAll(uniqueNames);
|
||||
}
|
||||
else {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
// Retain original structure of tuple parameter.
|
||||
// Note that tuple parameters cannot have annotations or nested default values, so it's syntactically safe
|
||||
superCallArgs.add(param.getText());
|
||||
}
|
||||
if (p.getText().startsWith("*")) {
|
||||
starName = p.getText();
|
||||
continue;
|
||||
else {
|
||||
if (!origInfo.getAllParameterNames().contains(param.getName())) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
superCallArgs.add(param.getName());
|
||||
}
|
||||
if (p.getDefaultValue() != null) {
|
||||
problemParams.add(p.getText());
|
||||
continue;
|
||||
}
|
||||
newFunction.append(",").append(p.getText());
|
||||
}
|
||||
|
||||
addParametersFromSuper(superInit, superCall, newFunction, addComma, problemParams, functionParams, starName, doubleStarName);
|
||||
// Optional parameters (not-keyword)
|
||||
for (PyParameter param : origInfo.getOptionalParameters()) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
|
||||
// Positional vararg
|
||||
PyParameter starredParam = null;
|
||||
if (origInfo.getPositionalContainerParameter() != null) {
|
||||
starredParam = origInfo.getPositionalContainerParameter();
|
||||
}
|
||||
else if (superInfo.getPositionalContainerParameter() != null) {
|
||||
starredParam = superInfo.getPositionalContainerParameter();
|
||||
}
|
||||
else if (origInfo.getSingleStarParameter() != null) {
|
||||
starredParam = origInfo.getSingleStarParameter();
|
||||
}
|
||||
else if (superInfo.getSingleStarParameter() != null) {
|
||||
starredParam = superInfo.getSingleStarParameter();
|
||||
}
|
||||
if (starredParam != null) {
|
||||
newFunctionParams.add(starredParam.getText());
|
||||
if (superInfo.getPositionalContainerParameter() != null) {
|
||||
superCallArgs.add("*" + starredParam.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Required keyword-only parameters
|
||||
for (PyParameter param : origInfo.getRequiredKeywordOnlyParameters()) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
for (PyParameter param : superInfo.getRequiredKeywordOnlyParameters()) {
|
||||
if (!origInfo.getAllParameterNames().contains(param.getName())) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
superCallArgs.add(param.getName() + "=" + param.getName());
|
||||
}
|
||||
|
||||
// Optional keyword-only parameters
|
||||
for (PyParameter param : origInfo.getOptionalKeywordOnlyParameters()) {
|
||||
newFunctionParams.add(param.getText());
|
||||
}
|
||||
|
||||
// Keyword vararg
|
||||
PyParameter doubleStarredParam = null;
|
||||
if (origInfo.getKeywordContainerParameter() != null) {
|
||||
doubleStarredParam = origInfo.getKeywordContainerParameter();
|
||||
}
|
||||
else if (superInfo.getKeywordContainerParameter() != null) {
|
||||
doubleStarredParam = superInfo.getKeywordContainerParameter();
|
||||
}
|
||||
if (doubleStarredParam != null) {
|
||||
newFunctionParams.add(doubleStarredParam.getText());
|
||||
if (superInfo.getKeywordContainerParameter() != null) {
|
||||
superCallArgs.add("**" + doubleStarredParam.getName());
|
||||
}
|
||||
}
|
||||
return Couple.of(newFunctionParams, superCallArgs);
|
||||
}
|
||||
|
||||
private static void addParametersFromSuper(@NotNull final PyFunction superInit, @NotNull final StringBuilder superCall,
|
||||
@NotNull final StringBuilder newFunction, boolean addComma,
|
||||
@NotNull final List<String> problemParams, @NotNull final List<String> functionParams,
|
||||
@Nullable String starName, @Nullable String doubleStarName) {
|
||||
final PyParameterList paramList = superInit.getParameterList();
|
||||
PyParameter[] parameters = paramList.getParameters();
|
||||
boolean addDouble = false;
|
||||
boolean addStar = false;
|
||||
for (int i = 1; i != parameters.length; i++) {
|
||||
PyParameter p = parameters[i];
|
||||
if (p.getDefaultValue() != null) continue;
|
||||
final String param = p.getName();
|
||||
String paramText = p.getText();
|
||||
if (paramText.startsWith("**")) {
|
||||
addDouble = true;
|
||||
if (doubleStarName == null)
|
||||
doubleStarName = p.getText();
|
||||
continue;
|
||||
private static class ParametersInfo {
|
||||
|
||||
private final PyParameter mySelfParam;
|
||||
/**
|
||||
* Parameters without default value that come before first "*..." parameter.
|
||||
*/
|
||||
private final List<PyParameter> myRequiredParams = new ArrayList<PyParameter>();
|
||||
/**
|
||||
* Parameters with default value that come before first "*..." parameter.
|
||||
*/
|
||||
private final List<PyParameter> myOptionalParams = new ArrayList<PyParameter>();
|
||||
/**
|
||||
* Parameter of form "*args" (positional vararg), not the same as single "*".
|
||||
*/
|
||||
private final PyParameter myPositionalContainerParam;
|
||||
/**
|
||||
* Parameter "*", that is used to delimit normal and keyword-only parameters.
|
||||
*/
|
||||
private final PyParameter mySingleStarParam;
|
||||
/**
|
||||
* Parameters without default value that come after first "*..." parameter.
|
||||
*/
|
||||
private final List<PyParameter> myRequiredKwOnlyParams = new ArrayList<PyParameter>();
|
||||
/**
|
||||
* Parameters with default value that come after first "*..." parameter.
|
||||
*/
|
||||
private final List<PyParameter> myOptionalKwOnlyParams = new ArrayList<PyParameter>();
|
||||
/**
|
||||
* Parameter of form "**kwargs" (keyword vararg).
|
||||
*/
|
||||
private final PyParameter myKeywordContainerParam;
|
||||
|
||||
private final Set<String> myAllParameterNames = new LinkedHashSet<String>();
|
||||
|
||||
public ParametersInfo(@NotNull PyParameterList parameterList) {
|
||||
PyParameter positionalContainer = null;
|
||||
PyParameter singleStarParam = null;
|
||||
PyParameter keywordContainer = null;
|
||||
PyParameter selfParam = null;
|
||||
|
||||
for (PyParameter param : parameterList.getParameters()) {
|
||||
myAllParameterNames.addAll(collectParameterNames(param));
|
||||
|
||||
if (param.isSelf()) {
|
||||
selfParam = param;
|
||||
}
|
||||
else if (param.getText().equals("*")) {
|
||||
singleStarParam = param;
|
||||
}
|
||||
else if (param.getText().startsWith("**")) {
|
||||
keywordContainer = param;
|
||||
}
|
||||
else if (param.getText().startsWith("*")) {
|
||||
positionalContainer = param;
|
||||
}
|
||||
else if (positionalContainer == null && singleStarParam == null) {
|
||||
if (param.hasDefaultValue()) {
|
||||
myOptionalParams.add(param);
|
||||
}
|
||||
else {
|
||||
myRequiredParams.add(param);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (param.hasDefaultValue()) {
|
||||
myOptionalKwOnlyParams.add(param);
|
||||
}
|
||||
else {
|
||||
myRequiredKwOnlyParams.add(param);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (paramText.startsWith("*")) {
|
||||
addStar = true;
|
||||
if (starName == null)
|
||||
starName = p.getText();
|
||||
continue;
|
||||
}
|
||||
if (addComma)
|
||||
superCall.append(",");
|
||||
superCall.append(param);
|
||||
if (!functionParams.contains(param))
|
||||
newFunction.append(",").append(param);
|
||||
addComma = true;
|
||||
|
||||
mySelfParam = selfParam;
|
||||
myPositionalContainerParam = positionalContainer;
|
||||
mySingleStarParam = singleStarParam;
|
||||
myKeywordContainerParam = keywordContainer;
|
||||
}
|
||||
for(String p : problemParams)
|
||||
newFunction.append(",").append(p);
|
||||
if (starName != null) {
|
||||
newFunction.append(",").append(starName);
|
||||
if (addStar) {
|
||||
if (addComma) superCall.append(",");
|
||||
superCall.append(starName);
|
||||
addComma = true;
|
||||
|
||||
@Nullable
|
||||
public PyParameter getSelfParameter() {
|
||||
return mySelfParam;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<PyParameter> getRequiredParameters() {
|
||||
return Collections.unmodifiableList(myRequiredParams);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<PyParameter> getOptionalParameters() {
|
||||
return Collections.unmodifiableList(myOptionalParams);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyParameter getPositionalContainerParameter() {
|
||||
return myPositionalContainerParam;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyParameter getSingleStarParameter() {
|
||||
return mySingleStarParam;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<PyParameter> getRequiredKeywordOnlyParameters() {
|
||||
return Collections.unmodifiableList(myRequiredKwOnlyParams);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<PyParameter> getOptionalKeywordOnlyParameters() {
|
||||
return Collections.unmodifiableList(myOptionalKwOnlyParams);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PyParameter getKeywordContainerParameter() {
|
||||
return myKeywordContainerParam;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getAllParameterNames() {
|
||||
return Collections.unmodifiableSet(myAllParameterNames);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<String> collectParameterNames(@NotNull PyParameter param) {
|
||||
final List<String> result = new ArrayList<String>();
|
||||
collectParameterNames(param, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private static void collectParameterNames(@NotNull PyParameter param, @NotNull Collection<String> acc) {
|
||||
final PyTupleParameter tupleParam = param.getAsTuple();
|
||||
if (tupleParam != null) {
|
||||
for (PyParameter subParam : tupleParam.getContents()) {
|
||||
collectParameterNames(subParam, acc);
|
||||
}
|
||||
}
|
||||
if (doubleStarName != null) {
|
||||
newFunction.append(",").append(doubleStarName);
|
||||
if (addDouble) {
|
||||
if (addComma) superCall.append(",");
|
||||
superCall.append(doubleStarName);
|
||||
}
|
||||
else {
|
||||
ContainerUtil.addIfNotNull(acc, param.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
class Example1:
|
||||
def __init__(self, field1: str):
|
||||
self.field1 = field1
|
||||
|
||||
|
||||
class Example2(Example1):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self): ## Missed call to __init__ of super class
|
||||
pass
|
||||
@@ -1,8 +0,0 @@
|
||||
class Example1:
|
||||
def __init__(self, field1: str):
|
||||
self.field1 = field1
|
||||
|
||||
|
||||
class Example2(Example1):
|
||||
def __init__(self, field1):
|
||||
super().__init__(field1)
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, (a, (b, c)), (d, e)):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__init_<caret>_</warning>(self, (a, b), c, e):
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, (a, (b, c)), (d, e)):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def __init__(self, (a, b), c, e, d):
|
||||
A.__init__(self, (a, (b, c)), (d, e))
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, a):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, b, c=1, *args, kw_only):
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, a):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def __init__(self, b, a, c=1, *args, kw_only):
|
||||
super().__init__(a)
|
||||
@@ -0,0 +1,8 @@
|
||||
class A:
|
||||
def __init__(self, a, b=1, *args, kw_only):
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, c):
|
||||
pass
|
||||
@@ -0,0 +1,8 @@
|
||||
class A:
|
||||
def __init__(self, a, b=1, *args, kw_only):
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
def __init__(self, c, a, *args, kw_only):
|
||||
super().__init__(a, *args, kw_only=kw_only)
|
||||
@@ -0,0 +1,8 @@
|
||||
class A:
|
||||
def __init__(self, a):
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__init_<caret>_</warning>(self, a=1):
|
||||
pass
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class A:
|
||||
def __init__(self, a):
|
||||
pass
|
||||
|
||||
|
||||
class B(A):
|
||||
def __init__(self, a=1):
|
||||
A.__init__(self, a)
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, *, kw_only, optional_kw_only=None):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self):
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, *, kw_only):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, *args, another_kw_only):
|
||||
pass
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, *, kw_only):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def __init__(self, *args, another_kw_only, kw_only):
|
||||
super().__init__(kw_only=kw_only)
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, *, kw_only, optional_kw_only=None):
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def __init__(self, *, kw_only):
|
||||
super().__init__(kw_only=kw_only)
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, a:int, b:float, *args:tuple, c:complex, **kwargs:dict) -> None:
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def <warning descr="Call to __init__ of super class is missed">__i<caret>nit__</warning>(self, d:str, *, e:bytes) -> list:
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
def __init__(self, a:int, b:float, *args:tuple, c:complex, **kwargs:dict) -> None:
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
def __init__(self, d:str, a:int, b:float, *args:tuple, e:bytes, c:complex, **kwargs:dict) -> list:
|
||||
super().__init__(a, b, *args, c=c, **kwargs)
|
||||
@@ -24,6 +24,7 @@ import com.jetbrains.python.inspections.PyMissingConstructorInspection;
|
||||
import com.jetbrains.python.inspections.PyStatementEffectInspection;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@TestDataPath("$CONTENT_ROOT/../testData/inspections/")
|
||||
public class Py3QuickFixTest extends PyTestCase {
|
||||
@@ -32,39 +33,107 @@ public class Py3QuickFixTest extends PyTestCase {
|
||||
return PyTestCase.ourPy3Descriptor;
|
||||
}
|
||||
|
||||
// PY-13685
|
||||
public void testReplacePrintEnd() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("ReplacePrintEnd.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}});
|
||||
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-13685
|
||||
public void testReplacePrintComment() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("ReplacePrintComment.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true,
|
||||
true);
|
||||
}});
|
||||
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-13685
|
||||
public void testReplaceExecComment() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON34, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("ReplaceExecComment.py", PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true,
|
||||
true);
|
||||
}});
|
||||
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testAddCallSuperAnnotations() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON33, new Runnable() {
|
||||
// PY-15867
|
||||
public void testAddCallSuperKeywordOnlyParamInSuperInit() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
|
||||
public void run() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-15867
|
||||
public void testAddCallSuperKeywordOnlyParamInInit() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
|
||||
public void run() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-15867
|
||||
public void testAddCallSuperSingleStarParamInSuperInit() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
|
||||
public void run() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-15867
|
||||
public void testAddCallSuperSingleStarParamInSuperInitAndVarargInInit() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("AddCallSuperAnnotations.py",
|
||||
PyMissingConstructorInspection.class,
|
||||
PyBundle.message("QFIX.add.super"), true, true);
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-11561
|
||||
public void testAddCallSuperTypeAnnotationsPreserved() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-8991
|
||||
public void testRemoveUnicodePrefixFromGluedStringNodesWithSlash() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
|
||||
public void run() {
|
||||
myFixture.configureByFile(getTestName(false) + ".py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.py");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-8990
|
||||
public void testRemoveUnicodePrefixFromGluedStringNodesInParenthesis() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
|
||||
public void run() {
|
||||
myFixture.configureByFile(getTestName(false) + ".py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.py");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -75,9 +144,16 @@ public class Py3QuickFixTest extends PyTestCase {
|
||||
return PythonTestUtil.getTestDataPath() + "/inspections/";
|
||||
}
|
||||
|
||||
protected void doInspectionTest(@TestDataFile @NonNls String testFileName,
|
||||
final Class inspectionClass,
|
||||
@NonNls String quickFixName,
|
||||
private void doInspectionTest(@NotNull Class inspectionClass,
|
||||
@NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
doInspectionTest(getTestName(false) + ".py", inspectionClass, quickFixName, applyFix, available);
|
||||
}
|
||||
|
||||
protected void doInspectionTest(@TestDataFile @NonNls @NotNull String testFileName,
|
||||
@NotNull Class inspectionClass,
|
||||
@NonNls @NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
doInspectionTest(new String[]{testFileName}, inspectionClass, quickFixName, applyFix, available);
|
||||
@@ -93,9 +169,9 @@ public class Py3QuickFixTest extends PyTestCase {
|
||||
* @param available true if the fix should be available, false if it should be explicitly not available.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void doInspectionTest(@NonNls String[] testFiles,
|
||||
final Class inspectionClass,
|
||||
@NonNls String quickFixName,
|
||||
protected void doInspectionTest(@NonNls @NotNull String[] testFiles,
|
||||
@NotNull Class inspectionClass,
|
||||
@NonNls @NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
myFixture.enableInspections(inspectionClass);
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.jetbrains.python.inspections.*;
|
||||
import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author dcheryasov
|
||||
@@ -47,15 +48,19 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testAddImport() {
|
||||
doInspectionTest(new String[] { "AddImport.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
doInspectionTest(new String[]{"AddImport.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
|
||||
"Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testAddImportDoc() {
|
||||
doInspectionTest(new String[] { "AddImportDoc.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
doInspectionTest(new String[]{"AddImportDoc.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
|
||||
"Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testAddImportDocComment() { // PY-728
|
||||
doInspectionTest(new String[] { "AddImportDocComment.py", "ImportTarget.py" }, PyUnresolvedReferencesInspection.class, "Import 'ImportTarget'", true, true);
|
||||
// PY-728
|
||||
public void testAddImportDocComment() {
|
||||
doInspectionTest(new String[]{"AddImportDocComment.py", "ImportTarget.py"}, PyUnresolvedReferencesInspection.class,
|
||||
"Import 'ImportTarget'", true, true);
|
||||
}
|
||||
|
||||
public void testImportFromModule() {
|
||||
@@ -73,7 +78,8 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
assertEquals("Import 'module.MyOldStyleClass'", intention.getText());
|
||||
}
|
||||
|
||||
public void testImportFromModuleStar() { // PY-6302
|
||||
// PY-6302
|
||||
public void testImportFromModuleStar() {
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
myFixture.copyDirectoryToProject("importFromModuleStar", "");
|
||||
myFixture.configureFromTempProjectFile("source.py");
|
||||
@@ -91,7 +97,8 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
settings.PREFER_FROM_IMPORT = false;
|
||||
settings.HIGHLIGHT_UNUSED_IMPORTS = false;
|
||||
try {
|
||||
doInspectionTest(new String[]{"QualifyByImport.py", "QualifyByImportFoo.py"}, PyUnresolvedReferencesInspection.class, PyBundle.message("ACT.qualify.with.module"), true, true);
|
||||
doInspectionTest(new String[]{"QualifyByImport.py", "QualifyByImportFoo.py"}, PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("ACT.qualify.with.module"), true, true);
|
||||
}
|
||||
finally {
|
||||
settings.PREFER_FROM_IMPORT = oldPreferFrom;
|
||||
@@ -104,7 +111,8 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
boolean oldHighlightUnused = settings.HIGHLIGHT_UNUSED_IMPORTS;
|
||||
settings.HIGHLIGHT_UNUSED_IMPORTS = false;
|
||||
try {
|
||||
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class, "Import 'foo(a) from AddToImportFromFoo'", true, true);
|
||||
doInspectionTest(new String[]{"AddToImportFromList.py", "AddToImportFromFoo.py"}, PyUnresolvedReferencesInspection.class,
|
||||
"Import 'foo(a) from AddToImportFromFoo'", true, true);
|
||||
}
|
||||
finally {
|
||||
settings.HIGHLIGHT_UNUSED_IMPORTS = oldHighlightUnused;
|
||||
@@ -115,90 +123,86 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
// TODO: add tests for stub indexes-based autoimport of unimported somehow.
|
||||
|
||||
public void testAddSelf() {
|
||||
doInspectionTest("AddSelf.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "self"), true, true);
|
||||
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "self"), true, true);
|
||||
}
|
||||
|
||||
public void testReplacePrint() {
|
||||
doInspectionTest("ReplacePrint.py", PyCompatibilityInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}
|
||||
|
||||
public void testAddSelfFunction() { //PY-4556
|
||||
doInspectionTest("AddSelfFunction.py",
|
||||
PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference", "get_a", "self"), true, true);
|
||||
// PY-4556
|
||||
public void testAddSelfFunction() {
|
||||
doInspectionTest("AddSelfFunction.py", PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference", "get_a", "self"), true, true);
|
||||
}
|
||||
|
||||
public void testAddSelfToClassmethod() { //PY-9721
|
||||
doInspectionTest("AddSelfToClassmethod.py",
|
||||
PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference", "foo", "cls"), true, true);
|
||||
// PY-9721
|
||||
public void testAddSelfToClassmethod() {
|
||||
doInspectionTest("AddSelfToClassmethod.py", PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference", "foo", "cls"), true, true);
|
||||
}
|
||||
|
||||
public void testAddCls() {
|
||||
doInspectionTest("AddCls.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "cls"), true, true);
|
||||
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.add.parameter.self", "cls"), true, true);
|
||||
}
|
||||
|
||||
public void testRenameToSelf() {
|
||||
doInspectionTest("RenameToSelf.py", PyMethodParametersInspection.class, PyBundle.message("QFIX.rename.parameter.to.$0", "self"), true,
|
||||
true);
|
||||
doInspectionTest(PyMethodParametersInspection.class, PyBundle.message("QFIX.rename.parameter.to.$0", "self"), true, true);
|
||||
}
|
||||
|
||||
public void testRemoveTrailingSemicolon() {
|
||||
doInspectionTest("RemoveTrailingSemicolon.py", PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"),
|
||||
true, true);
|
||||
doInspectionTest(PyTrailingSemicolonInspection.class, PyBundle.message("QFIX.remove.trailing.semicolon"), true, true);
|
||||
}
|
||||
|
||||
public void testDictCreation() {
|
||||
doInspectionTest("DictCreation.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
}
|
||||
|
||||
public void testDictCreationTuple() { //PY-6283
|
||||
doInspectionTest("DictCreationTuple.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
// PY-6283
|
||||
public void testDictCreationTuple() {
|
||||
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
}
|
||||
|
||||
public void testDictCreationDuplicate() { //PY-7318
|
||||
doInspectionTest("DictCreationDuplicate.py", PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
// PY-7318
|
||||
public void testDictCreationDuplicate() {
|
||||
doInspectionTest(PyDictCreationInspection.class, PyBundle.message("QFIX.dict.creation"), true, true);
|
||||
}
|
||||
|
||||
public void testTransformClassicClass() {
|
||||
doInspectionTest("TransformClassicClass.py", PyClassicStyleClassInspection.class,
|
||||
PyBundle.message("QFIX.classic.class.transform"), true, true);
|
||||
doInspectionTest(PyClassicStyleClassInspection.class, PyBundle.message("QFIX.classic.class.transform"), true, true);
|
||||
}
|
||||
|
||||
public void testAddGlobalQuickFix() {
|
||||
doInspectionTest("AddGlobalStatement.py", PyUnboundLocalVariableInspection.class,
|
||||
PyBundle.message("QFIX.add.global"), true, true);
|
||||
public void testAddGlobalStatement() {
|
||||
doInspectionTest(PyUnboundLocalVariableInspection.class, PyBundle.message("QFIX.add.global"), true, true);
|
||||
}
|
||||
|
||||
public void testAddGlobalExistingQuickFix() {
|
||||
doInspectionTest("AddGlobalExistingStatement.py", PyUnboundLocalVariableInspection.class,
|
||||
PyBundle.message("QFIX.add.global"), true, true);
|
||||
public void testAddGlobalExistingStatement() {
|
||||
doInspectionTest(PyUnboundLocalVariableInspection.class, PyBundle.message("QFIX.add.global"), true, true);
|
||||
}
|
||||
|
||||
public void testSimplifyBooleanCheckQuickFix() {
|
||||
doInspectionTest("SimplifyBooleanCheck.py", PySimplifyBooleanCheckInspection.class,
|
||||
PyBundle.message("QFIX.simplify.$0", "b"), true, true);
|
||||
public void testSimplifyBooleanCheck() {
|
||||
doInspectionTest(PySimplifyBooleanCheckInspection.class, PyBundle.message("QFIX.simplify.$0", "b"), true, true);
|
||||
}
|
||||
|
||||
public void testFromFutureImportQuickFix() {
|
||||
doInspectionTest("MoveFromFutureImport.py", PyFromFutureImportInspection.class,
|
||||
PyBundle.message("QFIX.move.from.future.import"), true, true);
|
||||
public void testMoveFromFutureImport() {
|
||||
doInspectionTest(PyFromFutureImportInspection.class, PyBundle.message("QFIX.move.from.future.import"), true, true);
|
||||
}
|
||||
|
||||
public void testFromFutureImportQuickFixDocString() { // PY-10080
|
||||
doInspectionTest("MoveFromFutureImportDocString.py", PyFromFutureImportInspection.class,
|
||||
PyBundle.message("QFIX.move.from.future.import"), true, true);
|
||||
// PY-10080
|
||||
public void testMoveFromFutureImportDocString() {
|
||||
doInspectionTest(PyFromFutureImportInspection.class, PyBundle.message("QFIX.move.from.future.import"), true, true);
|
||||
}
|
||||
|
||||
public void testComparisonWithNoneQuickFix() {
|
||||
doInspectionTest("ComparisonWithNone.py", PyComparisonWithNoneInspection.class,
|
||||
PyBundle.message("QFIX.replace.equality"), true, true);
|
||||
public void testComparisonWithNone() {
|
||||
doInspectionTest(PyComparisonWithNoneInspection.class, PyBundle.message("QFIX.replace.equality"), true, true);
|
||||
}
|
||||
|
||||
public void testAddClassFix() {
|
||||
doInspectionTest("AddClass.py", PyUnresolvedReferencesInspection.class, "Create class 'Xyzzy'", true, true);
|
||||
}
|
||||
|
||||
|
||||
public void testAddFunctionToModule() { // PY-1602
|
||||
// PY-1602
|
||||
public void testAddFunctionToModule() {
|
||||
doInspectionTest(
|
||||
"AddFunctionToModule.py",
|
||||
PyUnresolvedReferencesInspection.class,
|
||||
@@ -207,7 +211,8 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public void testRedundantParentheses() { // PY-1470
|
||||
// PY-1470
|
||||
public void testRedundantParentheses() {
|
||||
String[] testFiles = new String[]{"RedundantParentheses.py"};
|
||||
myFixture.enableInspections(PyRedundantParenthesesInspection.class);
|
||||
myFixture.configureByFiles(testFiles);
|
||||
@@ -216,88 +221,86 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
|
||||
|
||||
}
|
||||
|
||||
public void testRedundantParenthesesBoolean() { // PY-3095
|
||||
doInspectionTest("RedundantParenthesesBoolean.py", PyRedundantParenthesesInspection.class,
|
||||
PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
// PY-3095
|
||||
public void testRedundantParenthesesBoolean() {
|
||||
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
}
|
||||
|
||||
public void testRedundantParenthesesMore() { // PY-3239
|
||||
doInspectionTest("RedundantParenthesesMore.py", PyRedundantParenthesesInspection.class,
|
||||
PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
// PY-3239
|
||||
public void testRedundantParenthesesMore() {
|
||||
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
}
|
||||
|
||||
public void testRedundantParenthesesParenthesizedExpression() { // PY-12679
|
||||
doInspectionTest("RedundantParenthesesParenthesizedExpression.py", PyRedundantParenthesesInspection.class,
|
||||
PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
// PY-12679
|
||||
public void testRedundantParenthesesParenthesizedExpression() {
|
||||
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
}
|
||||
|
||||
// PY-15506
|
||||
public void testEmptyListOfBaseClasses() {
|
||||
doInspectionTest("EmptyListOfBaseClasses.py", PyRedundantParenthesesInspection.class,
|
||||
PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
doInspectionTest(PyRedundantParenthesesInspection.class, PyBundle.message("QFIX.redundant.parentheses"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparisons() { // PY-1020
|
||||
doInspectionTest("ChainedComparisons.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-1020
|
||||
public void testChainedComparisons() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparison1() { // PY-3126
|
||||
doInspectionTest("ChainedComparison1.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-3126
|
||||
public void testChainedComparison1() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparison2() { // PY-3126
|
||||
doInspectionTest("ChainedComparison2.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-3126
|
||||
public void testChainedComparison2() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparison3() { // PY-3126
|
||||
doInspectionTest("ChainedComparison3.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-3126
|
||||
public void testChainedComparison3() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparison4() { // PY-5623
|
||||
doInspectionTest("ChainedComparison4.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-5623
|
||||
public void testChainedComparison4() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testChainedComparison5() { // PY-6467
|
||||
doInspectionTest("ChainedComparison5.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
// PY-6467
|
||||
public void testChainedComparison5() {
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
// PY-14002
|
||||
public void testChainedComparisonWithCommonBinaryExpression() {
|
||||
doInspectionTest("ChainedComparisonWithCommonBinaryExpression.py", PyChainedComparisonsInspection.class,
|
||||
PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
doInspectionTest(PyChainedComparisonsInspection.class, PyBundle.message("QFIX.chained.comparison"), true, true);
|
||||
}
|
||||
|
||||
public void testStatementEffect() { // PY-1362, PY-2585
|
||||
doInspectionTest("StatementEffect.py", PyStatementEffectInspection.class,
|
||||
PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
// PY-1362, PY-2585
|
||||
public void testStatementEffect() {
|
||||
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect"), true, true);
|
||||
}
|
||||
|
||||
public void testStatementEffectIntroduceVariable() { // PY-1265
|
||||
doInspectionTest("StatementEffectIntroduceVariable.py", PyStatementEffectInspection.class,
|
||||
PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true);
|
||||
// PY-1265
|
||||
public void testStatementEffectIntroduceVariable() {
|
||||
doInspectionTest(PyStatementEffectInspection.class, PyBundle.message("QFIX.statement.effect.introduce.variable"), true, true);
|
||||
}
|
||||
|
||||
public void testUnresolvedWith() { // PY-2083
|
||||
// PY-2083
|
||||
public void testUnresolvedWith() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON25, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("UnresolvedWith.py", PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference.add.future"), true, true);
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference.add.future"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testUnresolvedRefCreateFunction() { // PY-2092
|
||||
doInspectionTest("UnresolvedRefCreateFunction.py", PyUnresolvedReferencesInspection.class,
|
||||
// PY-2092
|
||||
public void testUnresolvedRefCreateFunction() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"), true, true);
|
||||
}
|
||||
|
||||
@@ -305,109 +308,113 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
myFixture.enableInspections(PyUnresolvedReferencesInspection.class);
|
||||
myFixture.configureByFile("UnresolvedRefNoCreateFunction.py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.getAvailableIntention(
|
||||
PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"));
|
||||
final IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.unresolved.reference.create.function.$0", "ref"));
|
||||
assertNull(intentionAction);
|
||||
}
|
||||
|
||||
public void testReplaceNotEqOperator() {
|
||||
doInspectionTest("ReplaceNotEqOperator.py", PyCompatibilityInspection.class,
|
||||
PyBundle.message("INTN.replace.noteq.operator"), true, true);
|
||||
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("INTN.replace.noteq.operator"), true, true);
|
||||
}
|
||||
|
||||
public void testListCreation() {
|
||||
doInspectionTest("ListCreation.py", PyListCreationInspection.class,
|
||||
PyBundle.message("QFIX.list.creation"), true, true);
|
||||
doInspectionTest(PyListCreationInspection.class, PyBundle.message("QFIX.list.creation"), true, true);
|
||||
}
|
||||
|
||||
public void testConvertSingleQuotedDocstring() { //PY-1445
|
||||
doInspectionTest("ConvertSingleQuotedDocstring.py", PySingleQuotedDocstringInspection.class,
|
||||
PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
|
||||
// PY-1445
|
||||
public void testConvertSingleQuotedDocstring() {
|
||||
doInspectionTest(PySingleQuotedDocstringInspection.class, PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
|
||||
}
|
||||
|
||||
public void testConvertSingleQuotedDocstringEscape() { //PY-8926
|
||||
doInspectionTest("ConvertSingleQuotedDocstringEscape.py", PySingleQuotedDocstringInspection.class,
|
||||
PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
|
||||
// PY-8926
|
||||
public void testConvertSingleQuotedDocstringEscape() {
|
||||
doInspectionTest(PySingleQuotedDocstringInspection.class, PyBundle.message("QFIX.convert.single.quoted.docstring"), true, true);
|
||||
}
|
||||
|
||||
public void testDefaultArgument() { //PY-3127
|
||||
doInspectionTest("DefaultArgument.py", PyDefaultArgumentInspection.class,
|
||||
PyBundle.message("QFIX.default.argument"), true, true);
|
||||
// PY-3127
|
||||
public void testDefaultArgument() {
|
||||
doInspectionTest(PyDefaultArgumentInspection.class, PyBundle.message("QFIX.default.argument"), true, true);
|
||||
}
|
||||
|
||||
public void testDefaultArgumentEmptyList() {
|
||||
doInspectionTest("DefaultArgumentEmptyList.py", PyDefaultArgumentInspection.class,
|
||||
PyBundle.message("QFIX.default.argument"), true, true);
|
||||
doInspectionTest(PyDefaultArgumentInspection.class, PyBundle.message("QFIX.default.argument"), true, true);
|
||||
}
|
||||
|
||||
public void testPyArgumentEqualDefault() { //PY-3125
|
||||
doInspectionTest("ArgumentEqualDefault.py", PyArgumentEqualDefaultInspection.class,
|
||||
PyBundle.message("QFIX.remove.argument.equal.default"), true, true);
|
||||
// PY-3125
|
||||
public void testArgumentEqualDefault() {
|
||||
doInspectionTest(PyArgumentEqualDefaultInspection.class, PyBundle.message("QFIX.remove.argument.equal.default"), true, true);
|
||||
}
|
||||
|
||||
public void testAddCallSuper() { //PY-3315
|
||||
doInspectionTest("AddCallSuper.py", PyMissingConstructorInspection.class,
|
||||
PyBundle.message("QFIX.add.super"), true, true);
|
||||
// PY-3315
|
||||
public void testAddCallSuper() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
|
||||
public void testAddCallSuper1() { //PY-4017
|
||||
doInspectionTest("AddCallSuper1.py", PyMissingConstructorInspection.class,
|
||||
PyBundle.message("QFIX.add.super"), true, true);
|
||||
// PY-4017
|
||||
public void testAddCallSuper1() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
|
||||
public void testAddCallSuperPass() { //PY-8654
|
||||
doInspectionTest("AddCallSuperPass.py", PyMissingConstructorInspection.class,
|
||||
PyBundle.message("QFIX.add.super"), true, true);
|
||||
// PY-8654
|
||||
public void testAddCallSuperPass() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
|
||||
//PY-491, PY-13297
|
||||
// PY-15867
|
||||
public void testAddCallSuperOptionalAndRequiredParamsNameCollision() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
|
||||
// PY-15927
|
||||
public void testAddCallSuperConflictingTupleParam() {
|
||||
doInspectionTest(PyMissingConstructorInspection.class, PyBundle.message("QFIX.add.super"), true, true);
|
||||
}
|
||||
|
||||
// PY-491, PY-13297
|
||||
public void testAddEncoding() {
|
||||
doInspectionTest("AddEncoding.py", PyMandatoryEncodingInspection.class,
|
||||
PyBundle.message("QFIX.add.encoding"), true, true);
|
||||
doInspectionTest(PyMandatoryEncodingInspection.class, PyBundle.message("QFIX.add.encoding"), true, true);
|
||||
}
|
||||
|
||||
// PY-13297
|
||||
public void testAddEncodingAtLastLine() {
|
||||
doInspectionTest("AddEncodingAtLastLine.py", PyMandatoryEncodingInspection.class,
|
||||
PyBundle.message("QFIX.add.encoding"), true, true);
|
||||
doInspectionTest(PyMandatoryEncodingInspection.class, PyBundle.message("QFIX.add.encoding"), true, true);
|
||||
}
|
||||
|
||||
public void testRemoveDecorator() { //PY-3348
|
||||
doInspectionTest("RemoveDecorator.py", PyDecoratorInspection.class,
|
||||
PyBundle.message("QFIX.remove.decorator"), true, true);
|
||||
// PY-3348
|
||||
public void testRemoveDecorator() {
|
||||
doInspectionTest(PyDecoratorInspection.class, PyBundle.message("QFIX.remove.decorator"), true, true);
|
||||
}
|
||||
|
||||
public void testAddParameter() {
|
||||
doInspectionTest("AddParameter.py", PyUnresolvedReferencesInspection.class,
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference.add.param.$0", "test"), true, true);
|
||||
}
|
||||
|
||||
public void testRenameUnresolvedReference() { //PY-6595
|
||||
doInspectionTest("RenameUnresolvedReference.py", PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.rename.unresolved.reference"), true, true);
|
||||
// PY-6595
|
||||
public void testRenameUnresolvedReference() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.rename.unresolved.reference"), true, true);
|
||||
}
|
||||
|
||||
public void testSetFunctionToLiteral() { //PY-3120
|
||||
// PY-3120
|
||||
public void testSetFunctionToLiteral() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON27, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doInspectionTest("SetFunctionToLiteral.py", PySetFunctionToLiteralInspection.class,
|
||||
PyBundle.message("QFIX.replace.function.set.with.literal"), true, true);
|
||||
doInspectionTest(PySetFunctionToLiteralInspection.class, PyBundle.message("QFIX.replace.function.set.with.literal"), true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testDictComprehensionToCall() {
|
||||
doInspectionTest("DictComprehensionToCall.py", PyCompatibilityInspection.class,
|
||||
PyBundle.message("INTN.convert.dict.comp.to"), true, true);
|
||||
doInspectionTest(PyCompatibilityInspection.class, PyBundle.message("INTN.convert.dict.comp.to"), true, true);
|
||||
}
|
||||
|
||||
public void testDocstringParams() { //PY-3394
|
||||
// PY-3394
|
||||
public void testDocstringParams() {
|
||||
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
|
||||
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
|
||||
try {
|
||||
doInspectionTest("DocstringParams.py", PyDocstringInspection.class,
|
||||
PyBundle.message("QFIX.docstring.add.$0", "b"), true, true);
|
||||
doInspectionTest(PyDocstringInspection.class,
|
||||
PyBundle.message("QFIX.docstring.add.$0", "b"), true, true);
|
||||
}
|
||||
finally {
|
||||
documentationSettings.setFormat(DocStringFormat.PLAIN);
|
||||
@@ -418,20 +425,19 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
|
||||
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
|
||||
try {
|
||||
doInspectionTest("DocstringParams1.py", PyDocstringInspection.class,
|
||||
PyBundle.message("QFIX.docstring.remove.$0", "c"), true, true);
|
||||
doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.remove.$0", "c"), true, true);
|
||||
}
|
||||
finally {
|
||||
documentationSettings.setFormat(DocStringFormat.PLAIN);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDocstringParams2() { //PY-4964
|
||||
// PY-4964
|
||||
public void testDocstringParams2() {
|
||||
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(myFixture.getModule());
|
||||
documentationSettings.setFormat(DocStringFormat.EPYTEXT);
|
||||
try {
|
||||
doInspectionTest("DocstringParams2.py", PyDocstringInspection.class,
|
||||
PyBundle.message("QFIX.docstring.add.$0", "ham"), true, true);
|
||||
doInspectionTest(PyDocstringInspection.class, PyBundle.message("QFIX.docstring.add.$0", "ham"), true, true);
|
||||
}
|
||||
finally {
|
||||
documentationSettings.setFormat(DocStringFormat.PLAIN);
|
||||
@@ -449,9 +455,9 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
|
||||
}
|
||||
|
||||
public void testUnresolvedRefTrueFalse() { //PY-3051
|
||||
doInspectionTest("UnresolvedRefTrueFalse.py", PyUnresolvedReferencesInspection.class,
|
||||
PyBundle.message("QFIX.unresolved.reference.replace.$0", "True"), true, true);
|
||||
// PY-3051
|
||||
public void testUnresolvedRefTrueFalse() {
|
||||
doInspectionTest(PyUnresolvedReferencesInspection.class, PyBundle.message("QFIX.unresolved.reference.replace.$0", "True"), true, true);
|
||||
}
|
||||
|
||||
public void testUnnecessaryBackslashInArgumentList() {
|
||||
@@ -498,43 +504,22 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
}
|
||||
|
||||
// PY-8991
|
||||
public void testRemoveUnicodePrefixFromGluedStringNodesWithSlash() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
|
||||
public void run() {
|
||||
myFixture.configureByFile(getTestName(false) + ".py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.py");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// PY-8990
|
||||
public void testRemoveUnicodePrefixFromGluedStringNodesInParenthesis() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON32, new Runnable() {
|
||||
public void run() {
|
||||
myFixture.configureByFile(getTestName(false) + ".py");
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("INTN.remove.leading.$0", "U"));
|
||||
assertNotNull(intentionAction);
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(getTestName(false) + "_after.py");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNls
|
||||
protected String getTestDataPath() {
|
||||
return PythonTestUtil.getTestDataPath() + "/inspections/";
|
||||
}
|
||||
|
||||
protected void doInspectionTest(@TestDataFile @NonNls String testFileName,
|
||||
final Class inspectionClass,
|
||||
@NonNls String quickFixName,
|
||||
private void doInspectionTest(@NotNull Class inspectionClass,
|
||||
@NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
doInspectionTest(getTestName(false) + ".py", inspectionClass, quickFixName, applyFix, available);
|
||||
}
|
||||
|
||||
protected void doInspectionTest(@TestDataFile @NonNls @NotNull String testFileName,
|
||||
@NotNull Class inspectionClass,
|
||||
@NonNls @NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
doInspectionTest(new String[]{testFileName}, inspectionClass, quickFixName, applyFix, available);
|
||||
@@ -550,9 +535,9 @@ public class PyQuickFixTest extends PyTestCase {
|
||||
* @param available true if the fix should be available, false if it should be explicitly not available.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected void doInspectionTest(@NonNls String[] testFiles,
|
||||
final Class inspectionClass,
|
||||
@NonNls String quickFixName,
|
||||
protected void doInspectionTest(@NonNls @NotNull String[] testFiles,
|
||||
@NotNull Class inspectionClass,
|
||||
@NonNls @NotNull String quickFixName,
|
||||
boolean applyFix,
|
||||
boolean available) {
|
||||
myFixture.enableInspections(inspectionClass);
|
||||
|
||||
@@ -1621,6 +1621,7 @@
|
||||
<hierarchy.referenceProcessor implementation="com.intellij.ide.hierarchy.call.JavaCallReferenceProcessor"/>
|
||||
<projectTemplate projectType="JAVA_MODULE" templatePath="resources/projectTemplates/Java/Command_Line_App.zip"/>
|
||||
<generatedSourcesFilter implementation="com.intellij.openapi.roots.JavaGeneratedSourcesFilter"/>
|
||||
<languageTestDataChecker implementation="com.intellij.openapi.projectRoots.JavaLanguageTestDataChecker"/>
|
||||
<refactoring.elementListenerProvider implementation="com.intellij.codeInspection.ex.AdditionalAnnotationsRefactoringElementListener"/>
|
||||
<projectOpenProcessor implementation="com.intellij.platform.PlatformProjectOpenProcessor" order="last"/>
|
||||
<projectService serviceInterface="com.intellij.platform.ProjectBaseDirectory"
|
||||
|
||||
@@ -48,7 +48,7 @@ public class WebBrowserServiceImpl extends WebBrowserService {
|
||||
VirtualFile file = request.getVirtualFile();
|
||||
return file instanceof LightVirtualFile || !request.getFile().getViewProvider().isPhysical()
|
||||
? Collections.<Url>emptyList()
|
||||
: Collections.singleton(Urls.newFromVirtualFile(file));
|
||||
: Collections.singletonList(Urls.newFromVirtualFile(file));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
Reference in New Issue
Block a user