Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2014-10-04 17:52:43 +04:00
10 changed files with 166 additions and 105 deletions
@@ -20,9 +20,9 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.UnorderedPair;
import com.intellij.psi.JavaTokenType;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -56,32 +56,25 @@ class StateMerger {
for (DfaMemoryStateImpl state : ContainerUtil.concat(statesByFact.get(fact), statesWithNegations)) {
statesByUnrelatedFacts.putValue(getUnrelatedFacts(fact, state), state);
}
Set<DfaMemoryStateImpl> removedStates = ContainerUtil.newIdentityTroveSet();
List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList();
Replacements replacements = new Replacements(states);
for (Set<Fact> key : statesByUnrelatedFacts.keySet()) {
Collection<DfaMemoryStateImpl> group = statesByUnrelatedFacts.get(key);
if (group.size() > 1) {
DfaMemoryStateImpl copy = group.iterator().next().createCopy();
fact.removeFromState(copy);
if (fact.myType == FactType.equality) {
restoreOtherInequalities(fact, group, copy);
final Collection<DfaMemoryStateImpl> group = statesByUnrelatedFacts.get(key);
final Set<DfaVariableValue> unknowns = getAllUnknownVariables(group);
replacements.stripAndMerge(group, new Function<DfaMemoryStateImpl, DfaMemoryStateImpl>() {
@Override
public DfaMemoryStateImpl fun(DfaMemoryStateImpl original) {
DfaMemoryStateImpl copy = withUnknownVariables(original, unknowns);
fact.removeFromState(copy);
if (fact.myType == FactType.equality) {
restoreOtherInequalities(fact, group, copy);
}
return copy;
}
mergeUnknowns(copy, group);
removedStates.addAll(group);
result.add(copy);
}
});
}
if (!result.isEmpty()) {
for (DfaMemoryStateImpl state : states) {
if (!removedStates.contains(state)) {
result.add(state);
}
}
return result;
}
if (replacements.hasMerges()) return replacements.getMergeResult();
}
return null;
}
@@ -129,26 +122,20 @@ class StateMerger {
return otherInequalities;
}
private static void mergeUnknowns(DfaMemoryStateImpl mergedState, Collection<DfaMemoryStateImpl> complementaryStates) {
for (DfaMemoryStateImpl removedState : complementaryStates) {
for (DfaVariableValue unknownVar : removedState.getUnknownVariables()) {
mergedState.doFlush(unknownVar, true);
}
private static Set<DfaVariableValue> getAllUnknownVariables(Collection<DfaMemoryStateImpl> complementary) {
final Set<DfaVariableValue> toFlush = ContainerUtil.newLinkedHashSet();
for (DfaMemoryStateImpl removedState : complementary) {
toFlush.addAll(removedState.getUnknownVariables());
}
return toFlush;
}
private static List<DfaMemoryStateImpl> getMergeResult(List<DfaMemoryStateImpl> statesBeforeMerge,
final THashSet<DfaMemoryStateImpl> mergedStates,
DfaMemoryStateImpl mergeResult) {
List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList();
result.add(mergeResult);
result.addAll(ContainerUtil.filter(statesBeforeMerge, new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state) {
return !mergedStates.contains(state);
}
}));
return result;
private static DfaMemoryStateImpl withUnknownVariables(DfaMemoryStateImpl original, Set<DfaVariableValue> toFlush) {
DfaMemoryStateImpl copy = original.createCopy();
for (DfaVariableValue value : toFlush) {
copy.doFlush(value, true);
}
return copy;
}
@Nullable
@@ -159,6 +146,7 @@ class StateMerger {
byHash.putValue(state.getPartialHashCode(false, true), state);
}
Replacements replacements = new Replacements(states);
for (Integer key : byHash.keySet()) {
Collection<DfaMemoryStateImpl> similarStates = byHash.get(key);
if (similarStates.size() < 2) continue;
@@ -171,16 +159,11 @@ class StateMerger {
return state1.equalsByRelations(state2) && state1.equalsByVariableStates(state2);
}
});
if (complementary.size() > 1) {
DfaMemoryStateImpl copy = state1.createCopy();
mergeUnknowns(copy, complementary);
return getMergeResult(states, ContainerUtil.newIdentityTroveSet(complementary), copy);
}
if (mergeUnknowns(replacements, complementary)) break;
}
}
return null;
return replacements.getMergeResult();
}
@Nullable
@@ -191,10 +174,12 @@ class StateMerger {
byHash.putValue(state.getPartialHashCode(false, false), state);
}
Replacements replacements = new Replacements(states);
for (Integer key : byHash.keySet()) {
Collection<DfaMemoryStateImpl> similarStates = byHash.get(key);
if (similarStates.size() < 2) continue;
groupLoop:
for (final DfaMemoryStateImpl state1 : similarStates) {
ProgressManager.checkCanceled();
for (final DfaVariableValue var : state1.getChangedVariables()) {
@@ -205,25 +190,33 @@ class StateMerger {
List<DfaMemoryStateImpl> complementary = ContainerUtil.filter(similarStates, new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state2) {
return state1.equalsByRelations(state2) &&
return state1.equalsByRelations(state2) &&
areEquivalentModuloVar(state1, state2, var) &&
areVarStatesEqualModuloNullability(state1, state2, var);
}
});
if (complementary.size() > 1) {
DfaMemoryStateImpl copy = state1.createCopy();
mergeUnknowns(copy, complementary);
return getMergeResult(states, ContainerUtil.newIdentityTroveSet(complementary), copy);
}
if (mergeUnknowns(replacements, complementary)) break groupLoop;
}
}
}
return null;
return replacements.getMergeResult();
}
private static boolean mergeUnknowns(Replacements replacements, List<DfaMemoryStateImpl> complementary) {
if (complementary.size() < 2) return false;
final Set<DfaVariableValue> toFlush = getAllUnknownVariables(complementary);
if (toFlush.isEmpty()) return false;
return replacements.stripAndMerge(complementary, new Function<DfaMemoryStateImpl, DfaMemoryStateImpl>() {
@Override
public DfaMemoryStateImpl fun(DfaMemoryStateImpl original) {
return withUnknownVariables(original, toFlush);
}
});
}
private boolean areEquivalentModuloVar(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
DfaMemoryStateImpl copy1 = copyWithoutVar(state1, var);
DfaMemoryStateImpl copy2 = copyWithoutVar(state2, var);
@@ -380,4 +373,51 @@ class StateMerger {
}
}
}
private static class Replacements {
private final List<DfaMemoryStateImpl> myAllStates;
private final Set<DfaMemoryStateImpl> myRemovedStates = ContainerUtil.newIdentityTroveSet();
private final List<DfaMemoryStateImpl> myMerged = ContainerUtil.newArrayList();
Replacements(List<DfaMemoryStateImpl> allStates) {
myAllStates = allStates;
}
boolean hasMerges() { return !myMerged.isEmpty(); }
@Nullable
List<DfaMemoryStateImpl> getMergeResult() {
if (hasMerges()) {
List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList(myMerged);
for (DfaMemoryStateImpl state : myAllStates) {
if (!myRemovedStates.contains(state)) {
result.add(state);
}
}
return result;
}
return null;
}
boolean stripAndMerge(Collection<DfaMemoryStateImpl> group,
Function<DfaMemoryStateImpl, DfaMemoryStateImpl> stripper) {
if (group.size() <= 1) return false;
boolean hasMerges = false;
MultiMap<DfaMemoryStateImpl, DfaMemoryStateImpl> strippedToOriginals = MultiMap.create();
for (DfaMemoryStateImpl original : group) {
strippedToOriginals.putValue(stripper.fun(original), original);
}
for (Map.Entry<DfaMemoryStateImpl, Collection<DfaMemoryStateImpl>> entry : strippedToOriginals.entrySet()) {
Collection<DfaMemoryStateImpl> merged = entry.getValue();
if (merged.size() > 1) {
myRemovedStates.addAll(merged);
myMerged.add(entry.getKey());
hasMerges = true;
}
}
return hasMerges;
}
}
}
@@ -740,7 +740,11 @@ public class JavaDocInfoGenerator {
if (inferred) buffer.append("<i>");
final PsiClassType type = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createType(annotationType, PsiSubstitutor.EMPTY);
buffer.append("@");
generateType(buffer, type, owner, generateLink);
if (inferred && !generateLink) {
buffer.append(type.getPresentableText());
} else {
generateType(buffer, type, owner, generateLink);
}
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
if (attributes.length > 0) {
buffer.append("(");
@@ -778,9 +782,11 @@ public class JavaDocInfoGenerator {
}
} else if (external) {
if (inferred) buffer.append("<i>");
buffer.append(XmlStringUtil.escapeString(annotation.getText()));
buffer.append("&nbsp;");
String annoText = inferred ? "@" + annotation.getNameReferenceElement().getReferenceName() + annotation.getParameterList().getText()
: annotation.getText();
buffer.append(XmlStringUtil.escapeString(annoText));
if (inferred) buffer.append("</i>");
buffer.append("&nbsp;");
}
else {
buffer.append("<font color=red>");
@@ -0,0 +1,16 @@
public abstract class Zzza {
abstract Object getFoo();
void foo(Zzza other) {
int a;
if (other.getFoo() instanceof String) {
a = 1;
} else {
a = 2;
}
other.getFoo().subst<caret>
}
}
@@ -34,6 +34,7 @@ class NormalCompletionDfaTest extends LightFixtureCompletionTestCase {
void testCastTooComplexInstanceofedQualifier() { doAntiTest() }
void testDontCastInstanceofedQualifier() { doTest(); }
void testDontCastPartiallyInstanceofedQualifier() { doAntiTest(); }
void testQualifierCastingWithUnknownAssignments() { doTest(); }
void testQualifierCastingBeforeLt() { doTest(); }
void testCastQualifierForPrivateFieldReference() { doTest(); }
@@ -132,7 +132,7 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
public void testInferredAnnoGutter() {
setUpLibraries();
openDecompiledClass("org.apache.velocity.util.ExceptionUtils");
checkHasGutter("<i>@org.jetbrains.annotations.Contract(&quot;null,_,_-&gt;null&quot;)</i>");
checkHasGutter("<i>@Contract(&quot;null,_,_-&gt;null&quot;)</i>");
}
public void testExternalAnnoGutter() {
@@ -17,7 +17,9 @@
package com.intellij.lang;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -26,6 +28,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
@@ -74,7 +77,7 @@ public final class LanguageUtil {
return language instanceof TemplateLanguage;
}
public static boolean isInjectableLanguage(Language language) {
public static boolean isInjectableLanguage(@NotNull Language language) {
if (language == Language.ANY) {
return false;
}
@@ -93,6 +96,27 @@ public final class LanguageUtil {
return true;
}
public static boolean isFileLanguage(@NotNull Language language) {
if (language instanceof DependentLanguage || language instanceof InjectableLanguage) return false;
if (LanguageParserDefinitions.INSTANCE.forLanguage(language) == null) return false;
LanguageFileType type = language.getAssociatedFileType();
if (type == null || StringUtil.isEmpty(type.getDefaultExtension())) return false;
String name = language.getDisplayName();
if (StringUtil.isEmpty(name) || name.startsWith("<") || name.startsWith("[")) return false;
return StringUtil.isNotEmpty(type.getDefaultExtension());
}
@NotNull
public static List<Language> getFileLanguages() {
List<Language> result = ContainerUtil.newArrayList();
for (Language language : Language.getRegisteredLanguages()) {
if (!isFileLanguage(language)) continue;
result.add(language);
}
Collections.sort(result, LANGUAGE_COMPARATOR);
return result;
}
@NotNull
public static Language getRootLanguage(@NotNull PsiElement element) {
final FileViewProvider provider = element.getContainingFile().getViewProvider();
@@ -16,9 +16,8 @@
package com.intellij.ide.scratch;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.lang.DependentLanguage;
import com.intellij.lang.InjectableLanguage;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
import com.intellij.lang.StdLanguages;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
@@ -31,23 +30,18 @@ import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.ListPopupStep;
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* @author ignatov
@@ -56,7 +50,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
public static final int MAX_VISIBLE_SIZE = 20;
public NewScratchFileAction() {
super("New Scratch Pad...", null, null);
super("New Scratch File...", null, null);
}
@Override
@@ -82,7 +76,7 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
@NotNull
static ListPopup buildLanguagePopup(@Nullable Language previous, final Consumer<Language> onChoosen) {
List<Language> languages = getLanguages();
List<Language> languages = LanguageUtil.getFileLanguages();
BaseListPopupStep<Language> step =
new BaseListPopupStep<Language>("Choose Language", languages) {
@NotNull
@@ -128,30 +122,4 @@ public class NewScratchFileAction extends AnAction implements DumbAware {
}
return popup;
}
@NotNull
private static List<Language> getLanguages() {
Set<Language> result = ContainerUtilRt.newTreeSet(new Comparator<Language>() {
@Override
public int compare(@NotNull Language l1, @NotNull Language l2) {
return l1.getDisplayName().compareTo(l2.getDisplayName());
}
});
for (Language lang : Language.getRegisteredLanguages()) {
if (!StringUtil.isEmpty(lang.getDisplayName())) result.add(lang);
for (Language dialect : lang.getDialects()) result.add(dialect);
}
return ContainerUtil.filter(result, new Condition<Language>() {
@Override
public boolean value(Language lang) {
if (lang instanceof DependentLanguage || lang instanceof InjectableLanguage) return false;
LanguageFileType type = lang.getAssociatedFileType();
if (type == null) return false;
String name = lang.getDisplayName();
if (StringUtil.startsWith(name, "<") || StringUtil.startsWith(name, "[") || StringUtil.isEmpty(name) || StringUtil.equalsIgnoreCase(name, "SQL")) return false;
return !StringUtil.isEmpty(type.getDefaultExtension());
}
});
}
}
@@ -28,6 +28,7 @@ import com.intellij.openapi.wm.CustomStatusBarWidget;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
import com.intellij.openapi.wm.impl.status.TextPanel;
import com.intellij.psi.LanguageSubstitutors;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.ui.ClickListener;
import com.intellij.ui.awt.RelativePoint;
@@ -50,7 +51,7 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
new ClickListener() {
@Override
public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final Project project = getProject();
Project project = getProject();
Editor editor = getEditor();
final LightVirtualFile selectedFile = getScratchFile();
if (project == null || editor == null || selectedFile == null) return false;
@@ -58,7 +59,7 @@ class ScratchWidget extends EditorBasedWidget implements CustomStatusBarWidget.M
ListPopup popup = NewScratchFileAction.buildLanguagePopup(selectedFile.getLanguage(), new Consumer<Language>() {
@Override
public void consume(Language language) {
selectedFile.setLanguage(language);
selectedFile.setLanguage(LanguageSubstitutors.INSTANCE.substituteLanguage(language, selectedFile, myProject));
FileContentUtilCore.reparseFiles(selectedFile);
update();
}
@@ -29,14 +29,12 @@ import com.intellij.openapi.editor.impl.EditorImpl;
import com.intellij.openapi.editor.impl.LineSet;
import com.intellij.openapi.editor.impl.RangeMarkerTree;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,7 +50,7 @@ import java.util.List;
*/
public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, Disposable {
private static final String MY_PANEL_PROPERTY = "EditorTextFieldCellRenderer.MyEditorPanel";
private static final Key<MyPanel> MY_PANEL_PROPERTY = Key.create("EditorTextFieldCellRenderer.MyEditorPanel");
public EditorTextFieldCellRenderer(Disposable parent) {
Disposer.register(parent, this);
@@ -96,7 +94,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
@NotNull
private MyPanel getEditorPanel(JTable table) {
MyPanel panel = (MyPanel)table.getClientProperty(MY_PANEL_PROPERTY);
MyPanel panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
if (panel != null) {
EditorColorsScheme scheme = panel.myEditor.getColorsScheme();
if (scheme instanceof DelegateColorScheme) {
@@ -22,6 +22,7 @@ import git4idea.commands.GitCommand;
import git4idea.commands.GitLineHandler;
import git4idea.i18n.GitBundle;
import git4idea.util.GitUIUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
@@ -101,6 +102,12 @@ public class GitResetDialog extends DialogWrapper {
init();
}
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return myCommitTextField;
}
/**
* Validate
*/