Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ilya.Kazakevich
2015-05-18 20:32:07 +03:00
79 changed files with 1574 additions and 928 deletions
@@ -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;
}
});
}
@@ -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;
}
@@ -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
@@ -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;
}
}
}
+2 -2
View File
@@ -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) {
}
}
@@ -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);
}
}
@@ -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 { }
}
@@ -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") {
}
}
}
}
@@ -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");
}
}
}
}
@@ -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
}
@@ -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')
@@ -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;
@@ -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 &&
@@ -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 = "&lt;";
@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);
}
@@ -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
@@ -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")
);
@@ -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);
}
}
@@ -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) {
@@ -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();
@@ -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;
@@ -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) {
@@ -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());
}
@@ -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();
@@ -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));
}
@@ -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) {
+5 -4
View File
@@ -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
@@ -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
@@ -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);
+1
View File
@@ -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