This commit is contained in:
Alexey Kudravtsev
2018-03-22 11:16:03 +03:00
parent 15cd3c027f
commit 8bcd17315c
19 changed files with 214 additions and 219 deletions
@@ -44,7 +44,10 @@ public class GutterIconTooltipHelper {
return composeText(elements, start, pattern, "");
}
public static String composeText(@NotNull Iterable<? extends PsiElement> elements, @NotNull String start, @NotNull String pattern, @NotNull String postfix) {
static String composeText(@NotNull Iterable<? extends PsiElement> elements,
@NotNull String start,
@NotNull String pattern,
@NotNull String postfix) {
@NonNls StringBuilder result = new StringBuilder();
result.append("<html><body>");
result.append(start);
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.lang.java.request.CreateFieldFromUsage;
import com.intellij.lang.jvm.actions.JvmElementActionFactories;
@@ -23,9 +24,6 @@ import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import static com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper.highPriority;
import static com.intellij.openapi.util.text.StringUtil.isUpperCase;
public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
@Override
public void registerFixes(@NotNull PsiJavaCodeReferenceElement ref, @NotNull QuickFixActionRegistrar registrar) {
@@ -90,9 +88,9 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
result.addAll(CreateFieldFromUsage.generateActions(refExpr));
if (!refExpr.isQualified()) {
IntentionAction createLocalFix = new CreateLocalFromUsageFix(refExpr);
result.add(kind == VariableKind.LOCAL_VARIABLE ? highPriority(createLocalFix) : createLocalFix);
result.add(kind == VariableKind.LOCAL_VARIABLE ? PriorityIntentionActionWrapper.highPriority(createLocalFix) : createLocalFix);
IntentionAction createParameterFix = new CreateParameterFromUsageFix(refExpr);
result.add(kind == VariableKind.PARAMETER ? highPriority(createParameterFix) : createParameterFix);
result.add(kind == VariableKind.PARAMETER ? PriorityIntentionActionWrapper.highPriority(createParameterFix) : createParameterFix);
}
return result;
}
@@ -106,7 +104,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
}
if (map.containsKey(kind)) {
map.put(kind, highPriority(map.get(kind)));
map.put(kind, PriorityIntentionActionWrapper.highPriority(map.get(kind)));
}
result.add(new CreateEnumConstantFromUsageFix(refExpr));
@@ -118,7 +116,7 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager, @NotNull PsiReferenceExpression refExpr) {
final String reference = refExpr.getText();
if (isUpperCase(reference)) {
if (StringUtil.isUpperCase(reference)) {
return VariableKind.STATIC_FINAL_FIELD;
}
@@ -149,7 +149,7 @@ public class DeferFinalAssignmentFix implements IntentionAction {
PsiStatement finalAssignment,
ControlFlow controlFlow,
int minOffset,
List references) throws IncorrectOperationException {
@NotNull List<? extends PsiElement> references) throws IncorrectOperationException {
int offset = ControlFlowUtil.getMinDefinitelyReachedOffset(controlFlow, minOffset, references);
if (offset == controlFlow.getSize()) {
codeBlock.add(finalAssignment);
@@ -84,12 +84,12 @@ public class ControlFlowWrapper {
}
}
public PsiStatement getFirstExitStatementCopy() {
PsiStatement getFirstExitStatementCopy() {
return myFirstExitStatementCopy;
}
public Collection<PsiStatement> prepareExitStatements(final @NotNull PsiElement[] elements,
final @NotNull PsiElement enclosingCodeFragment)
public Collection<PsiStatement> prepareExitStatements(@NotNull final PsiElement[] elements,
@NotNull final PsiElement enclosingCodeFragment)
throws ExitStatementsNotSameException {
myExitPoints = new IntArrayList();
myExitStatements = ControlFlowUtil
@@ -138,15 +138,15 @@ public class ControlFlowWrapper {
myFirstExitStatementCopy = (PsiStatement)first.copy();
}
public boolean isGenerateConditionalExit() {
boolean isGenerateConditionalExit() {
return myGenerateConditionalExit;
}
public Collection<PsiStatement> getExitStatements() {
Collection<PsiStatement> getExitStatements() {
return myExitStatements;
}
public boolean needVariableValueAfterEnd(PsiVariable variable) {
public boolean needVariableValueAfterEnd(@NotNull PsiVariable variable) {
return ControlFlowUtil.needVariableValueAt(variable, myControlFlow, myFlowEnd);
}
@@ -159,7 +159,7 @@ public class ControlFlowWrapper {
}
@NotNull
public PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
PsiVariable[] myOutputVariables = ControlFlowUtil.getOutputVariables(myControlFlow, myFlowStart, myFlowEnd, myExitPoints.toArray());
if (collectVariablesAtExitPoints) {
//variables declared in selected block used in return statements are to be considered output variables when extracting guard methods
@@ -199,7 +199,7 @@ public class ControlFlowWrapper {
return myOutputVariables;
}
public boolean isReturnPresentBetween() {
boolean isReturnPresentBetween() {
return ControlFlowUtil.returnPresentBetween(myControlFlow, myFlowStart, myFlowEnd);
}
@@ -276,8 +276,8 @@ public class ControlFlowWrapper {
return myInputVariables;
}
public PsiStatement getExitStatementCopy(PsiElement returnStatement,
final PsiElement[] elements) {
PsiStatement getExitStatementCopy(PsiElement returnStatement,
final PsiElement[] elements) {
PsiStatement exitStatementCopy = null;
// replace all exit-statements such as break's or continue's with appropriate return
for (PsiStatement exitStatement : myExitStatements) {
@@ -323,23 +323,23 @@ public class ControlFlowWrapper {
return exitStatementCopy;
}
public List<PsiVariable> getUsedVariables(int start) {
private List<PsiVariable> getUsedVariables(int start) {
return getUsedVariables(start, myControlFlow.getSize());
}
public List<PsiVariable> getUsedVariables(int start, int end) {
private List<PsiVariable> getUsedVariables(int start, int end) {
return ControlFlowUtil.getUsedVariables(myControlFlow, start, end);
}
public Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(int start) {
private Collection<ControlFlowUtil.VariableInfo> getInitializedTwice(int start) {
return ControlFlowUtil.getInitializedTwice(myControlFlow, start, myControlFlow.getSize());
}
public List<PsiVariable> getUsedVariables() {
List<PsiVariable> getUsedVariables() {
return getUsedVariables(myFlowEnd);
}
public List<PsiVariable> getUsedVariablesInBody(PsiElement codeFragment, PsiVariable[] outputVariables) {
List<PsiVariable> getUsedVariablesInBody(PsiElement codeFragment, PsiVariable[] outputVariables) {
final List<PsiVariable> variables = getUsedVariables(myFlowStart, myFlowEnd);
if (skipVariablesFromExitStatements(outputVariables)) {
removeParametersUsedInExitsOnly(codeFragment, variables);
@@ -354,8 +354,4 @@ public class ControlFlowWrapper {
public Collection<ControlFlowUtil.VariableInfo> getInitializedTwice() {
return getInitializedTwice(myFlowEnd);
}
public void setGenerateConditionalExit(boolean generateConditionalExit) {
myGenerateConditionalExit = generateConditionalExit;
}
}
@@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull;
* when Java references are being resolved.
*
* @author ik, dsl
* @see com.intellij.psi.PsiCall#resolveMethodGenerics()
* @see PsiCall#resolveMethodGenerics()
*/
public interface JavaResolveResult extends ResolveResult {
JavaResolveResult[] EMPTY_ARRAY = new JavaResolveResult[0];
@@ -26,6 +26,7 @@ public interface PsiPostfixExpression extends PsiUnaryExpression {
*
* @return the operand expression.
*/
@Override
@NotNull
PsiExpression getOperand();
@@ -35,6 +36,7 @@ public interface PsiPostfixExpression extends PsiUnaryExpression {
*
* @return the token for the operation performed.
*/
@Override
@NotNull
PsiJavaToken getOperationSign();
}
@@ -72,8 +72,7 @@ public class PsiWildcardType extends PsiType.Stub implements JvmWildcardType {
@NotNull
public static PsiWildcardType createSuper(@NotNull PsiManager manager, @NotNull PsiType bound) {
LOG.assertTrue(!(bound instanceof PsiWildcardType));
LOG.assertTrue(bound != PsiType.NULL);
LOG.assertTrue(!(bound instanceof PsiWildcardType) && bound != PsiType.NULL, bound);
return new PsiWildcardType(manager, false, bound);
}
@@ -163,7 +162,7 @@ public class PsiWildcardType extends PsiType.Stub implements JvmWildcardType {
if (myBound == null && that.myBound != null) {
return that.isExtends() && that.myBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT);
}
else if (myBound != null && that.myBound == null) {
if (myBound != null && that.myBound == null) {
return isExtends() && myBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT);
}
return myIsExtending == that.myIsExtending && Comparing.equal(myBound, that.myBound);
@@ -26,7 +26,7 @@ public class ControlFlowUtil {
private final int myWriteCount;
private final int myInstructionIdx;
public SSAInstructionState(int writeCount, int instructionIdx) {
SSAInstructionState(int writeCount, int instructionIdx) {
myWriteCount = writeCount;
myInstructionIdx = instructionIdx;
}
@@ -38,9 +38,7 @@ public class ControlFlowUtil {
final SSAInstructionState ssaInstructionState = (SSAInstructionState)o;
if (myInstructionIdx != ssaInstructionState.myInstructionIdx) return false;
if (Math.min(2, myWriteCount) != Math.min(2, ssaInstructionState.myWriteCount)) return false;
return true;
return Math.min(2, myWriteCount) == Math.min(2, ssaInstructionState.myWriteCount);
}
public int hashCode() {
@@ -49,24 +47,26 @@ public class ControlFlowUtil {
return result;
}
public int getWriteCount() {
int getWriteCount() {
return myWriteCount;
}
public int getInstructionIdx() {
int getInstructionIdx() {
return myInstructionIdx;
}
}
public static List<PsiVariable> getSSAVariables(ControlFlow flow) {
@NotNull
public static List<PsiVariable> getSSAVariables(@NotNull ControlFlow flow) {
return getSSAVariables(flow, 0, flow.getSize(), false);
}
public static List<PsiVariable> getSSAVariables(ControlFlow flow, int from, int to,
@NotNull
public static List<PsiVariable> getSSAVariables(@NotNull ControlFlow flow, int from, int to,
boolean reportVarsIfNonInitializingPathExists) {
List<Instruction> instructions = flow.getInstructions();
Collection<PsiVariable> writtenVariables = getWrittenVariables(flow, from, to, false);
ArrayList<PsiVariable> result = new ArrayList<>(1);
List<PsiVariable> result = new ArrayList<>(1);
variables:
for (PsiVariable psiVariable : writtenVariables) {
@@ -135,7 +135,7 @@ public class ControlFlowUtil {
return result;
}
public static boolean needVariableValueAt(final PsiVariable variable, final ControlFlow flow, final int offset) {
public static boolean needVariableValueAt(@NotNull PsiVariable variable, @NotNull ControlFlow flow, final int offset) {
InstructionClientVisitor<Boolean> visitor = new InstructionClientVisitor<Boolean>() {
final boolean[] neededBelow = new boolean[flow.getSize() + 1];
@@ -180,17 +180,18 @@ public class ControlFlowUtil {
return visitor.getResult().booleanValue();
}
public static Collection<PsiVariable> getWrittenVariables(ControlFlow flow, int start, int end, final boolean ignoreNotReachingWrites) {
final HashSet<PsiVariable> set = new HashSet<>();
@NotNull
public static Collection<PsiVariable> getWrittenVariables(@NotNull ControlFlow flow, int start, int end, final boolean ignoreNotReachingWrites) {
Set<PsiVariable> set = new HashSet<>();
getWrittenVariables(flow, start, end, ignoreNotReachingWrites, set);
return set;
}
public static void getWrittenVariables(ControlFlow flow,
public static void getWrittenVariables(@NotNull ControlFlow flow,
int start,
int end,
final boolean ignoreNotReachingWrites,
final Collection<PsiVariable> set) {
@NotNull Collection<PsiVariable> set) {
List<Instruction> instructions = flow.getInstructions();
for (int i = start; i < end; i++) {
Instruction instruction = instructions.get(i);
@@ -200,8 +201,9 @@ public class ControlFlowUtil {
}
}
public static List<PsiVariable> getUsedVariables(ControlFlow flow, int start, int end) {
ArrayList<PsiVariable> array = new ArrayList<>();
@NotNull
public static List<PsiVariable> getUsedVariables(@NotNull ControlFlow flow, int start, int end) {
List<PsiVariable> array = new ArrayList<>();
if (start < 0) return array;
List<Instruction> instructions = flow.getInstructions();
for (int i = start; i < end; i++) {
@@ -221,8 +223,8 @@ public class ControlFlowUtil {
}
return array;
}
public static boolean isVariableUsed(ControlFlow flow, int start, int end, PsiVariable variable) {
public static boolean isVariableUsed(@NotNull ControlFlow flow, int start, int end, @NotNull PsiVariable variable) {
List<Instruction> instructions = flow.getInstructions();
LOG.assertTrue(start >= 0, "flow start");
LOG.assertTrue(end <= instructions.size(), "flow end");
@@ -316,9 +318,10 @@ public class ControlFlowUtil {
return false;
}
public static List<PsiVariable> getInputVariables(ControlFlow flow, int start, int end) {
@NotNull
public static List<PsiVariable> getInputVariables(@NotNull ControlFlow flow, int start, int end) {
List<PsiVariable> usedVariables = getUsedVariables(flow, start, end);
ArrayList<PsiVariable> array = new ArrayList<>(usedVariables.size());
List<PsiVariable> array = new ArrayList<>(usedVariables.size());
for (PsiVariable variable : usedVariables) {
if (needVariableValueAt(variable, flow, start)) {
array.add(variable);
@@ -328,9 +331,9 @@ public class ControlFlowUtil {
}
@NotNull
public static PsiVariable[] getOutputVariables(ControlFlow flow, int start, int end, int[] exitPoints) {
public static PsiVariable[] getOutputVariables(@NotNull ControlFlow flow, int start, int end, @NotNull int[] exitPoints) {
Collection<PsiVariable> writtenVariables = getWrittenVariables(flow, start, end, false);
ArrayList<PsiVariable> array = new ArrayList<>();
List<PsiVariable> array = new ArrayList<>();
for (PsiVariable variable : writtenVariables) {
for (int exitPoint : exitPoints) {
if (needVariableValueAt(variable, flow, exitPoint)) {
@@ -348,8 +351,10 @@ public class ControlFlowUtil {
return outputVariables;
}
public static Collection<PsiStatement> findExitPointsAndStatements(final ControlFlow flow, final int start, final int end, final IntArrayList exitPoints,
final Class... classesFilter) {
@NotNull
public static Collection<PsiStatement> findExitPointsAndStatements(@NotNull ControlFlow flow, final int start, final int end,
@NotNull IntArrayList exitPoints,
@NotNull Class... classesFilter) {
if (end == start) {
exitPoints.add(end);
return Collections.emptyList();
@@ -359,12 +364,12 @@ public class ControlFlowUtil {
@Override
public void visitThrowToInstruction(ThrowToInstruction instruction, int offset, int nextOffset) {
//[ven]This is a hack since Extract Method doesn't want to see throw's exit points
processGotoStatement(classesFilter, exitStatements, findStatement(flow, offset));
processGotoStatement(exitStatements, findStatement(flow, offset), classesFilter);
}
@Override
public void visitBranchingInstruction(BranchingInstruction instruction, int offset, int nextOffset) {
processGoto(flow, start, end, exitPoints, exitStatements, instruction, classesFilter, findStatement(flow, offset));
processGoto(flow, start, end, exitPoints, exitStatements, instruction, findStatement(flow, offset), classesFilter);
}
// call/return do not incur exit points
@@ -401,9 +406,11 @@ public class ControlFlowUtil {
return exitStatements;
}
private static void processGoto(ControlFlow flow, int start, int end,
IntArrayList exitPoints,
Collection<PsiStatement> exitStatements, BranchingInstruction instruction, Class[] classesFilter, final PsiStatement statement) {
private static void processGoto(@NotNull ControlFlow flow, int start, int end,
@NotNull IntArrayList exitPoints,
@NotNull Collection<PsiStatement> exitStatements,
@NotNull BranchingInstruction instruction,
final PsiStatement statement, @NotNull Class... classesFilter) {
if (statement == null) return;
int gotoOffset = instruction.offset;
if (start > gotoOffset || gotoOffset >= end || isElementOfClass(statement, classesFilter)) {
@@ -414,27 +421,27 @@ public class ControlFlowUtil {
exitPoints.add(gotoOffset);
}
if (gotoOffset >= end || gotoOffset < start) {
processGotoStatement(classesFilter, exitStatements, statement);
processGotoStatement(exitStatements, statement, classesFilter);
}
else {
boolean isReturn = instruction instanceof GoToInstruction && ((GoToInstruction)instruction).isReturn;
final Instruction gotoInstruction = flow.getInstructions().get(gotoOffset);
isReturn |= gotoInstruction instanceof GoToInstruction && ((GoToInstruction)gotoInstruction).isReturn;
if (isReturn) {
processGotoStatement(classesFilter, exitStatements, statement);
processGotoStatement(exitStatements, statement, classesFilter);
}
}
}
}
private static void processGotoStatement(Class[] classesFilter, Collection<PsiStatement> exitStatements, PsiStatement statement) {
private static void processGotoStatement(@NotNull Collection<PsiStatement> exitStatements,
PsiStatement statement, @NotNull Class... classesFilter) {
if (statement != null && isElementOfClass(statement, classesFilter)) {
exitStatements.add(statement);
}
}
private static boolean isElementOfClass(PsiElement element, Class[] classesFilter) {
if (classesFilter == null) return true;
private static boolean isElementOfClass(@NotNull PsiElement element, @NotNull Class... classesFilter) {
for (Class aClassesFilter : classesFilter) {
if (ReflectionUtil.isAssignable(aClassesFilter, element.getClass())) {
return true;
@@ -443,7 +450,7 @@ public class ControlFlowUtil {
return false;
}
private static int promoteThroughGotoChain(ControlFlow flow, int offset) {
private static int promoteThroughGotoChain(@NotNull ControlFlow flow, int offset) {
List<Instruction> instructions = flow.getInstructions();
while (true) {
if (offset >= instructions.size()) break;
@@ -454,10 +461,9 @@ public class ControlFlowUtil {
return offset;
}
public static final Class[] DEFAULT_EXIT_STATEMENTS_CLASSES =
{PsiReturnStatement.class, PsiBreakStatement.class, PsiContinueStatement.class};
public static final Class[] DEFAULT_EXIT_STATEMENTS_CLASSES = {PsiReturnStatement.class, PsiBreakStatement.class, PsiContinueStatement.class};
private static PsiStatement findStatement(ControlFlow flow, int offset) {
private static PsiStatement findStatement(@NotNull ControlFlow flow, int offset) {
PsiElement element = flow.getElement(offset);
return PsiTreeUtil.getParentOfType(element, PsiStatement.class, false);
}
@@ -490,7 +496,7 @@ public class ControlFlowUtil {
* In the same example {@code hasObservableThrowExitPoints(theOuterBlock) == false},
* because no outgoing variables here depend on the exceptions being thrown.
*/
public static boolean hasObservableThrowExitPoints(final @NotNull ControlFlow flow,
public static boolean hasObservableThrowExitPoints(@NotNull final ControlFlow flow,
final int flowStart,
final int flowEnd,
@NotNull PsiElement[] elements,
@@ -516,7 +522,7 @@ public class ControlFlowUtil {
}
@NotNull
private Map<PsiVariable, IntArrayList> getVisibleReadsOffsets(Map<PsiVariable, IntArrayList> writeOffsets, PsiCodeBlock tryBlock) {
private Map<PsiVariable, IntArrayList> getVisibleReadsOffsets(@NotNull Map<PsiVariable, IntArrayList> writeOffsets, @NotNull PsiCodeBlock tryBlock) {
final Map<PsiVariable, IntArrayList> visibleReadOffsets = new THashMap<>();
for (PsiVariable variable : writeOffsets.keySet()) {
if (!PsiTreeUtil.isAncestor(tryBlock, variable, true)) {
@@ -540,8 +546,8 @@ public class ControlFlowUtil {
}
@NotNull
private Map<PsiVariable, Set<PsiElement>> getReachableAfterWrite(Map<PsiVariable, IntArrayList> writeOffsets,
Map<PsiVariable, IntArrayList> visibleReadOffsets) {
private Map<PsiVariable, Set<PsiElement>> getReachableAfterWrite(@NotNull Map<PsiVariable, IntArrayList> writeOffsets,
@NotNull Map<PsiVariable, IntArrayList> visibleReadOffsets) {
final Map<PsiVariable, Set<PsiElement>> afterWrite = new THashMap<>();
for (PsiVariable variable : visibleReadOffsets.keySet()) {
final Function<Integer, BitSet> calculator = getReachableInstructionsCalculator();
@@ -571,7 +577,7 @@ public class ControlFlowUtil {
}
@NotNull
private IntArrayList getCatchOrFinallyOffsets(List<PsiTryStatement> tryStatements, List<PsiClassType> thrownExceptions) {
private IntArrayList getCatchOrFinallyOffsets(@NotNull List<PsiTryStatement> tryStatements, @NotNull List<PsiClassType> thrownExceptions) {
final IntArrayList catchOrFinallyOffsets = new IntArrayList();
for (PsiTryStatement tryStatement : tryStatements) {
final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
@@ -599,7 +605,7 @@ public class ControlFlowUtil {
return catchOrFinallyOffsets;
}
private boolean isAnyReadOffsetReachableFrom(IntArrayList readOffsets, IntArrayList fromOffsets) {
private boolean isAnyReadOffsetReachableFrom(@Nullable IntArrayList readOffsets, @NotNull IntArrayList fromOffsets) {
if (readOffsets != null && !readOffsets.isEmpty()) {
final int[] readOffsetsArray = readOffsets.toArray();
for (int j = 0; j < fromOffsets.size(); j++) {
@@ -613,6 +619,7 @@ public class ControlFlowUtil {
return false;
}
@NotNull
private Function<Integer, BitSet> getReachableInstructionsCalculator() {
final ControlFlowGraph graph = new ControlFlowGraph(flow.getSize()) {
@Override
@@ -712,7 +719,7 @@ public class ControlFlowUtil {
return codeFragment;
}
private static boolean checkReferenceExpressionScope(final PsiReferenceExpression ref, @NotNull PsiElement targetClassMember) {
private static boolean checkReferenceExpressionScope(@NotNull PsiReferenceExpression ref, @NotNull PsiElement targetClassMember) {
final JavaResolveResult resolveResult = ref.advancedResolve(false);
final PsiElement def = resolveResult.getElement();
if (def != null) {
@@ -748,8 +755,8 @@ public class ControlFlowUtil {
* @param targetClassMember member in target class containing code fragment
* @return true if code fragment can be extracted outside
*/
public static boolean collectOuterLocals(List<PsiVariable> array, PsiElement scope, PsiElement member,
PsiElement targetClassMember) {
public static boolean collectOuterLocals(@NotNull List<PsiVariable> array, @NotNull PsiElement scope, @NotNull PsiElement member,
@NotNull PsiElement targetClassMember) {
if (scope instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression call = (PsiMethodCallExpression)scope;
if (!checkReferenceExpressionScope(call.getMethodExpression(), targetClassMember)) {
@@ -818,14 +825,14 @@ public class ControlFlowUtil {
/**
* @return true if each control flow path results in return statement or exception thrown
*/
public static boolean returnPresent(final ControlFlow flow) {
public static boolean returnPresent(@NotNull ControlFlow flow) {
InstructionClientVisitor<Boolean> visitor = new ReturnPresentClientVisitor(flow);
depthFirstSearch(flow, visitor);
return visitor.getResult().booleanValue();
}
public static boolean processReturns(final ControlFlow flow, final ReturnStatementsVisitor afterVisitor) throws IncorrectOperationException {
public static boolean processReturns(@NotNull ControlFlow flow, @NotNull ReturnStatementsVisitor afterVisitor) throws IncorrectOperationException {
final ConvertReturnClientVisitor instructionsVisitor = new ConvertReturnClientVisitor(flow, afterVisitor);
depthFirstSearch(flow, instructionsVisitor);
@@ -838,7 +845,7 @@ public class ControlFlowUtil {
private final List<PsiReturnStatement> myAffectedReturns;
private final ReturnStatementsVisitor myVisitor;
ConvertReturnClientVisitor(final ControlFlow flow, final ReturnStatementsVisitor visitor) {
ConvertReturnClientVisitor(@NotNull ControlFlow flow, @NotNull ReturnStatementsVisitor visitor) {
super(flow);
myAffectedReturns = new ArrayList<>();
myVisitor = visitor;
@@ -857,7 +864,7 @@ public class ControlFlowUtil {
}
}
public void afterProcessing() throws IncorrectOperationException {
void afterProcessing() throws IncorrectOperationException {
myVisitor.visit(myAffectedReturns);
}
}
@@ -867,7 +874,7 @@ public class ControlFlowUtil {
private final boolean[] isNormalCompletion;
protected final ControlFlow myFlow;
public ReturnPresentClientVisitor(ControlFlow flow) {
ReturnPresentClientVisitor(@NotNull ControlFlow flow) {
myFlow = flow;
isNormalCompletion = new boolean[myFlow.getSize() + 1];
isNormalCompletion[myFlow.getSize()] = true;
@@ -904,15 +911,16 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
return !isNormalCompletion[0];
}
}
public static boolean returnPresentBetween(final ControlFlow flow, final int startOffset, final int endOffset) {
public static boolean returnPresentBetween(@NotNull ControlFlow flow, final int startOffset, final int endOffset) {
class MyVisitor extends InstructionClientVisitor<Boolean> {
// false if control flow at this offset terminates either by return called or exception thrown
final boolean[] isNormalCompletion = new boolean[flow.getSize() + 1];
private final boolean[] isNormalCompletion = new boolean[flow.getSize() + 1];
public MyVisitor() {
int i;
@@ -984,6 +992,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
return !isNormalCompletion[startOffset];
}
@@ -993,27 +1002,14 @@ public class ControlFlowUtil {
return visitor.getResult().booleanValue();
}
@NotNull
public static Object[] getAllWorldProblemsAtOnce(final ControlFlow flow) {
InstructionClientVisitor[] visitors = {
new ReturnPresentClientVisitor(flow),
new UnreachableStatementClientVisitor(flow),
new ReadBeforeWriteClientVisitor(flow, true),
new InitializedTwiceClientVisitor(flow, 0),
};
CompositeInstructionClientVisitor visitor = new CompositeInstructionClientVisitor(visitors);
depthFirstSearch(flow, visitor);
return visitor.getResult();
}
/**
* returns true iff exists controlflow path completing normally, i.e. not resulting in return,break,continue or exception thrown.
* In other words, if we add instruction after controlflow specified, it should be reachable
*/
public static boolean canCompleteNormally(final ControlFlow flow, final int startOffset, final int endOffset) {
public static boolean canCompleteNormally(@NotNull ControlFlow flow, final int startOffset, final int endOffset) {
class MyVisitor extends InstructionClientVisitor<Boolean> {
// false if control flow at this offset terminates abruptly
final boolean[] canCompleteNormally = new boolean[flow.getSize() + 1];
private final boolean[] canCompleteNormally = new boolean[flow.getSize() + 1];
@Override
public void visitConditionalGoToInstruction(ConditionalGoToInstruction instruction, int offset, int nextOffset) {
@@ -1089,6 +1085,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
return canCompleteNormally[startOffset];
}
@@ -1101,7 +1098,7 @@ public class ControlFlowUtil {
/**
* @return any unreachable statement or null
*/
public static PsiElement getUnreachableStatement(final ControlFlow flow) {
public static PsiElement getUnreachableStatement(@NotNull ControlFlow flow) {
final InstructionClientVisitor<PsiElement> visitor = new UnreachableStatementClientVisitor(flow);
depthFirstSearch(flow, visitor);
return visitor.getResult();
@@ -1110,7 +1107,7 @@ public class ControlFlowUtil {
private static class UnreachableStatementClientVisitor extends InstructionClientVisitor<PsiElement> {
private final ControlFlow myFlow;
public UnreachableStatementClientVisitor(ControlFlow flow) {
UnreachableStatementClientVisitor(@NotNull ControlFlow flow) {
myFlow = flow;
}
@@ -1196,14 +1193,14 @@ public class ControlFlowUtil {
}
}
private static PsiReferenceExpression getEnclosingReferenceExpression(PsiElement element, PsiVariable variable) {
private static PsiReferenceExpression getEnclosingReferenceExpression(@NotNull PsiElement element, @NotNull PsiVariable variable) {
final PsiReferenceExpression reference = findReferenceTo(element, variable);
if (reference != null) return reference;
while (element != null) {
if (element instanceof PsiReferenceExpression) {
return (PsiReferenceExpression)element;
}
else if (element instanceof PsiMethod || element instanceof PsiClass) {
if (element instanceof PsiMethod || element instanceof PsiClass) {
return null;
}
element = element.getParent();
@@ -1211,7 +1208,7 @@ public class ControlFlowUtil {
return null;
}
private static PsiReferenceExpression findReferenceTo(PsiElement element, PsiVariable variable) {
private static PsiReferenceExpression findReferenceTo(@NotNull PsiElement element, @NotNull PsiVariable variable) {
if (element instanceof PsiReferenceExpression
&& ExpressionUtil.isEffectivelyUnqualified((PsiReferenceExpression)element)
&& ((PsiReferenceExpression)element).resolve() == variable) {
@@ -1229,7 +1226,7 @@ public class ControlFlowUtil {
public static boolean isVariableDefinitelyAssigned(@NotNull final PsiVariable variable, @NotNull final ControlFlow flow) {
class MyVisitor extends InstructionClientVisitor<Boolean> {
// true if from this point below there may be branch with no variable assignment
final boolean[] maybeUnassigned = new boolean[flow.getSize() + 1];
private final boolean[] maybeUnassigned = new boolean[flow.getSize() + 1];
{
maybeUnassigned[maybeUnassigned.length - 1] = true;
@@ -1279,6 +1276,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
final int variableDeclarationOffset = flow.getStartOffset(variable.getParent());
return !maybeUnassigned[variableDeclarationOffset > -1 ? variableDeclarationOffset : 0];
@@ -1290,10 +1288,10 @@ public class ControlFlowUtil {
return visitor.getResult().booleanValue();
}
public static boolean isVariableDefinitelyNotAssigned(final PsiVariable variable, final ControlFlow flow) {
public static boolean isVariableDefinitelyNotAssigned(@NotNull PsiVariable variable, @NotNull ControlFlow flow) {
class MyVisitor extends InstructionClientVisitor<Boolean> {
// true if from this point below there may be branch with variable assignment
final boolean[] maybeAssigned = new boolean[flow.getSize() + 1];
private final boolean[] maybeAssigned = new boolean[flow.getSize() + 1];
@Override
public void visitWriteVariableInstruction(WriteVariableInstruction instruction, int offset, int nextOffset) {
@@ -1328,6 +1326,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
return !maybeAssigned[0];
}
@@ -1346,12 +1345,12 @@ public class ControlFlowUtil {
* @param variable the variable to examine
* @return true if the value the variable has at start is later referenced without going through stop instruction
*/
public static boolean isValueUsedWithoutVisitingStop(final ControlFlow flow, final int start, final int stop, final PsiVariable variable) {
public static boolean isValueUsedWithoutVisitingStop(@NotNull ControlFlow flow, final int start, final int stop, @NotNull PsiVariable variable) {
if(start == stop) return false;
class MyVisitor extends InstructionClientVisitor<Boolean> {
// true if value the variable has at given offset maybe referenced without going through stop instruction
final boolean[] maybeReferenced = new boolean[flow.getSize() + 1];
private final boolean[] maybeReferenced = new boolean[flow.getSize() + 1];
@Override
public void visitInstruction(Instruction instruction, int offset, int nextOffset) {
@@ -1368,10 +1367,11 @@ public class ControlFlowUtil {
boolean nextState = maybeReferenced[nextOffset];
maybeReferenced[offset] =
nextState || (instruction instanceof ReadVariableInstruction && ((ReadVariableInstruction)instruction).variable == variable);
nextState || instruction instanceof ReadVariableInstruction && ((ReadVariableInstruction)instruction).variable == variable;
}
@Override
@NotNull
public Boolean getResult() {
return maybeReferenced[start];
}
@@ -1389,7 +1389,7 @@ public class ControlFlowUtil {
* @param variable a variable the access to which is to be checked
* @return true if the given instruction is actually a variable access
*/
public static boolean isVariableAccess(ControlFlow flow, int offset, PsiVariable variable) {
public static boolean isVariableAccess(@NotNull ControlFlow flow, int offset, @NotNull PsiVariable variable) {
Instruction instruction = flow.getInstructions().get(offset);
return instruction instanceof ReadVariableInstruction && ((ReadVariableInstruction)instruction).variable == variable ||
instruction instanceof WriteVariableInstruction && ((WriteVariableInstruction)instruction).variable == variable;
@@ -1399,7 +1399,7 @@ public class ControlFlowUtil {
public final int myFrom;
public final int myTo;
public ControlFlowEdge(int from, int to) {
ControlFlowEdge(int from, int to) {
myFrom = from;
myTo = to;
}
@@ -1417,7 +1417,8 @@ public class ControlFlowUtil {
* @param start starting instruction offset
* @return a list of edges
*/
public static List<ControlFlowEdge> getEdges(ControlFlow flow, int start) {
@NotNull
public static List<ControlFlowEdge> getEdges(@NotNull ControlFlow flow, int start) {
final List<ControlFlowEdge> list = new ArrayList<>();
depthFirstSearch(flow, new InstructionClientVisitor<Void>() {
@Override
@@ -1436,11 +1437,11 @@ public class ControlFlowUtil {
/**
* @return min offset after sourceOffset which is definitely reachable from all references
*/
public static int getMinDefinitelyReachedOffset(final ControlFlow flow, final int sourceOffset,
final List references) {
public static int getMinDefinitelyReachedOffset(@NotNull ControlFlow flow, final int sourceOffset,
@NotNull List<? extends PsiElement> references) {
class MyVisitor extends InstructionClientVisitor<Integer> {
// set of exit points reached from this offset
final TIntHashSet[] exitPoints = new TIntHashSet[flow.getSize()];
private final TIntHashSet[] exitPoints = new TIntHashSet[flow.getSize()];
@Override
public void visitInstruction(Instruction instruction, int offset, int nextOffset) {
@@ -1458,6 +1459,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Integer getResult() {
int minOffset = flow.getSize();
int maxExitPoints = 0;
@@ -1467,8 +1469,7 @@ public class ControlFlowUtil {
final int size = exitPointSet == null ? 0 : exitPointSet.size();
if (size > maxExitPoints) {
// this offset should be reachable from all other references
for (Object reference : references) {
PsiElement element = (PsiElement)reference;
for (PsiElement element : references) {
final PsiElement statement = PsiUtil.getEnclosingStatement(element);
if (statement == null) continue;
final int endOffset = flow.getEndOffset(statement);
@@ -1487,7 +1488,7 @@ public class ControlFlowUtil {
return visitor.getResult().intValue();
}
private static int findUnprocessed(int startOffset, int endOffset, InstructionClientVisitor<?> visitor) {
private static int findUnprocessed(int startOffset, int endOffset, @NotNull InstructionClientVisitor<?> visitor) {
for (int i = startOffset; i < endOffset; i++) {
if (!visitor.processedInstructions[i]) {
return i;
@@ -1496,17 +1497,17 @@ public class ControlFlowUtil {
return endOffset;
}
private static void depthFirstSearch(ControlFlow flow, InstructionClientVisitor visitor) {
private static void depthFirstSearch(@NotNull ControlFlow flow, @NotNull InstructionClientVisitor visitor) {
depthFirstSearch(flow, visitor, 0, flow.getSize());
}
private static void depthFirstSearch(ControlFlow flow, InstructionClientVisitor visitor, int startOffset, int endOffset) {
private static void depthFirstSearch(@NotNull ControlFlow flow, @NotNull InstructionClientVisitor visitor, int startOffset, int endOffset) {
visitor.processedInstructions = new boolean[endOffset];
internalDepthFirstSearch(flow.getInstructions(), visitor, startOffset, endOffset);
}
private static void internalDepthFirstSearch(final List<Instruction> instructions,
final InstructionClientVisitor clientVisitor,
private static void internalDepthFirstSearch(@NotNull List<Instruction> instructions,
@NotNull InstructionClientVisitor clientVisitor,
int startOffset,
int endOffset) {
@@ -1680,7 +1681,8 @@ public class ControlFlowUtil {
private static class CopyOnWriteList {
private final List<VariableInfo> list;
public CopyOnWriteList add(VariableInfo value) {
@NotNull
public CopyOnWriteList add(@NotNull VariableInfo value) {
CopyOnWriteList newList = new CopyOnWriteList();
List<VariableInfo> list = getList();
for (final VariableInfo variableInfo : list) {
@@ -1692,7 +1694,8 @@ public class ControlFlowUtil {
return newList;
}
public CopyOnWriteList remove(VariableInfo value) {
@NotNull
public CopyOnWriteList remove(@NotNull VariableInfo value) {
CopyOnWriteList newList = new CopyOnWriteList();
List<VariableInfo> list = getList();
for (final VariableInfo variableInfo : list) {
@@ -1708,19 +1711,20 @@ public class ControlFlowUtil {
return list;
}
public CopyOnWriteList() {
CopyOnWriteList() {
this(Collections.emptyList());
}
public CopyOnWriteList(VariableInfo... infos) {
CopyOnWriteList(@NotNull VariableInfo... infos) {
this(Arrays.asList(infos));
}
public CopyOnWriteList(Collection<VariableInfo> infos) {
CopyOnWriteList(@NotNull Collection<VariableInfo> infos) {
list = new SmartList<>(infos);
}
public CopyOnWriteList addAll(CopyOnWriteList addList) {
@NotNull
public CopyOnWriteList addAll(@NotNull CopyOnWriteList addList) {
CopyOnWriteList newList = new CopyOnWriteList();
List<VariableInfo> list = getList();
newList.list.addAll(list);
@@ -1734,6 +1738,7 @@ public class ControlFlowUtil {
return newList;
}
@NotNull
public static CopyOnWriteList add(@Nullable CopyOnWriteList list, @NotNull VariableInfo value) {
return list == null ? new CopyOnWriteList(value) : list.add(value);
}
@@ -1743,7 +1748,7 @@ public class ControlFlowUtil {
private final PsiVariable variable;
public final PsiElement expression;
public VariableInfo(PsiVariable variable, PsiElement expression) {
public VariableInfo(@NotNull PsiVariable variable, @Nullable PsiElement expression) {
this.variable = variable;
this.expression = expression;
}
@@ -1757,7 +1762,7 @@ public class ControlFlowUtil {
}
}
private static void merge(int offset, CopyOnWriteList source, CopyOnWriteList[] target) {
private static void merge(int offset, CopyOnWriteList source, @NotNull CopyOnWriteList[] target) {
if (source != null) {
CopyOnWriteList existing = target[offset];
target[offset] = existing == null ? source : existing.addAll(source);
@@ -1767,17 +1772,20 @@ public class ControlFlowUtil {
/**
* @return list of PsiReferenceExpression of usages of non-initialized local variables
*/
public static List<PsiReferenceExpression> getReadBeforeWriteLocals(ControlFlow flow) {
@NotNull
public static List<PsiReferenceExpression> getReadBeforeWriteLocals(@NotNull ControlFlow flow) {
final InstructionClientVisitor<List<PsiReferenceExpression>> visitor = new ReadBeforeWriteClientVisitor(flow, true);
depthFirstSearch(flow, visitor);
return visitor.getResult();
}
public static List<PsiReferenceExpression> getReadBeforeWrite(ControlFlow flow) {
@NotNull
public static List<PsiReferenceExpression> getReadBeforeWrite(@NotNull ControlFlow flow) {
return getReadBeforeWrite(flow, 0);
}
public static List<PsiReferenceExpression> getReadBeforeWrite(ControlFlow flow, int startOffset) {
@NotNull
private static List<PsiReferenceExpression> getReadBeforeWrite(@NotNull ControlFlow flow, int startOffset) {
if (startOffset < 0 || startOffset >= flow.getSize()) {
return Collections.emptyList();
}
@@ -1792,7 +1800,7 @@ public class ControlFlowUtil {
private final ControlFlow myFlow;
private final boolean localVariablesOnly;
public ReadBeforeWriteClientVisitor(ControlFlow flow, boolean localVariablesOnly) {
ReadBeforeWriteClientVisitor(@NotNull ControlFlow flow, boolean localVariablesOnly) {
myFlow = flow;
this.localVariablesOnly = localVariablesOnly;
readVariables = new CopyOnWriteList[myFlow.getSize() + 1];
@@ -1845,10 +1853,12 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public List<PsiReferenceExpression> getResult() {
return getResult(0);
}
@NotNull
public List<PsiReferenceExpression> getResult(int startOffset) {
final CopyOnWriteList topReadVariables = readVariables[startOffset];
if (topReadVariables == null) return Collections.emptyList();
@@ -1863,16 +1873,16 @@ public class ControlFlowUtil {
}
public static final int NORMAL_COMPLETION_REASON = 1;
public static final int RETURN_COMPLETION_REASON = 2;
private static final int RETURN_COMPLETION_REASON = 2;
/**
* return reasons.normalCompletion when block can complete normally
* reasons.returnCalled when block can complete abruptly because of return statement executed
*/
public static int getCompletionReasons(final ControlFlow flow, final int offset, final int endOffset) {
public static int getCompletionReasons(@NotNull ControlFlow flow, final int offset, final int endOffset) {
class MyVisitor extends InstructionClientVisitor<Integer> {
final boolean[] normalCompletion = new boolean[endOffset];
final boolean[] returnCalled = new boolean[endOffset];
private final boolean[] normalCompletion = new boolean[endOffset];
private final boolean[] returnCalled = new boolean[endOffset];
@Override
public void visitInstruction(Instruction instruction, int offset, int nextOffset) {
@@ -1897,6 +1907,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Integer getResult() {
return (returnCalled[offset] ? RETURN_COMPLETION_REASON : 0) | (normalCompletion[offset] ? NORMAL_COMPLETION_REASON : 0);
}
@@ -1933,7 +1944,7 @@ public class ControlFlowUtil {
private final ControlFlow myFlow;
private final int myStartOffset;
public InitializedTwiceClientVisitor(@NotNull ControlFlow flow, final int startOffset) {
InitializedTwiceClientVisitor(@NotNull ControlFlow flow, final int startOffset) {
myFlow = flow;
myStartOffset = startOffset;
writtenVariables = new CopyOnWriteList[myFlow.getSize() + 1];
@@ -1969,11 +1980,11 @@ public class ControlFlowUtil {
PsiExpression target = PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)element).getLExpression());
return ObjectUtils.tryCast(target, PsiReferenceExpression.class);
}
else if (element instanceof PsiUnaryExpression) {
if (element instanceof PsiUnaryExpression) {
PsiExpression target = PsiUtil.skipParenthesizedExprDown(((PsiUnaryExpression)element).getOperand());
return ObjectUtils.tryCast(target, PsiReferenceExpression.class);
}
else if (element instanceof PsiDeclarationStatement) {
if (element instanceof PsiDeclarationStatement) {
//should not happen
return element;
}
@@ -1981,7 +1992,7 @@ public class ControlFlowUtil {
}
@Nullable
private static PsiElement getLatestWriteVarExpression(@Nullable CopyOnWriteList writeVars, @Nullable PsiVariable variable) {
private static PsiElement getLatestWriteVarExpression(@Nullable CopyOnWriteList writeVars, @NotNull PsiVariable variable) {
if (writeVars == null) return null;
for (final VariableInfo variableInfo : writeVars.getList()) {
@@ -2009,10 +2020,10 @@ public class ControlFlowUtil {
}
private static boolean areInstructionsReachable(@NotNull final ControlFlow flow,
@NotNull final int[] instructionOffsets,
final int startOffset) {
@NotNull final int[] instructionOffsets,
final int startOffset) {
class MyVisitor extends InstructionClientVisitor<Boolean> {
boolean reachable;
private boolean reachable;
@Override
public void visitInstruction(Instruction instruction, int offset, int nextOffset) {
@@ -2020,6 +2031,7 @@ public class ControlFlowUtil {
}
@Override
@NotNull
public Boolean getResult() {
return reachable;
}
@@ -2037,7 +2049,7 @@ public class ControlFlowUtil {
return visitor.getResult().booleanValue();
}
private static boolean hasCalls(ControlFlow flow) {
private static boolean hasCalls(@NotNull ControlFlow flow) {
for (Instruction instruction : flow.getInstructions()) {
if (instruction instanceof CallInstruction) {
return true;
@@ -2112,7 +2124,7 @@ public class ControlFlowUtil {
return depthFirstSearch(startOffset, new BitSet(size()));
}
boolean depthFirstSearch(final int startOffset, final BitSet visitedOffsets) {
boolean depthFirstSearch(final int startOffset, @NotNull BitSet visitedOffsets) {
// traverse the graph starting with the startOffset
IntStack walkThroughStack = new IntStack(Math.max(size() / 2, 2));
visitedOffsets.clear();
@@ -2143,7 +2155,7 @@ public class ControlFlowUtil {
return false;
}
void buildFrom(ControlFlow flow) {
void buildFrom(@NotNull ControlFlow flow) {
// traverse the whole flow in order to collect the graph edges
ControlFlowUtil.depthFirstSearch(flow, this, 0, flow.getSize());
}
@@ -2153,6 +2165,7 @@ public class ControlFlowUtil {
@NotNull final int[] instructionOffsets,
final int startOffset) {
ControlFlowGraph graph = new ControlFlowGraph(flow.getSize()) {
@Override
boolean isComplete(int offset, int nextOffset) {
return ArrayUtil.indexOf(instructionOffsets, nextOffset) >= 0;
}
@@ -2161,7 +2174,7 @@ public class ControlFlowUtil {
return graph.depthFirstSearch(startOffset);
}
public static boolean isVariableAssignedInLoop(@NotNull PsiReferenceExpression expression, PsiElement resolved) {
public static boolean isVariableAssignedInLoop(@NotNull PsiReferenceExpression expression, @NotNull PsiElement resolved) {
if (!(expression.getParent() instanceof PsiAssignmentExpression)
|| ((PsiAssignmentExpression)expression.getParent()).getLExpression() != expression) {
return false;
@@ -2186,7 +2199,7 @@ public class ControlFlowUtil {
return startOffset != -1 && isInstructionReachable(flow, startOffset, startOffset);
}
public static boolean isCaughtExceptionType(@NotNull PsiClassType throwType, @NotNull PsiType catchType) {
static boolean isCaughtExceptionType(@NotNull PsiClassType throwType, @NotNull PsiType catchType) {
return catchType.isAssignableFrom(throwType) || mightBeAssignableFromSubclass(throwType, catchType);
}
@@ -22,7 +22,7 @@ abstract class InstructionClientVisitor<T> extends ControlFlowInstructionVisitor
return offset == processedInstructions.length;
}
protected boolean[] processedInstructions;
boolean[] processedInstructions;
public void procedureEntered(int startOffset, int endOffset) {
}
@@ -23,24 +23,17 @@ import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import java.util.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.stream.Stream;
/**
* @author max
*/
public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
private static final SmartTypePointer NULL_POINTER = new SmartTypePointer() {
@Override
public PsiType getType() { return null; }
};
private static final SmartTypePointer NULL_POINTER = () -> null;
private final SmartPointerManager myPsiPointerManager;
private final Project myProject;
@@ -73,7 +66,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
private static class ArrayTypePointer extends TypePointerBase<PsiArrayType> {
private final SmartTypePointer myComponentTypePointer;
public ArrayTypePointer(@NotNull PsiArrayType type, @NotNull SmartTypePointer componentTypePointer) {
ArrayTypePointer(@NotNull PsiArrayType type, @NotNull SmartTypePointer componentTypePointer) {
super(type);
myComponentTypePointer = componentTypePointer;
}
@@ -91,7 +84,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
private final SmartTypePointer myBoundPointer;
private final boolean myIsExtending;
public WildcardTypePointer(@NotNull PsiWildcardType type, @Nullable SmartTypePointer boundPointer) {
WildcardTypePointer(@NotNull PsiWildcardType type, @Nullable SmartTypePointer boundPointer) {
super(type);
myManager = type.getManager();
myBoundPointer = boundPointer;
@@ -120,11 +113,11 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
private final Map<SmartPsiElementPointer<PsiTypeParameter>, SmartTypePointer> myMap;
private final SmartPsiElementPointer[] myAnnotations;
public ClassTypePointer(@NotNull PsiClassType type,
@NotNull SmartPsiElementPointer aClass,
@NotNull LanguageLevel languageLevel,
@NotNull Map<SmartPsiElementPointer<PsiTypeParameter>, SmartTypePointer> map,
@NotNull SmartPsiElementPointer[] annotations) {
ClassTypePointer(@NotNull PsiClassType type,
@NotNull SmartPsiElementPointer aClass,
@NotNull LanguageLevel languageLevel,
@NotNull Map<SmartPsiElementPointer<PsiTypeParameter>, SmartTypePointer> map,
@NotNull SmartPsiElementPointer[] annotations) {
super(type);
myClass = aClass;
myLevel = languageLevel;
@@ -416,7 +416,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
final AtomicReference<RuntimeException> stopDaemonReason = new AtomicReference<>();
StorageUtilKt.setDEBUG_LOG("");
getProject().getMessageBus().connect(disposable).subscribe(DaemonCodeAnalyzer.DAEMON_EVENT_TOPIC,
new DaemonCodeAnalyzer.DaemonListenerAdapter() {
new DaemonCodeAnalyzer.DaemonListener() {
@Override
public void daemonCancelEventOccurred(@NotNull String reason) {
RuntimeException e = new RuntimeException("Some bastard's restarted daemon: " + reason +
@@ -911,7 +911,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
TextRange range = ObjectUtils.assertNotNull(FileStatusMap.getDirtyTextRange(getEditor(), Pass.UPDATE_ALL));
log.append("FileStatusMap.getDirtyTextRange: " + range+"\n");
List<PsiElement> elements = CollectHighlightsUtil.getElementsInRange(getFile(), range.getStartOffset(), range.getEndOffset());
log.append("CollectHighlightsUtil.getElementsInRange" + range + ": " + elements.size() +" elements : "+ elements+"\n");
log.append("CollectHighlightsUtil.getElementsInRange: " + range + ": " + elements.size() +" elements : "+ elements+"\n");
List<HighlightInfo> infos = doHighlighting();
log.append(" File text: '" + getFile().getText() + "'\n");
log.append("infos: " + infos + "\n");
@@ -1313,7 +1313,6 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
highlightErrors();
GeneralSettings settings = GeneralSettings.getInstance();
ApplicationEx application = ApplicationManagerEx.getApplicationEx();
boolean frameSave = settings.isSaveOnFrameDeactivation();
settings.setSaveOnFrameDeactivation(true);
UtilKt.runInAllowSaveMode(() -> {
@@ -1692,9 +1691,9 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
type(' ');
CompletionContributor.forLanguage(getFile().getLanguage());
long s = System.currentTimeMillis();
//long s = System.currentTimeMillis();
highlightErrors();
long e = System.currentTimeMillis();
//long e = System.currentTimeMillis();
//System.out.println("Hi elapsed: "+(e-s));
//List<String> dumps = new ArrayList<>();
@@ -2311,9 +2310,7 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
waitForDaemon();
checkFoldingState("[FoldRegion +(25:33), placeholder='{}']");
WriteCommandAction.runWriteCommandAction(myProject, () -> {
myEditor.getDocument().insertString(0, "/*");
});
WriteCommandAction.runWriteCommandAction(myProject, () -> myEditor.getDocument().insertString(0, "/*"));
waitForDaemon();
checkFoldingState("[FoldRegion -(0:37), placeholder='/.../', FoldRegion +(27:35), placeholder='{}']");
@@ -2358,7 +2355,10 @@ public class DaemonRespondToChangesTest extends DaemonAnalyzerTestCase {
UIUtil.dispatchInvocationEvent();
}
while (daemonIsWorkingOrPending()) {
if (System.currentTimeMillis() > deadline) fail("Too long waiting for daemon to finish");
if (System.currentTimeMillis() > deadline) {
dumpThreadsToConsole();
fail("Too long waiting for daemon to finish");
}
UIUtil.dispatchInvocationEvent();
}
}
@@ -31,7 +31,6 @@ import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.Topic;
import gnu.trove.TIntFunction;
import gnu.trove.TObjectIntHashMap;
import gnu.trove.TObjectIntProcedure;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -46,16 +45,15 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
/**
* Always first {@link HighlightDisplayLevel#DO_NOT_SHOW} must be skipped during navigation, editing settings, etc.
*/
public static final int SHOWN_SEVERITIES_OFFSET = 1;
static final int SHOWN_SEVERITIES_OFFSET = 1;
private final static Logger LOG = Logger.getInstance(SeverityRegistrar.class);
private static final Logger LOG = Logger.getInstance(SeverityRegistrar.class);
@NonNls private static final String INFO_TAG = "info";
@NonNls private static final String COLOR_ATTRIBUTE = "color";
private final Map<String, SeverityBasedTextAttributes> myMap = ContainerUtil.newConcurrentMap();
private final Map<String, Color> myRendererColors = ContainerUtil.newConcurrentMap();
public static final Topic<Runnable> SEVERITIES_CHANGED_TOPIC =
Topic.create("SEVERITIES_CHANGED_TOPIC", Runnable.class, Topic.BroadcastDirection.TO_PARENT);
static final Topic<Runnable> SEVERITIES_CHANGED_TOPIC = Topic.create("SEVERITIES_CHANGED_TOPIC", Runnable.class, Topic.BroadcastDirection.TO_PARENT);
@NotNull private final MessageBus myMessageBus;
private volatile OrderMap myOrderMap;
@@ -205,12 +203,9 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
}
else if (!getDefaultOrder().equals(list)) {
final JDOMExternalizableStringList ext = new JDOMExternalizableStringList(Collections.nCopies(getOrderMap().size(), ""));
getOrderMap().forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity orderSeverity, int oIdx) {
ext.set(oIdx, orderSeverity.getName());
return true;
}
getOrderMap().forEachEntry((orderSeverity, oIdx) -> {
ext.set(oIdx, orderSeverity.getName());
return true;
});
ext.writeExternal(element);
}
@@ -226,26 +221,23 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
return list;
}
public int getSeveritiesCount() {
int getSeveritiesCount() {
return createCurrentSeverityNames().size();
}
public HighlightSeverity getSeverityByIndex(final int i) {
final HighlightSeverity[] found = new HighlightSeverity[1];
getOrderMap().forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity severity, int order) {
if (order == i) {
found[0] = severity;
return false;
}
return true;
getOrderMap().forEachEntry((severity, order) -> {
if (order == i) {
found[0] = severity;
return false;
}
return true;
});
return found[0];
}
public int getSeverityMaxIndex() {
int getSeverityMaxIndex() {
int[] values = getOrderMap().getValues();
int max = values[0];
for(int i = 1; i < values.length; ++i) if (values[i] > max) max = values[i];
@@ -271,7 +263,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
return list;
}
public Icon getRendererIconByIndex(int i) {
Icon getRendererIconByIndex(int i) {
final HighlightSeverity severity = getSeverityByIndex(i);
HighlightDisplayLevel level = HighlightDisplayLevel.find(severity);
if (level != null) {
@@ -348,7 +340,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
severitiesChanged();
}
public int getSeverityIdx(@NotNull HighlightSeverity severity) {
int getSeverityIdx(@NotNull HighlightSeverity severity) {
return getOrderMap().getOrder(severity, -1);
}
@@ -356,7 +348,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
return STANDARD_SEVERITIES.containsKey(severity.myName);
}
public static boolean isGotoBySeverityEnabled(@NotNull HighlightSeverity minSeverity) {
static boolean isGotoBySeverityEnabled(@NotNull HighlightSeverity minSeverity) {
for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) {
if (provider.isGotoBySeverityEnabled(minSeverity)) return true;
}
@@ -366,12 +358,9 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
private static class OrderMap extends TObjectIntHashMap<HighlightSeverity> {
private OrderMap(@NotNull TObjectIntHashMap<HighlightSeverity> map) {
super(map.size());
map.forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity key, int value) {
OrderMap.super.put(key, value);
return true;
}
map.forEachEntry((key, value) -> {
super.put(key, value);
return true;
});
trimToSize();
}
@@ -418,7 +407,7 @@ public class SeverityRegistrar implements Comparator<HighlightSeverity> {
private final HighlightInfoType.HighlightInfoTypeImpl myType;
//read external
public SeverityBasedTextAttributes(@NotNull Element element) {
SeverityBasedTextAttributes(@NotNull Element element) {
this(new TextAttributes(element), new HighlightInfoType.HighlightInfoTypeImpl(element));
}
@@ -72,7 +72,7 @@ public class HighlightInfoHolder {
return myErrorCount != 0;
}
public boolean addAll(Collection<? extends HighlightInfo> highlightInfos) {
public boolean addAll(@Nullable Collection<? extends HighlightInfo> highlightInfos) {
if (highlightInfos == null) return false;
LOG.assertTrue(highlightInfos != this);
boolean added = false;
@@ -2,7 +2,6 @@
package com.intellij.openapi.editor.impl;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldRegion;
@@ -18,8 +17,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
abstract class FoldRegionsTree {
private static final Logger LOG = Logger.getInstance(FoldRegionsTree.class);
private final RangeMarkerTree<FoldRegionImpl> myMarkerTree;
@NotNull private volatile CachedData myCachedData = new CachedData();
@@ -56,7 +56,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class SearchForUsagesRunnable implements Runnable {
class SearchForUsagesRunnable implements Runnable {
@NonNls private static final String FIND_OPTIONS_HREF_TARGET = "FindOptions";
@NonNls private static final String SEARCH_IN_PROJECT_HREF_TARGET = "SearchInProject";
@NonNls private static final String LARGE_FILES_HREF_TARGET = "LargeFiles";
@@ -18,6 +18,7 @@ package com.intellij.xml.util;
import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Verifier;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,14 +45,17 @@ public class XmlStringUtil {
return sb.toString();
}
@Contract("null->null; !null->!null")
public static String escapeString(@Nullable String str) {
return escapeString(str, false);
}
@Contract("null,_->null; !null,_->!null")
public static String escapeString(@Nullable String str, final boolean escapeWhiteSpace) {
return escapeString(str, escapeWhiteSpace, true);
}
@Contract("null,_,_->null; !null,_,_->!null")
public static String escapeString(@Nullable String str, final boolean escapeWhiteSpace, final boolean convertNoBreakSpace) {
if (str == null) return null;
StringBuilder buffer = null;
@@ -778,10 +778,10 @@ public class ControlFlowUtils {
* @param variable variable to analyze
* @return true if variable can be referenced between start point and statement entry
*/
private static boolean isVariableReferencedBeforeStatementEntry(final ControlFlow flow,
private static boolean isVariableReferencedBeforeStatementEntry(@NotNull ControlFlow flow,
final int start,
final PsiStatement statement,
final PsiVariable variable) {
@NotNull PsiVariable variable) {
final int statementStart = flow.getStartOffset(statement);
final int statementEnd = flow.getEndOffset(statement);
@@ -849,7 +849,7 @@ public class ControlFlowUtils {
return var.hasModifierProperty(PsiModifier.FINAL) ? UNKNOWN : AT_WANTED_PLACE;
}
static boolean isDeclarationJustBefore(PsiVariable var, PsiStatement nextStatement) {
private static boolean isDeclarationJustBefore(PsiVariable var, PsiStatement nextStatement) {
PsiElement declaration = var.getParent();
PsiElement nextStatementParent = nextStatement.getParent();
if(nextStatementParent instanceof PsiLabeledStatement) {
@@ -180,6 +180,7 @@ public class AntDomPropertyReference extends PsiPolyVariantReferenceBase<PsiElem
return myProvider;
}
@Override
public boolean isValidResult() {
return true;
}
@@ -19,7 +19,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.ResolveResult;
import com.intellij.util.containers.SortedList;
import java.util.Comparator;
import java.util.List;
/**
@@ -41,6 +40,7 @@ public class RatedResolveResult implements ResolveResult {
return myWhat;
}
@Override
public boolean isValidResult() {
return myWhat != null;
}