Merge remote-tracking branch 'origin/master'

This commit is contained in:
Konstantin Bulenkov
2013-09-30 12:15:04 +02:00
12 changed files with 176 additions and 37 deletions
@@ -99,12 +99,9 @@ class StateQueue {
StateMerger merger = new StateMerger();
while (true) {
List<DfaMemoryStateImpl> nextStates = merger.mergeByEquality(memoryStates);
if (nextStates == null) {
nextStates = merger.mergeByType(memoryStates);
}
if (nextStates == null) {
nextStates = merger.mergeByUnknowns(memoryStates);
}
if (nextStates == null) nextStates = merger.mergeByType(memoryStates);
if (nextStates == null) nextStates = merger.mergeByNullability(memoryStates);
if (nextStates == null) nextStates = merger.mergeByUnknowns(memoryStates);
if (nextStates == null) break;
memoryStates = nextStates;
}
@@ -136,14 +136,16 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
public int hashCode() {
return getPartialHashCode(true);
return getPartialHashCode(true, true);
}
int getPartialHashCode(boolean unknowns) {
int hash = ((getNonTrivialEqClasses().hashCode() * 31 +
int getPartialHashCode(boolean unknowns, boolean varStates) {
int hash = (getNonTrivialEqClasses().hashCode() * 31 +
getDistinctClassPairs().hashCode()) * 31 +
myStack.hashCode()) * 31 +
myVariableStates.hashCode();
myStack.hashCode();
if (varStates) {
hash = hash * 31 + myVariableStates.hashCode();
}
if (unknowns) {
hash = hash * 31 + myUnknownVariables.hashCode();
}
@@ -817,14 +819,14 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
}
}
for (DfaVariableValue value : new ArrayList<DfaVariableValue>(getChangedVariable())) {
for (DfaVariableValue value : new ArrayList<DfaVariableValue>(getChangedVariables())) {
if (value.isFlushableByCalls()) {
doFlush(value, true);
}
}
}
Set<DfaVariableValue> getChangedVariable() {
Set<DfaVariableValue> getChangedVariables() {
return myVariableStates.keySet();
}
@@ -112,7 +112,7 @@ class StateMerger {
MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
for (DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
byHash.putValue(state.getPartialHashCode(false), state);
byHash.putValue(state.getPartialHashCode(false, true), state);
}
for (Integer key : byHash.keySet()) {
@@ -139,12 +139,54 @@ class StateMerger {
return null;
}
@Nullable
public List<DfaMemoryStateImpl> mergeByNullability(List<DfaMemoryStateImpl> states) {
MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
for (DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
byHash.putValue(state.getPartialHashCode(false, false), state);
}
for (Integer key : byHash.keySet()) {
Collection<DfaMemoryStateImpl> similarStates = byHash.get(key);
if (similarStates.size() < 2) continue;
for (final DfaMemoryStateImpl state1 : similarStates) {
ProgressManager.checkCanceled();
for (final DfaVariableValue var : state1.getChangedVariables()) {
if (state1.getVariableState(var).getNullability() != Nullness.NULLABLE) {
continue;
}
List<DfaMemoryStateImpl> complementary = ContainerUtil.filter(similarStates, new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state2) {
return state1.equalsSuperficially(state2) &&
state1.equalsByRelations(state2) &&
areEquivalentModuloVar(state1, state2, var) &&
areVarStatesEqualModuloNullability(state1, state2, var);
}
});
if (complementary.size() > 1) {
DfaMemoryStateImpl copy = state1.createCopy();
mergeUnknowns(copy, complementary);
return getMergeResult(copy, ContainerUtil.newHashSet(complementary), states);
}
}
}
}
return null;
}
@Nullable
public List<DfaMemoryStateImpl> mergeByType(List<DfaMemoryStateImpl> states) {
MultiMap<Pair<DfaVariableValue, DfaPsiType>,DfaMemoryStateImpl> byInstanceof = new MultiMap<Pair<DfaVariableValue, DfaPsiType>, DfaMemoryStateImpl>();
for (final DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
for (DfaVariableValue value : state.getChangedVariable()) {
for (DfaVariableValue value : state.getChangedVariables()) {
for (DfaPsiType instanceofValue : state.getVariableState(value).myInstanceofValues) {
byInstanceof.putValue(Pair.create(value, instanceofValue), state);
}
@@ -154,7 +196,7 @@ class StateMerger {
for (final DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
for (final DfaVariableValue var : state.getChangedVariable()) {
for (final DfaVariableValue var : state.getChangedVariables()) {
for (final DfaPsiType notInstanceof : state.getVariableState(var).myNotInstanceofValues) {
final DfaVariableState varStateWithoutType = getVarStateWithoutType(state, var, notInstanceof);
List<DfaMemoryStateImpl> complementaryStates = ContainerUtil.filter(
@@ -163,8 +205,10 @@ class StateMerger {
@Override
public boolean value(DfaMemoryStateImpl another) {
return seemCompatible(state, another, var) &&
another.getVariableState(var).myInstanceofValues.contains(notInstanceof) &&
varStateWithoutType.equals(getVarStateWithoutType(another, var, notInstanceof)) &&
areEquivalentModuloVar(another, state, var);
areEquivalentModuloVar(another, state, var) &&
!(state.isNull(var) && another.isNotNull(var));
}
});
if (complementaryStates.isEmpty()) {
@@ -238,8 +282,8 @@ class StateMerger {
List<DfaMemoryStateImpl> compatible = ContainerUtil.filter(statesByEq.get(createPair(var, value)), new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state2) {
return seemCompatible(state, state2, var) &&
state.getVariableState(var).withNullability(Nullness.UNKNOWN).equals(state2.getVariableState(var).withNullability(Nullness.UNKNOWN));
return seemCompatible(state, state2, var) &&
areVarStatesEqualModuloNullability(state, state2, var);
}
});
if (compatible.isEmpty()) {
@@ -250,6 +294,10 @@ class StateMerger {
return statesByValue;
}
private boolean areVarStatesEqualModuloNullability(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
return state1.getVariableState(var).withNullability(Nullness.UNKNOWN).equals(state2.getVariableState(var).withNullability(Nullness.UNKNOWN));
}
private boolean seemCompatible(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue differentVar) {
if (!state1.equalsSuperficially(state2)) {
return false;
@@ -47,10 +47,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.codeStyle.*;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl;
import com.intellij.psi.search.GlobalSearchScope;
@@ -516,7 +513,7 @@ public class ExtractMethodProcessor implements MatchProvider {
PsiElement prevSibling = PsiTreeUtil.skipSiblingsBackward(myElements[0], PsiWhiteSpace.class);
if (prevSibling instanceof PsiComment && ((PsiComment)prevSibling).getTokenType() == JavaTokenType.END_OF_LINE_COMMENT) {
final String text = prevSibling.getText().trim().replaceAll(" ", "").substring(2);
final String text = StringUtil.decapitalize(StringUtil.capitalizeWords(prevSibling.getText().trim().substring(2), true)).replaceAll(" ", "");
if (JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(text) && text.length() < 20) {
return text;
}
@@ -394,9 +394,6 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(getProject()).getResolveHelper();
PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel);
psiSubstitutor = psiSubstitutor.putAll(substitutor);
if (method.isConstructor()) {
psiSubstitutor = psiSubstitutor.putAll(resolveHelper.inferTypeArguments(method.getContainingClass().getTypeParameters(), types, rightTypes, languageLevel));
}
return LambdaUtil.inferFromReturnType(method.getTypeParameters(),
psiSubstitutor.substitute(method.getReturnType()),
@@ -0,0 +1,21 @@
class Some {
private boolean canBePatternVariable(PsiElement element) {
if (element instanceof LeafElement) {
return true;
}
while (!(element instanceof LeafElement) && element != null) {
element = getNextObject(element);
}
return element != null;
}
PsiElement getNextObject(PsiElement element) { return element; }
class LeafElement {}
interface PsiElement {}
}
@@ -0,0 +1,39 @@
import org.jetbrains.annotations.Nullable;
abstract class Some {
void foo(Object o1, Object o2, Object o3, Object o4, Object o5, Object o6, Object o7, Object o8, Object o9) {
String p1 = unknown() ? bar(o1) : "";
consume(p1 == null ? "" : p1);
String p2 = unknown() ? bar(o2) : "";
consume(p2 == null ? "" : p2);
String p3 = unknown() ? bar(o3) : "";
consume(p3 == null ? "" : p3);
String p4 = unknown() ? bar(o4) : "";
consume(p4 == null ? "" : p4);
String p5 = unknown() ? bar(o5) : "";
consume(p5 == null ? "" : p5);
String p6 = unknown() ? bar(o6) : "";
consume(p6 == null ? "" : p6);
String p7 = unknown() ? bar(o7) : "";
consume(p7 == null ? "" : p7);
String p8 = unknown() ? bar(o8) : "";
consume(p8 == null ? "" : p8);
String p9 = unknown() ? bar(o9) : "";
consume(p9 == null ? "" : p9);
}
abstract void consume(String s);
abstract boolean unknown();
@Nullable abstract String bar(Object o);
}
@@ -307,7 +307,9 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testManyDisjunctiveFieldAssignmentsInLoopNotComplex() { doTest(); }
public void testVariablesDiverge() { doTest(); }
public void testMergeByNullability() { doTest(); }
public void testDontForgetInstanceofInfoWhenMerging() { doTest(); }
public void testDontForgetEqInfoWhenMergingByType() { doTest(); }
public void testDontMakeNullableAfterInstanceof() { doTest(); }
public void _testNullCheckBeforeInstanceof() { doTest(); } // http://youtrack.jetbrains.com/issue/IDEA-113220
@@ -49,4 +49,21 @@ public class SimpleCommit implements TimedVcsCommit {
public List<Hash> getParents() {
return myParents;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SimpleCommit commit = (SimpleCommit)o;
if (myHash != null ? !myHash.equals(commit.myHash) : commit.myHash != null) return false;
return true;
}
@Override
public int hashCode() {
return myHash != null ? myHash.hashCode() : 0;
}
}
@@ -40,4 +40,22 @@ class SimpleHash implements Hash {
public String toShortString() {
return myHash.substring(0, 7);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SimpleHash that = (SimpleHash)o;
if (myHash != null ? !myHash.equals(that.myHash) : that.myHash != null) return false;
return true;
}
@Override
public int hashCode() {
return myHash != null ? myHash.hashCode() : 0;
}
}
@@ -14,7 +14,7 @@ import static junit.framework.Assert.assertEquals;
public class RefParserTest {
public String toStr(VcsRef ref) {
return String.format("%s %s %s", ref.getCommitHash().asString(), ref.getType(), ref.getName());
return String.format("%s TAG %s", ref.getCommitHash().asString(), ref.getName());
}
public void runTest(String inputStr, String outStr) {
@@ -151,15 +151,16 @@ public class GradleImplicitContributor implements GradleMethodContextContributor
}
Module module = ModuleUtilCore.findModuleForPsiElement(place);
if (module != null) {
String path = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
GradleLocalSettings localSettings = GradleLocalSettings.getInstance(place.getProject());
Collection<ExternalTaskPojo> taskPojos = localSettings.getAvailableTasks().get(path);
for (ExternalTaskPojo taskPojo : taskPojos) {
if (taskName.equals(taskPojo.getName())) {
processTask(taskName, GRADLE_API_TASK, psiManager, processor, state, place);
return;
}
if (module == null) return;
String path = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
GradleLocalSettings localSettings = GradleLocalSettings.getInstance(place.getProject());
Collection<ExternalTaskPojo> taskPojos = localSettings.getAvailableTasks().get(path);
if (taskPojos == null) return;
for (ExternalTaskPojo taskPojo : taskPojos) {
if (taskName.equals(taskPojo.getName())) {
processTask(taskName, GRADLE_API_TASK, psiManager, processor, state, place);
return;
}
}
}