From 0179d0c29b495df4a7873420e2cd2218d479fd42 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 14 Dec 2011 16:43:57 +0100 Subject: [PATCH 01/32] search for actions: prepend group name if any --- .../ide/util/gotoByName/GotoActionModel.java | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index b773ec6cfcba..1d3408afcbd8 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -37,7 +37,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { private final Project myProject; @@ -51,11 +54,15 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { private Pattern myCompiledPattern; private final PatternMatcher myMatcher = new Perl5Matcher(); + + private Map myActionsMap = new HashMap(); public GotoActionModel(Project project, final Component component) { myProject = project; myContextComponent = component; + final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU); + collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText()); } public String getPromptText() { @@ -175,7 +182,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { public String[] getNames(boolean checkBoxState) { final ArrayList result = new ArrayList(); - collectActionIds(result, (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU)); + for (AnAction action : myActionsMap.keySet()) { + if (action instanceof ActionGroup) continue; + result.add(getActionId(action)); + } if (checkBoxState) { final Set ids = ((ActionManagerImpl)myActionManager).getActionIds(); for (String id : ids) { @@ -188,22 +198,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { return ArrayUtil.toStringArray(result); } - private void collectActionIds(Collection result, ActionGroup group){ - final AnAction[] actions = group.getChildren(null); - for (AnAction action : actions) { - if (action instanceof ActionGroup) { - collectActionIds(result, (ActionGroup)action); - } - else if (action != null) { - result.add(getActionId(action)); - } - } - } - public Object[] getElementsByName(final String id, final boolean checkBoxState, final String pattern) { final HashMap map = new HashMap(); - final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU); - collectActions(id, map, mainMenu, mainMenu.getTemplatePresentation().getText()); + final AnAction act = myActionManager.getAction(id); + map.put(act, myActionsMap.get(act)); if (checkBoxState) { final Set ids = ((ActionManagerImpl)myActionManager).getActionIds(); for (AnAction action : map.keySet()) { //do not add already included actions @@ -219,15 +217,15 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { return map.entrySet().toArray(new Map.Entry[map.size()]); } - private void collectActions(String id, Map result, ActionGroup group, final String containingGroupName){ + private static void collectActions(Map result, ActionGroup group, final String containingGroupName){ final AnAction[] actions = group.getChildren(null); for (AnAction action : actions) { if (action != null) { if (action instanceof ActionGroup) { final ActionGroup actionGroup = (ActionGroup)action; final String groupName = actionGroup.getTemplatePresentation().getText(); - collectActions(id, result, actionGroup, groupName != null ? groupName : containingGroupName); - } else if (getActionId(action) == id) { + collectActions(result, actionGroup, groupName != null ? groupName : containingGroupName); + } else { final String groupName = group.getTemplatePresentation().getText(); result.put(action, groupName != null && groupName.length() > 0 ? groupName : containingGroupName); } @@ -265,6 +263,10 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { (description != null && myMatcher.matches(description, compiledPattern))) { return true; } + final String groupName = myActionsMap.get(anAction); + if (groupName != null && text != null && myMatcher.matches(groupName + " " + text, compiledPattern)) { + return true; + } } return false; } From 735d3574aa662dbbe11da6ad4f75407bfcf4b14c Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 14 Dec 2011 16:44:40 +0100 Subject: [PATCH 02/32] introduce -> extract --- .../src/messages/ActionsBundle.properties | 26 +++++++++---------- .../src/main/resources/META-INF/plugin.xml | 4 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 0622dc768fba..6a54304b2fc4 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -514,7 +514,7 @@ action.CloneElement.text=Clo_ne... action.CloneElement.description=Create a copy of the selected class, file or directory in the same package/directory action.SafeDelete.text=Safe _Delete... action.SafeDelete.description=Delete the selected class, method or field, checking for usages -action.ExtractMethod.text=E_xtract Method... +action.ExtractMethod.text=_Method... action.ExtractMethod.description=Turn the selected code fragment into a method action.RemoveMiddleman.text=Remove _Middleman... action.RemoveMiddleman.description=Get the client to call the delegate directly @@ -522,25 +522,25 @@ action.MethodDuplicates.text=Replace Met_hod Code Duplicates... action.MethodDuplicates.description=Finds code in current file that can be transformed into a call of selected method action.InvertBoolean.text=Invert _Boolean... action.InvertBoolean.description=Makes the method return or variable contain the opposite value and corrects the references -action.IntroduceParameterObject.text=Introduce Parameter Ob_ject... +action.IntroduceParameterObject.text=Parameter Ob_ject... action.IntroduceParameterObject.description=Replaces method parameters list with object -action.ExtractClass.text=Extract Cla_ss... +action.ExtractClass.text=Cla_ss... action.ExtractClass.description=Extract Delegate -action.IntroduceVariable.text=Introduce _Variable... +action.IntroduceVariable.text=_Variable... action.IntroduceVariable.description=Put a result of the selected expression into a variable -action.IntroduceField.text=Introduce _Field... +action.IntroduceField.text=_Field... action.IntroduceField.description=Put a result of the selected expression into a field -action.IntroduceConstant.text=Introduce _Constant... +action.IntroduceConstant.text=_Constant... action.IntroduceConstant.description=Replace selected expression with a constant (static final field) -action.IntroduceParameter.text=Introduce _Parameter... +action.IntroduceParameter.text=_Parameter... action.IntroduceParameter.description=Turn the selected expression into method parameter -action.ExtractInterface.text=Extract _Interface... +action.ExtractInterface.text=_Interface... action.ExtractInterface.description=Extract interface from the selected class -action.ExtractModule.text=Extract _Module... +action.ExtractModule.text=_Module... action.ExtractModule.description=Extract module from the selected class -action.ExtractSuperclass.text=Extract S_uperclass... +action.ExtractSuperclass.text=S_uperclass... action.ExtractSuperclass.description=Extract superclass from the selected class -group.IntroduceActionsGroup.text=Introd_uce +group.IntroduceActionsGroup.text=E_xtract action.TurnRefsToSuper.text=Use Interface _Where Possible... action.TurnRefsToSuper.description=Change usages of a class to those of its superclass or interface action.MembersPullUp.text=Pu_ll Members Up... @@ -559,7 +559,7 @@ action.ReplaceTempWithQuery.text=Replace Temp with _Query... action.ReplaceTempWithQuery.description=Turn the selected variable into a method action.ReplaceConstructorWithFactory.text=Replace Constructor with F_actory Method... action.ReplaceConstructorWithFactory.description=Create a static factory method and use it instead of a constructor -action.ReplaceMethodWithMethodObject.text=Extract Method Ob_ject... +action.ReplaceMethodWithMethodObject.text=Method Ob_ject... action.ReplaceMethodWithMethodObject.description=Turn the method into its own object so that all the parameters become fields on that object action.Generify.text=Ge_nerify... action.Generify.description=Convert your code to use generic types @@ -567,7 +567,7 @@ action.Migrate.text=_Migrate... action.Migrate.description=Open migration dialog action.Type\ Migration.text=Type Migration... action.Type\ Migration.description=Migrate one type to another -action.ExtractInclude.text=E_xtract Include File... +action.ExtractInclude.text=_Include File... action.ExtractInclude.description=Turn the selected code fragment into included file group.BuildMenu.text=_Build action.CompileProject.text=_Rebuild Project diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml index 832515ed6d5e..865c37124ff6 100644 --- a/plugins/maven/src/main/resources/META-INF/plugin.xml +++ b/plugins/maven/src/main/resources/META-INF/plugin.xml @@ -388,9 +388,9 @@ - + - From 91f49975caadcfbacbbf1bfb30daee5a10c2fa8a Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 14 Dec 2011 16:50:14 +0100 Subject: [PATCH 03/32] cleanup --- .../com/intellij/ide/util/gotoByName/GotoActionModel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java index 1d3408afcbd8..2774d3f5ae1d 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java @@ -120,7 +120,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { final DataContext dataContext = DataManager.getInstance().getDataContext(myContextComponent); - final AnActionEvent event = updateActionBeforShow(anAction, dataContext); + final AnActionEvent event = updateActionBeforeShow(anAction, dataContext); final Presentation presentation = event.getPresentation(); final Color fg = defaultActionForeground(isSelected, presentation); @@ -164,7 +164,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { return actionLabel; } - protected AnActionEvent updateActionBeforShow(AnAction anAction, DataContext dataContext) { + protected static AnActionEvent updateActionBeforeShow(AnAction anAction, DataContext dataContext) { final AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(), 0); @@ -173,7 +173,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { return event; } - protected Color defaultActionForeground(boolean isSelected, Presentation presentation) { + protected static Color defaultActionForeground(boolean isSelected, Presentation presentation) { return isSelected ? UIUtil.getListSelectionForeground() : presentation.isEnabled() && presentation.isVisible() ? UIUtil.getListForeground() @@ -294,7 +294,7 @@ public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel { pattern = pattern.substring(0, 80); } - final @NonNls StringBuffer buffer = new StringBuffer(".*"); + final @NonNls StringBuilder buffer = new StringBuilder(".*"); pattern = pattern.toLowerCase(); for (int i = 0; i < pattern.length(); i++) { final char c = pattern.charAt(i); From a012a230e3a9016d767409a23096f9e400ddad9c Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 14 Dec 2011 17:13:43 +0100 Subject: [PATCH 04/32] correct rename range for inplace rename --- .../src/com/intellij/spellchecker/quickfixes/RenameTo.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java b/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java index e888ad5d421b..b700a27957b6 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/quickfixes/RenameTo.java @@ -25,6 +25,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.impl.text.TextEditorPsiDataProvider; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; @@ -106,6 +107,10 @@ public class RenameTo extends ShowSuggestions implements SpellCheckerQuickFix { DataContext dataContext = SimpleDataContext.getSimpleContext(map, DataManager.getInstance().getDataContext(editor.getComponent())); AnAction action = new RenameElementAction(); + final TextRange range = psiElement.getTextRange(); + if (range != null) { + editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset()); + } AnActionEvent event = new AnActionEvent(null, dataContext, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0); action.actionPerformed(event); if (provider != null) { From aef5aef05f28852f00e18c42e32126ce729392a8 Mon Sep 17 00:00:00 2001 From: Sascha Weinreuter Date: Wed, 14 Dec 2011 17:46:41 +0100 Subject: [PATCH 05/32] new dependencies collection method (fixed serious threading issues) --- .../lang/xpath/psi/impl/ResolveUtil.java | 25 ++++-- .../xslt/context/Xslt2ContextProvider.java | 15 ++-- .../xpath/xslt/impl/XsltIncludeIndex.java | 76 +++++++++++-------- .../xpath/xslt/util/IncludeAwareMatcher.java | 23 ++---- 4 files changed, 77 insertions(+), 62 deletions(-) diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/ResolveUtil.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/ResolveUtil.java index 4e69d9e00d0f..4b08417a9097 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/ResolveUtil.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/psi/impl/ResolveUtil.java @@ -15,7 +15,6 @@ */ package org.intellij.lang.xpath.psi.impl; -import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -25,25 +24,41 @@ import com.intellij.psi.xml.XmlAttribute; import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; -import org.jetbrains.annotations.Nullable; - import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; +import org.intellij.lang.xpath.xslt.impl.XsltIncludeIndex; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; public class ResolveUtil { - public static final Key> DEPENDENCIES = Key.create("XSLT_DEPENDENCIES"); - @SuppressWarnings({"unchecked"}) + @SuppressWarnings({"unchecked"}) private final THashSet myHistory = new THashSet(TObjectHashingStrategy.IDENTITY); private ResolveUtil() { } + @Nullable + public static Collection getDependencies(XmlFile element) { + final CommonProcessors.CollectUniquesProcessor processor = new CommonProcessors.CollectUniquesProcessor() { + @Override + public boolean process(XmlFile file) { + if (!getResults().contains(file)) { + XsltIncludeIndex.processForwardDependencies(file, this); + } + return super.process(file); + } + }; + XsltIncludeIndex.processForwardDependencies(element, processor); + return processor.getResults(); + } + @Nullable public static PsiFile resolveFile(String name, PsiFile baseFile) { if (baseFile == null) return null; diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/context/Xslt2ContextProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/context/Xslt2ContextProvider.java index 054adb037e8a..67a7d3a0018e 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/context/Xslt2ContextProvider.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/context/Xslt2ContextProvider.java @@ -18,7 +18,6 @@ package org.intellij.lang.xpath.xslt.context; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataCache; -import com.intellij.psi.PsiElement; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.ParameterizedCachedValue; @@ -27,7 +26,6 @@ import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; -import com.intellij.util.SmartList; import org.apache.commons.collections.map.CompositeMap; import org.intellij.lang.xpath.context.ContextType; import org.intellij.lang.xpath.context.XPathVersion; @@ -45,8 +43,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.xml.namespace.QName; +import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.Map; public class Xslt2ContextProvider extends XsltContextProviderBase { @@ -170,14 +168,15 @@ public class Xslt2ContextProvider extends XsltContextProviderBase { candidates.put(Pair.create(function.getQName(), function.getParameters().length), function); } - List data = param.getUserData(ResolveUtil.DEPENDENCIES); - if (data == null) { - data = new SmartList(param); + final Collection data = ResolveUtil.getDependencies(param); + final Object[] dependencies; + if (data == null || data.size() == 0) { + dependencies = new Object[]{ param }; } else { data.add(param); - param.putUserData(ResolveUtil.DEPENDENCIES, null); + dependencies = ArrayUtil.toObjectArray(data); } - return CachedValueProvider.Result.create(candidates, ArrayUtil.toObjectArray(data)); + return CachedValueProvider.Result.create(candidates, dependencies); } } } diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltIncludeIndex.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltIncludeIndex.java index d503c7d38428..b15d485771ea 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltIncludeIndex.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltIncludeIndex.java @@ -40,41 +40,55 @@ public class XsltIncludeIndex { public static boolean isReachableFrom(XmlFile which, XmlFile from) { return from == which || _isReachableFrom(from.getVirtualFile(), FileIncludeManager.getManager(which.getProject()).getIncludingFiles(which.getVirtualFile(), true)); - } + } - private static boolean _isReachableFrom(VirtualFile from, VirtualFile[] which) { - //noinspection ForLoopReplaceableByForEach - for (int i = 0; i < which.length; i++) { - final VirtualFile file = which[i]; - if (file == from) { - return true; - } - } - return false; - } - - public static boolean processBackwardDependencies(@NotNull XmlFile file, Processor processor) { - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile == null) { + private static boolean _isReachableFrom(VirtualFile from, VirtualFile[] which) { + //noinspection ForLoopReplaceableByForEach + for (int i = 0; i < which.length; i++) { + final VirtualFile file = which[i]; + if (file == from) { return true; } - final Project project = file.getProject(); - final PsiManager psiManager = PsiManager.getInstance(project); + } + return false; + } - final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludingFiles(virtualFile, true); - final PsiFile[] psiFiles = ContainerUtil.map2Array(files, PsiFile.class, new NullableFunction() { - public PsiFile fun(VirtualFile file) { - return psiManager.findFile(file); - } - }); - for (final PsiFile psiFile : psiFiles) { - if (XsltSupport.isXsltFile(psiFile)) { - if (!processor.process((XmlFile)psiFile)) { - return false; - } - } - } + public static boolean processForwardDependencies(@NotNull XmlFile file, Processor processor) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) { return true; } + final Project project = file.getProject(); -} \ No newline at end of file + final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludedFiles(virtualFile, true); + return _process(files, project, processor); + } + + public static boolean processBackwardDependencies(@NotNull XmlFile file, Processor processor) { + final VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) { + return true; + } + final Project project = file.getProject(); + + final VirtualFile[] files = FileIncludeManager.getManager(project).getIncludingFiles(virtualFile, true); + return _process(files, project, processor); + } + + private static boolean _process(VirtualFile[] files, Project project, Processor processor) { + final PsiManager psiManager = PsiManager.getInstance(project); + final PsiFile[] psiFiles = ContainerUtil.map2Array(files, PsiFile.class, new NullableFunction() { + public PsiFile fun(VirtualFile file) { + return psiManager.findFile(file); + } + }); + for (final PsiFile psiFile : psiFiles) { + if (XsltSupport.isXsltFile(psiFile)) { + if (!processor.process((XmlFile)psiFile)) { + return false; + } + } + } + return true; + } +} diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/IncludeAwareMatcher.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/IncludeAwareMatcher.java index e29e6e4004f7..cf5874eaf60c 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/IncludeAwareMatcher.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/util/IncludeAwareMatcher.java @@ -15,20 +15,15 @@ */ package org.intellij.lang.xpath.xslt.util; -import com.intellij.psi.PsiElement; -import com.intellij.util.SmartList; +import com.intellij.psi.PsiFile; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlDocument; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; import org.intellij.lang.xpath.psi.impl.ResolveUtil; import org.intellij.lang.xpath.xslt.XsltSupport; - -import com.intellij.psi.xml.XmlTag; -import com.intellij.psi.xml.XmlAttribute; -import com.intellij.psi.xml.XmlFile; -import com.intellij.psi.xml.XmlDocument; -import com.intellij.psi.PsiFile; import org.jetbrains.annotations.Nullable; -import java.util.List; - public abstract class IncludeAwareMatcher extends BaseMatcher { protected final XmlDocument myDocument; @@ -53,14 +48,6 @@ public abstract class IncludeAwareMatcher extends BaseMatcher { final PsiFile file = ResolveUtil.resolveFile(href, f); if (file instanceof XmlFile) { - - final List data = myDocument.getContainingFile().getUserData(ResolveUtil.DEPENDENCIES); - if (data == null) { - myDocument.getContainingFile().putUserData(ResolveUtil.DEPENDENCIES, new SmartList(file)); - } else if (!data.contains(file)) { - data.add(file); - } - return Result.create(changeDocument(((XmlFile)file).getDocument())); } } From b4c96dcf92c04329fe832bf946378b88efad98d4 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 14 Dec 2011 19:21:18 +0400 Subject: [PATCH 06/32] use usual indexed for loop --- .../openapi/extensions/impl/ExtensionsAreaImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index 792a57ad9aa8..814e450ead73 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -356,7 +356,8 @@ public class ExtensionsAreaImpl implements ExtensionsArea { final List extensions) { final String areaClass = getAreaClass(); if (extensionsPoints != null) { - for (Element element : extensionsPoints) { + for (int i = 0, size = extensionsPoints.size(); i < size; ++i) { + Element element = extensionsPoints.get(i); if (equal(areaClass, element.getAttributeValue(ATTRIBUTE_AREA))) { registerExtensionPoint(pluginDescriptor, element); } @@ -364,7 +365,8 @@ public class ExtensionsAreaImpl implements ExtensionsArea { } if (extensions != null) { - for (Element element : extensions) { + for (int i = 0, size = extensions.size(); i < size; ++i) { + Element element = extensions.get(i); if (hasExtensionPoint(extractEPName(element))) { registerExtension(pluginDescriptor, element); } From 129a2213de923a5062cd686aab691b3d8908cc7e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 14 Dec 2011 20:38:10 +0400 Subject: [PATCH 07/32] search form references the same way as isTooCheap, also smaller scope to search occurences --- .../cache/impl/IndexCacheManagerImpl.java | 5 +- .../psi/impl/search/PsiSearchHelperImpl.java | 2 +- .../binding/FormReferencesSearcher.java | 51 +++++++------------ 3 files changed, 22 insertions(+), 36 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java index 1d1a6fe5bfd7..8b23fb509d01 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/cache/impl/IndexCacheManagerImpl.java @@ -43,7 +43,6 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.indexing.FileBasedIndex; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -99,12 +98,12 @@ public class IndexCacheManagerImpl implements CacheManager{ public boolean process(final VirtualFile file, final Integer value) { ProgressManager.checkCanceled(); final int mask = value.intValue(); - if ((mask & occurrenceMask) != 0 && scope.contains(file) && shouldBeFound(scope, file, index)) { + if ((mask & occurrenceMask) != 0 && shouldBeFound(scope, file, index)) { if (!fileProcessor.process(file)) return false; } return true; } - }, GlobalSearchScope.allScope(myProject).union(scope)); + }, scope); } }); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 14bdaa670bd6..278ec7b62771 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -363,7 +363,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } } - private boolean processFilesWithText(@NotNull final GlobalSearchScope scope, + public boolean processFilesWithText(@NotNull final GlobalSearchScope scope, final short searchContext, final boolean caseSensitively, @NotNull String text, diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormReferencesSearcher.java b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormReferencesSearcher.java index 56cd49c5ef9e..ccbe1c7804fd 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormReferencesSearcher.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/binding/FormReferencesSearcher.java @@ -13,28 +13,21 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.NullableComputable; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.cache.CacheManager; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.LocalSearchScope; -import com.intellij.psi.search.SearchScope; -import com.intellij.psi.search.UsageSearchContext; +import com.intellij.psi.impl.search.PsiSearchHelperImpl; +import com.intellij.psi.search.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtilCore; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashSet; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; import java.util.List; -import java.util.Set; /** * @author max @@ -246,31 +239,25 @@ public class FormReferencesSearcher implements QueryExecutor words = StringUtil.getWordsIn(name); - if(words.isEmpty()) return true; - - final Set fileSet = new HashSet(); - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - PsiFile[] filesWithWord = CacheManager.SERVICE.getInstance(project).getFilesWithWord(words.get(0), - UsageSearchContext.IN_PLAIN_TEXT, scope, - true); - ContainerUtil.addAll(fileSet, filesWithWord); - for (int i = 1; i < words.size(); i++) { - ProgressManager.checkCanceled(); - String word = words.get(i); - PsiFile[] filesWithThisWord = CacheManager.SERVICE.getInstance(project).getFilesWithWord(word, UsageSearchContext.IN_PLAIN_TEXT, scope, true); - fileSet.retainAll(Arrays.asList(filesWithThisWord)); - if (fileSet.isEmpty()) break; - } + CommonProcessors.CollectProcessor collector = new CommonProcessors.CollectProcessor() { + @Override + protected boolean accept(VirtualFile virtualFile) { + return virtualFile.getFileType() == StdFileTypes.GUI_DESIGNER_FORM; } - }); - PsiFile[] files = PsiUtilCore.toPsiFileArray(fileSet); - - for (PsiFile file : files) { + }; + ((PsiSearchHelperImpl)PsiSearchHelper.SERVICE.getInstance(project)).processFilesWithText( + scope, UsageSearchContext.IN_PLAIN_TEXT, true, name, collector, null + ); + + for (final VirtualFile vfile:collector.getResults()) { ProgressManager.checkCanceled(); - if (file.getFileType() != StdFileTypes.GUI_DESIGNER_FORM) continue; + PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiFile compute() { + return PsiManager.getInstance(project).findFile(vfile); + } + }); if (!processReferences(processor, file, name, property, filterScope)) return false; } } From c301391d39a736fdaff477deab77d4969fbbff08 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 14 Dec 2011 16:43:14 +0400 Subject: [PATCH 08/32] IDEA-78849 it should be able to configure proguard launching [rev=maxim.medvedev] --- .../messages/AndroidBundle.properties | 5 +- .../compiler/AndroidProguardCompiler.java | 13 ++- .../android/exportSignedPackage/ApkStep.form | 28 +++++- .../android/exportSignedPackage/ApkStep.java | 86 +++++++++++++++++++ 4 files changed, 126 insertions(+), 6 deletions(-) diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 5e2930c3a5a2..e0090ed58cf1 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -297,4 +297,7 @@ android.logcat.new.logcat.dialog.label=Filter logcat messages by different android.logcat.new.filter.dialog.name.busy.error=Filter {0} already exists android.compile.messages.processing.external.apklib.dependencies=Processing external apklib dependencies android.maven.cannot.parse.android.sdk.error=Cannot parse Android SDK for module {0}. Try to force reimport from Maven model -android.facet.settings.custom.debug.keystore.label=C&ustom debug keystore\: \ No newline at end of file +android.facet.settings.custom.debug.keystore.label=C&ustom debug keystore\: +android.export.package.run.proguard.label=Run &ProGuard +android.export.package.proguad.config.label=C&onfig file path\: +android.extract.package.specify.proguard.cfg.path.error=Please specify ProGuard config file path \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidProguardCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidProguardCompiler.java index 0c637845975d..466dbf7512a3 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidProguardCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidProguardCompiler.java @@ -12,7 +12,9 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.HashMap; @@ -37,6 +39,7 @@ public class AndroidProguardCompiler implements ClassPostProcessingCompiler { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.compiler.AndroidProguardCompiler"); @NonNls private static final String DIRECTORY_FOR_LOGS_NAME = "proguard_logs"; @NonNls static final String PROGUARD_OUTPUT_JAR_NAME = "obfuscated_sources.jar"; + public static Key PROGUARD_CFG_PATH_KEY = Key.create("ANDROID_PROGUARD_CFG_PATH"); @NotNull @Override @@ -58,11 +61,17 @@ public class AndroidProguardCompiler implements ClassPostProcessingCompiler { continue; } - final VirtualFile proguardConfigFile = AndroidCompileUtil.getProguardConfigFile(facet); - if (proguardConfigFile == null) { + final String proguardCfgPath = context.getCompileScope().getUserData(PROGUARD_CFG_PATH_KEY); + if (proguardCfgPath == null) { continue; } + final VirtualFile proguardConfigFile = + LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(proguardCfgPath)); + if (proguardConfigFile == null) { + context.addMessage(CompilerMessageCategory.ERROR, "Cannot find file " + proguardCfgPath, null, -1, -1); + } + final CompilerModuleExtension extension = CompilerModuleExtension.getInstance(module); if (extension == null) { LOG.error("Cannot find compiler module extension for module " + module.getName()); diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.form b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.form index a9a9acbcc72b..20da15be5808 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.form +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.form @@ -1,9 +1,9 @@
- + - + @@ -18,7 +18,7 @@ - + @@ -30,6 +30,28 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java index 13e67e9d4f3d..df4d512ba3e2 100644 --- a/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java +++ b/plugins/android/src/org/jetbrains/android/exportSignedPackage/ApkStep.java @@ -31,6 +31,8 @@ import com.intellij.openapi.compiler.CompileContext; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompileStatusNotification; import com.intellij.openapi.compiler.CompilerManager; +import com.intellij.openapi.fileChooser.FileChooser; +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -40,10 +42,14 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBLabel; import org.jetbrains.android.compiler.AndroidCompileUtil; import org.jetbrains.android.compiler.AndroidPackagingCompiler; +import org.jetbrains.android.compiler.AndroidProguardCompiler; import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidUtils; @@ -52,6 +58,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -65,10 +73,15 @@ import java.security.cert.X509Certificate; */ class ApkStep extends ExportSignedPackageWizardStep { public static final String APK_PATH_PROPERTY = "ExportedApkPath"; + public static final String RUN_PROGUARD_PROPERTY = "AndroidRunProguardForReleaseBuild"; + public static final String PROGUARD_CFG_PATH_PROPERTY = "AndroidProguardConfigPath"; private TextFieldWithBrowseButton myApkPathField; private JPanel myContentPanel; private JLabel myApkPathLabel; + private JCheckBox myProguardCheckBox; + private JBLabel myProguardConfigFilePathLabel; + private TextFieldWithBrowseButton myProguardConfigFilePathField; private final ExportSignedPackageWizard myWizard; private boolean myInited; @@ -86,6 +99,8 @@ class ApkStep extends ExportSignedPackageWizardStep { public ApkStep(ExportSignedPackageWizard wizard) { myWizard = wizard; myApkPathLabel.setLabelFor(myApkPathField); + myProguardConfigFilePathLabel.setLabelFor(myProguardConfigFilePathField); + myApkPathField.getButton().addActionListener( new SaveFileListener(myContentPanel, myApkPathField, AndroidBundle.message("android.extract.package.choose.dest.apk")) { @Override @@ -94,6 +109,35 @@ class ApkStep extends ExportSignedPackageWizardStep { return getContentRootPath(module); } }); + + myProguardConfigFilePathField.getButton().addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final String path = myProguardConfigFilePathField.getText().trim(); + VirtualFile defaultFile = path != null && path.length() > 0 + ? LocalFileSystem.getInstance().findFileByPath(path) + : null; + final AndroidFacet facet = myWizard.getFacet(); + + if (defaultFile == null && facet != null) { + defaultFile = AndroidRootUtil.getMainContentRoot(facet); + } + final VirtualFile file = FileChooser.chooseFile(myContentPanel, FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor(), + defaultFile); + if (file != null) { + myProguardConfigFilePathField.setText(FileUtil.toSystemDependentName(file.getPath())); + } + } + }); + + myProguardCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final boolean enabled = myProguardCheckBox.isSelected(); + myProguardConfigFilePathLabel.setEnabled(enabled); + myProguardConfigFilePathField.setEnabled(enabled); + } + }); } @Override @@ -114,6 +158,32 @@ class ApkStep extends ExportSignedPackageWizardStep { myApkPathField.setText(defaultPath); } } + + final String runProguardPropValue = properties.getValue(RUN_PROGUARD_PROPERTY); + boolean selected; + + if (runProguardPropValue != null) { + selected = Boolean.parseBoolean(runProguardPropValue); + } + else { + selected = false; + } + myProguardCheckBox.setSelected(selected); + myProguardConfigFilePathLabel.setEnabled(selected); + myProguardConfigFilePathField.setEnabled(selected); + + final String proguardCfgPath = properties.getValue(PROGUARD_CFG_PATH_PROPERTY); + if (proguardCfgPath != null && + LocalFileSystem.getInstance().refreshAndFindFileByPath(proguardCfgPath) != null) { + myProguardConfigFilePathField.setText(FileUtil.toSystemDependentName(proguardCfgPath)); + } + else { + final VirtualFile proguardConfigFile = AndroidCompileUtil.getProguardConfigFile(myWizard.getFacet()); + if (proguardConfigFile != null) { + myProguardConfigFilePathField.setText(FileUtil.toSystemDependentName(proguardConfigFile.getPath())); + } + } + myInited = true; } @@ -266,6 +336,22 @@ class ApkStep extends ExportSignedPackageWizardStep { final CompileScope compileScope = manager.createModuleCompileScope(facet.getModule(), true); AndroidCompileUtil.setReleaseBuild(compileScope); + properties.setValue(RUN_PROGUARD_PROPERTY, Boolean.toString(myProguardCheckBox.isSelected())); + + if (myProguardCheckBox.isSelected()) { + final String proguardCfgPath = myProguardConfigFilePathField.getText().trim(); + if (proguardCfgPath.length() == 0) { + throw new CommitStepException(AndroidBundle.message("android.extract.package.specify.proguard.cfg.path.error")); + } + properties.setValue(PROGUARD_CFG_PATH_PROPERTY, proguardCfgPath); + + if (!new File(proguardCfgPath).isFile()) { + throw new CommitStepException("Cannot find file " + proguardCfgPath); + } + + compileScope.putUserData(AndroidProguardCompiler.PROGUARD_CFG_PATH_KEY, proguardCfgPath); + } + manager.make(compileScope, new CompileStatusNotification() { public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) { if (aborted || errors != 0) { From 5998c28caff93d2d2e75f60528286a489614bfcb Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 14 Dec 2011 18:03:34 +0400 Subject: [PATCH 09/32] clean up; hide Android action group if there is no facet in project --- .../jetbrains/android/actions/AndroidToolsActionGroup.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidToolsActionGroup.java b/plugins/android/src/org/jetbrains/android/actions/AndroidToolsActionGroup.java index 0869faf6d0ba..ae4902ac6297 100644 --- a/plugins/android/src/org/jetbrains/android/actions/AndroidToolsActionGroup.java +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidToolsActionGroup.java @@ -17,8 +17,8 @@ package org.jetbrains.android.actions; import com.intellij.facet.ProjectFacetManager; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DataKeys; import com.intellij.openapi.actionSystem.DefaultActionGroup; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.project.Project; import org.jetbrains.android.facet.AndroidFacet; @@ -28,7 +28,7 @@ import org.jetbrains.android.facet.AndroidFacet; public class AndroidToolsActionGroup extends DefaultActionGroup { @Override public void update(AnActionEvent e) { - final Project project = e.getData(DataKeys.PROJECT); - e.getPresentation().setEnabled(project != null && ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID).size() > 0); + final Project project = e.getData(PlatformDataKeys.PROJECT); + e.getPresentation().setVisible(project != null && ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID).size() > 0); } } From a33e1969ca7cb3dae3f2ae2d56ae2f0744e428e6 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 14 Dec 2011 20:04:01 +0400 Subject: [PATCH 10/32] android preview: show stacktraces from warnings instead of useless ClassCastException error [rev=nnmatveev] --- ...AndroidLayoutPreviewToolWindowManager.java | 20 ++++-- .../android/uipreview/ProjectCallback.java | 15 ++-- .../android/uipreview/RenderUtil.java | 68 ++++++++++++------- .../android/uipreview/RenderingException.java | 15 +++- 4 files changed, 79 insertions(+), 39 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java index 827844b76141..2d1f6473a338 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/AndroidLayoutPreviewToolWindowManager.java @@ -377,11 +377,11 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { LOG.debug(e); String message = e.getPresentableMessage(); message = message != null ? message : AndroidBundle.message("android.layout.preview.default.error.message"); - final Throwable cause = e.getCause(); - errorMessage = cause != null ? new RenderingErrorMessage(message + ' ', "Details", "", new Runnable() { + final Throwable[] causes = e.getCauses(); + errorMessage = causes.length > 0 ? new RenderingErrorMessage(message + ' ', "Details", "", new Runnable() { @Override public void run() { - showStackStace(cause); + showStackStace(causes); } }) : new RenderingErrorMessage(message); } @@ -432,8 +432,16 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { }); } - private void showStackStace(@NotNull Throwable t) { - final String stackTrace = getStackTrace(t); + private void showStackStace(@NotNull Throwable[] throwables) { + final StringBuilder messageBuilder = new StringBuilder(); + + for (Throwable t : throwables) { + if (messageBuilder.length() > 0) { + messageBuilder.append("\n\n"); + } + messageBuilder.append(getStackTrace(t)); + } + final DialogWrapper wrapper = new DialogWrapper(myProject, false) { { @@ -443,7 +451,7 @@ public class AndroidLayoutPreviewToolWindowManager implements ProjectComponent { @Override protected JComponent createCenterPanel() { final JPanel panel = new JPanel(new BorderLayout()); - final JTextArea textArea = new JTextArea(stackTrace); + final JTextArea textArea = new JTextArea(messageBuilder.toString()); textArea.setEditable(false); textArea.setRows(40); textArea.setColumns(70); diff --git a/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java b/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java index bb7d26d52867..8f5c2a3d3521 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/ProjectCallback.java @@ -49,7 +49,7 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback { public static final String FRAGMENT_TAG_NAME = "fragment"; private final Set myMissingClasses = new TreeSet(); - private final Set myBrokenClasses = new TreeSet(); + private final Map myBrokenClasses = new HashMap(); private final Map> myLoadedClasses = new HashMap>(); @@ -103,6 +103,7 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback { return myProjectResources.getResourceId(type, name); } + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") @Nullable public Object loadView(String className, Class[] constructorSignature, Object[] constructorArgs) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException, InstantiationException { @@ -123,23 +124,23 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback { } catch (ClassNotFoundException e) { LOG.info(e); - myBrokenClasses.add(className); + myBrokenClasses.put(className, e.getCause()); } catch (InvocationTargetException e) { LOG.info(e); - myBrokenClasses.add(className); + myBrokenClasses.put(className, e.getCause()); } catch (IllegalAccessException e) { LOG.info(e); - myBrokenClasses.add(className); + myBrokenClasses.put(className, e.getCause()); } catch (InstantiationException e) { LOG.info(e); - myBrokenClasses.add(className); + myBrokenClasses.put(className, e.getCause()); } catch (NoSuchMethodException e) { LOG.info(e); - myBrokenClasses.add(className); + myBrokenClasses.put(className, e.getCause()); } try { @@ -326,7 +327,7 @@ class ProjectCallback extends LegacyCallback implements IProjectCallback { } @NotNull - public Set getBrokenClasses() { + public Map getBrokenClasses() { return myBrokenClasses; } diff --git a/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java b/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java index 6dff138b7cab..e04126ea0ec8 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/RenderUtil.java @@ -7,6 +7,7 @@ import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.VersionQualifier; import com.android.io.*; import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.SdkConstants; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; @@ -30,10 +31,7 @@ import org.xmlpull.v1.XmlPullParserException; import javax.imageio.ImageIO; import java.io.*; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author Eugene.Kudelevsky @@ -115,23 +113,6 @@ class RenderUtil { return false; } - final Result result = session.getResult(); - if (!result.isSuccess()) { - final Throwable exception = result.getException(); - if (exception != null) { - throw new RenderingException(exception); - } - final String message = result.getErrorMessage(); - if (message != null) { - LOG.info(message); - throw new RenderingException(); - } - return false; - } - - final String format = FileUtil.getExtension(imgPath); - ImageIO.write(session.getImage(), format, new File(imgPath)); - if (missingRClass && callback.hasLoadedClasses()) { warningBuilder.append(missingRClassMessage != null && missingRClassMessage.length() > 0 ? ("Class not found error: " + missingRClassMessage + ".") @@ -152,16 +133,16 @@ class RenderUtil { } } - final Set brokenClasses = callback.getBrokenClasses(); + final Map brokenClasses = callback.getBrokenClasses(); if (brokenClasses.size() > 0) { if (brokenClasses.size() > 1) { warningBuilder.append("Unable to initialize:\n"); - for (String brokenClass : brokenClasses) { + for (String brokenClass : brokenClasses.keySet()) { warningBuilder.append(" ").append(brokenClass).append('\n'); } } else { - warningBuilder.append("Unable to initialize ").append(brokenClasses.iterator().next()); + warningBuilder.append("Unable to initialize ").append(brokenClasses.keySet().iterator().next()); } } @@ -169,9 +150,48 @@ class RenderUtil { warningBuilder.deleteCharAt(warningBuilder.length() - 1); } + final Result result = session.getResult(); + if (!result.isSuccess()) { + final Throwable exception = result.getException(); + + if (exception != null) { + final List exceptionsFromWarnings = getNonNullValues(brokenClasses); + + if (exceptionsFromWarnings.size() > 0 && + exception instanceof ClassCastException && + (SdkConstants.CLASS_MOCK_VIEW + " cannot be cast to " + SdkConstants.CLASS_VIEWGROUP) + .equalsIgnoreCase(exception.getMessage())) { + throw new RenderingException(exceptionsFromWarnings.toArray(new Throwable[exceptionsFromWarnings.size()])); + } + throw new RenderingException(exception); + } + final String message = result.getErrorMessage(); + if (message != null) { + LOG.info(message); + throw new RenderingException(); + } + return false; + } + + final String format = FileUtil.getExtension(imgPath); + ImageIO.write(session.getImage(), format, new File(imgPath)); + return true; } + @NotNull + private static List getNonNullValues(@NotNull Map map) { + final List result = new ArrayList(); + + for (Map.Entry entry : map.entrySet()) { + final T value = entry.getValue(); + if (value != null) { + result.add(value); + } + } + return result; + } + private static String getAppLabelToShow(final AndroidFacet facet) { return ApplicationManager.getApplication().runReadAction(new Computable() { @Override diff --git a/plugins/android/src/org/jetbrains/android/uipreview/RenderingException.java b/plugins/android/src/org/jetbrains/android/uipreview/RenderingException.java index 34fefeae50bd..f3525e400e5d 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/RenderingException.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/RenderingException.java @@ -1,29 +1,40 @@ package org.jetbrains.android.uipreview; +import org.jetbrains.annotations.NotNull; + /** * @author Eugene.Kudelevsky */ public class RenderingException extends Exception { private final String myPresentableMessage; + private final Throwable[] myCauses; public RenderingException() { super(); myPresentableMessage = null; + myCauses = new Throwable[0]; } public RenderingException(String message) { super(message); myPresentableMessage = message; + myCauses = new Throwable[0]; } public RenderingException(String message, Throwable cause) { super(message, cause); myPresentableMessage = message; + myCauses = new Throwable[]{cause}; } - public RenderingException(Throwable cause) { - super(cause); + public RenderingException(@NotNull Throwable... causes) { myPresentableMessage = null; + myCauses = causes; + } + + @NotNull + public Throwable[] getCauses() { + return myCauses; } public String getPresentableMessage() { From 3e98a015065bfd42fa3749e96b37e26a9a035b87 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 14 Dec 2011 18:05:36 +0100 Subject: [PATCH 11/32] inplace rename: preserve caret position --- .../introduce/inplace/InplaceVariableIntroducer.java | 5 +++++ .../rename/inplace/VariableInplaceRenamer.java | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java index c2a2981a89aa..04f188809dfc 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java @@ -85,6 +85,11 @@ public class InplaceVariableIntroducer extends VariableInp return true; } + @Override + protected int getOffsetForCaret(RangeMarker rangeMarker, int offset) { + return rangeMarker.isValid() ? rangeMarker.getStartOffset() : offset; + } + @Override protected StartMarkAction startRename() throws StartMarkAction.AlreadyStartedException { return null; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index fc32f5e340b4..0fb1a7c312a4 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -401,7 +401,7 @@ public class VariableInplaceRenamer { //move to old offset Runnable runnable = new Runnable() { public void run() { - myEditor.getCaretModel().moveToOffset(rangeMarker.isValid() ? rangeMarker.getStartOffset() : offset); + myEditor.getCaretModel().moveToOffset(getOffsetForCaret(rangeMarker, offset)); if (selectedRange != null){ myEditor.getSelectionModel().setSelection(selectedRange.getStartOffset(), selectedRange.getEndOffset()); } else if (!shouldSelectAll()){ @@ -411,7 +411,7 @@ public class VariableInplaceRenamer { }; final LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(myEditor); - if (lookup != null && lookup.getLookupStart() <= (rangeMarker.isValid() ? rangeMarker.getStartOffset() : offset)) { + if (lookup != null && lookup.getLookupStart() <= (getOffsetForCaret(rangeMarker, offset))) { lookup.setFocused(false); lookup.performGuardedChange(runnable); } else { @@ -446,6 +446,10 @@ public class VariableInplaceRenamer { return true; } + protected int getOffsetForCaret(RangeMarker rangeMarker, int offset) { + return offset; + } + protected boolean shouldSelectAll() { return false; } From 999b11d530a413bfb3b2e7825620c7c276a00ba1 Mon Sep 17 00:00:00 2001 From: Sascha Weinreuter Date: Wed, 14 Dec 2011 18:27:26 +0100 Subject: [PATCH 12/32] - IDEA-78638: XSLT debug: Xalan: Variables view shows only default value of template parameter - some cleanup --- .../rt/engine/local/AbstractFrame.java | 10 ++++++++++ .../rt/engine/local/saxon/SaxonFrameImpl.java | 2 +- .../engine/local/saxon9/Saxon9StyleFrame.java | 18 ++++++++++-------- .../rt/engine/local/xalan/XalanStyleFrame.java | 17 ++++++++++++----- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/AbstractFrame.java b/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/AbstractFrame.java index 87bd44fd373d..72b23e771c5d 100644 --- a/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/AbstractFrame.java +++ b/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/AbstractFrame.java @@ -59,4 +59,14 @@ public abstract class AbstractFrame implements Frame { public boolean isValid() { return myValid; } + + protected static void debug(Throwable e) { + assert _debug(e); + } + + @SuppressWarnings("CallToPrintStackTrace") + private static boolean _debug(Throwable e) { + e.printStackTrace(); + return true; + } } diff --git a/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/saxon/SaxonFrameImpl.java b/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/saxon/SaxonFrameImpl.java index fd6e60d0d0a7..0185059e714d 100644 --- a/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/saxon/SaxonFrameImpl.java +++ b/plugins/xslt-debugger/engine/impl/src/org/intellij/plugins/xsltDebugger/rt/engine/local/saxon/SaxonFrameImpl.java @@ -218,7 +218,7 @@ class SaxonFrameImpl extends AbstractSaxonFrame extends AbstractSaxon9Frame extends AbstractSaxon9Frame getVariables() { + assert isValid(); + final ArrayList variables = new ArrayList(); final HashMap globalVariables = @@ -177,6 +177,8 @@ class Saxon9StyleFrame extends AbstractSaxon9Frame implements Debu } public List getVariables() { + assert isValid(); + return collectVariables(); } private List collectVariables() { List variables = new ArrayList(); - @SuppressWarnings({ "unchecked" }) + @SuppressWarnings({"unchecked", "UseOfObsoleteCollectionType"}) final Vector globals = myTransformer.getStylesheet().getVariablesAndParamsComposed(); for (ElemVariable variable : globals) { addVariable(variable, true, variables); @@ -127,6 +132,8 @@ class XalanStyleFrame extends AbstractFrame implements Debu } public Value eval(String expr) throws Debugger.EvaluationException { + assert isValid(); + try { final DTMIterator context = myTransformer.getContextNodeList(); @@ -164,7 +171,7 @@ class XalanStyleFrame extends AbstractFrame implements Debu final XPath xPath = new XPath(expr, myCurrentElement, prefixResolver, XPath.SELECT, myTransformer.getErrorListener()); return new XObjectValue(xPath.execute(myContext, myCurrentNode, myCurrentElement)); } catch (Exception e) { - e.printStackTrace(); + debug(e); final String message = e.getMessage(); throw new Debugger.EvaluationException(message != null ? message : e.getClass().getSimpleName()); } From d940f2635d60a4ece7bdcfe0cac8d26596ca0c6d Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Wed, 14 Dec 2011 21:01:20 +0300 Subject: [PATCH 13/32] table arrow/index row renderer fixes --- .../src/com/intellij/ui/table/TableView.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/table/TableView.java b/platform/platform-api/src/com/intellij/ui/table/TableView.java index f550f5322e80..9995209c32cd 100644 --- a/platform/platform-api/src/com/intellij/ui/table/TableView.java +++ b/platform/platform-api/src/com/intellij/ui/table/TableView.java @@ -78,13 +78,23 @@ public class TableView extends BaseTableView implements ItemsProvider, Sel final JTableHeader header = getTableHeader(); final TableCellRenderer defaultRenderer = header == null? null : header.getDefaultRenderer(); + final RowSorter sorter = getRowSorter(); + final List current = sorter == null ? null : sorter.getSortKeys(); ColumnInfo[] columns = getListTableModel().getColumnInfos(); for (int i = 0; i < columns.length; i++) { final ColumnInfo columnInfo = columns[i]; final TableColumn column = getColumnModel().getColumn(i); + // hack to get sort arrow included into the renderer component + if (sorter != null && columnInfo.isSortable()) { + sorter.setSortKeys(Collections.singletonList(new RowSorter.SortKey(0, SortOrder.ASCENDING))); + } final Component headerComponent = defaultRenderer == null? null : defaultRenderer.getTableCellRendererComponent(this, column.getHeaderValue(), false, false, 0, 0); + + if (sorter != null && columnInfo.isSortable()) { + sorter.setSortKeys(current); + } final Dimension headerSize = headerComponent == null? new Dimension(0, 0) : headerComponent.getPreferredSize(); final String maxStringValue; final String preferredValue; From 7cf127da253937760a0e622afda85cfd4b188301 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 14 Dec 2011 20:19:41 +0100 Subject: [PATCH 14/32] Fixed console indentation parse error (PY-5333, PY-4493) --- .../intellij/execution/console/LanguageConsoleViewImpl.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleViewImpl.java index c07b21b5a6e5..7dfcb5d5468e 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleViewImpl.java @@ -20,6 +20,7 @@ import com.intellij.lang.Language; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -27,19 +28,21 @@ import javax.swing.*; * @author Gregory.Shrago */ public class LanguageConsoleViewImpl extends ConsoleViewImpl { + @NotNull protected LanguageConsoleImpl myConsole; public LanguageConsoleViewImpl(final Project project, String title, final Language language) { this(project, new LanguageConsoleImpl(project, title, language)); } - protected LanguageConsoleViewImpl(final Project project, final LanguageConsoleImpl console) { + protected LanguageConsoleViewImpl(final Project project, @NotNull final LanguageConsoleImpl console) { super(project, true); myConsole = console; Disposer.register(this, myConsole); Disposer.register(project, this); } + @NotNull public LanguageConsoleImpl getConsole() { return myConsole; } From 7bb4fa59436e2fb5e40be1389c41bef619033bdd Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 14 Dec 2011 22:10:57 +0100 Subject: [PATCH 15/32] an action to copy PSI to clipboard from PsiViewer, removed similar action in python --- .../internal/psiView/PsiViewerDialog.java | 83 ++++++++++++------- 1 file changed, 54 insertions(+), 29 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java index 9c1881d53a07..678765492a4b 100644 --- a/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java +++ b/platform/lang-impl/src/com/intellij/internal/psiView/PsiViewerDialog.java @@ -50,6 +50,7 @@ import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.*; import com.intellij.openapi.fileTypes.impl.AbstractFileType; +import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; @@ -66,6 +67,7 @@ import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiReference; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.impl.DebugUtil; import com.intellij.psi.impl.source.resolve.FileContextUtil; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.search.FilenameIndex; @@ -91,6 +93,7 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.*; import java.awt.*; +import java.awt.datatransfer.StringSelection; import java.awt.event.*; import java.util.*; import java.util.List; @@ -714,6 +717,29 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp return null; } + @Override + protected Action[] createActions() { + AbstractAction copyPsi = new AbstractAction("Co&py PSI") { + @Override + public void actionPerformed(ActionEvent e) { + PsiElement element = parseText(myEditor.getDocument().getText()); + List allToParse = new ArrayList(); + if (element instanceof PsiFile) { + allToParse.addAll(((PsiFile)element).getViewProvider().getAllFiles()); + } + else if (element != null) { + allToParse.add(element); + } + String data = ""; + for (PsiElement psiElement : allToParse) { + data += DebugUtil.psiToString(psiElement, !myShowWhiteSpacesBox.isSelected(), true); + } + CopyPasteManager.getInstance().setContents(new StringSelection(data)); + } + }; + return ArrayUtil.mergeArrays(new Action[]{copyPsi}, super.createActions()); + } + @Override protected void doOKAction() { if (myBlockTreeBuilder != null) { @@ -725,35 +751,8 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myLastParsedText = text; myLastParsedTextHashCode = text.hashCode(); myNewDocumentHashCode = myLastParsedTextHashCode; - PsiElement rootElement = null; - - final Object source = getSource(); - try { - if (source instanceof PsiViewerExtension) { - final PsiViewerExtension ext = (PsiViewerExtension)source; - rootElement = ext.createElement(myProject, text); - } - else if (source instanceof FileType) { - final FileType type = (FileType)source; - String ext = type.getDefaultExtension(); - if (myExtensionComboBox.isVisible()) { - ext = myExtensionComboBox.getSelectedItem().toString().toLowerCase(); - } - if (type instanceof LanguageFileType) { - final Language language = ((LanguageFileType)type).getLanguage(); - final Language dialect = (Language)myDialectComboBox.getSelectedItem(); - rootElement = PsiFileFactory.getInstance(myProject).createFileFromText("Dummy." + ext, dialect == null ? language : dialect, text); - } - else { - rootElement = PsiFileFactory.getInstance(myProject).createFileFromText("Dummy." + ext, text); - } - } - focusTree(); - } - catch (IncorrectOperationException e) { - rootElement = null; - Messages.showMessageDialog(myProject, e.getMessage(), "Error", Messages.getErrorIcon()); - } + PsiElement rootElement = parseText(text); + focusTree(); ViewerTreeStructure structure = (ViewerTreeStructure)myPsiTreeBuilder.getTreeStructure(); structure.setRootPsiElement(rootElement); @@ -796,6 +795,32 @@ public class PsiViewerDialog extends DialogWrapper implements DataProvider, Disp myBlockTreeBuilder.queueUpdate(); } + private PsiElement parseText(String text) { + final Object source = getSource(); + try { + if (source instanceof PsiViewerExtension) { + return ((PsiViewerExtension)source).createElement(myProject, text); + } + if (source instanceof FileType) { + final FileType type = (FileType)source; + String ext = type.getDefaultExtension(); + if (myExtensionComboBox.isVisible()) { + ext = myExtensionComboBox.getSelectedItem().toString().toLowerCase(); + } + if (type instanceof LanguageFileType) { + final Language language = ((LanguageFileType)type).getLanguage(); + final Language dialect = (Language)myDialectComboBox.getSelectedItem(); + return PsiFileFactory.getInstance(myProject).createFileFromText("Dummy." + ext, dialect == null ? language : dialect, text); + } + return PsiFileFactory.getInstance(myProject).createFileFromText("Dummy." + ext, text); + } + } + catch (IncorrectOperationException e) { + Messages.showMessageDialog(myProject, e.getMessage(), "Error", Messages.getErrorIcon()); + } + return null; + } + @Nullable private static Block buildBlocks(@NotNull PsiElement rootElement) { FormattingModelBuilder formattingModelBuilder = LanguageFormatting.INSTANCE.forContext(rootElement); From d630c4ba3c4d31ca43450374fe5c4cd4291b26f8 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Dec 2011 17:46:50 +0100 Subject: [PATCH 16/32] More suitable default keymap on Linux --- .../options/InitialConfigurationDialog.java | 18 +++++++++--------- .../intellij/openapi/keymap/KeymapManager.java | 3 ++- .../openapi/keymap/impl/DefaultKeymap.java | 15 ++++++++++++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java index e7816ffcbc94..577d96bb4f0e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java +++ b/platform/lang-impl/src/com/intellij/application/options/InitialConfigurationDialog.java @@ -97,7 +97,6 @@ public class InitialConfigurationDialog extends DialogWrapper { setText(keymap.getPresentableName()); } } - }); preselectKeyMap(keymaps); @@ -136,9 +135,10 @@ public class InitialConfigurationDialog extends DialogWrapper { } private void preselectKeyMap(ArrayList keymaps) { - if (SystemInfo.isMac) { + final Keymap defaultKeymap = KeymapManager.getInstance().getActiveKeymap(); + if (defaultKeymap != null) { for (Keymap keymap : keymaps) { - if (keymap.getName().equals("Default for Mac OS X")) { + if (keymap.equals(defaultKeymap)) { myKeymapComboBox.setSelectedItem(keymap); break; } @@ -261,15 +261,15 @@ public class InitialConfigurationDialog extends DialogWrapper { } private static boolean matchesPlatform(Keymap keymap) { - if (keymap.getName().equals(KeymapManager.DEFAULT_IDEA_KEYMAP)) { - return !SystemInfo.isMac; + final String name = keymap.getName(); + if (KeymapManager.DEFAULT_IDEA_KEYMAP.equals(name)) { + return !SystemInfo.isMac && !SystemInfo.isLinux; } - else if (keymap.getName().equals(KeymapManager.MAC_OS_X_KEYMAP)) { + else if (KeymapManager.MAC_OS_X_KEYMAP.equals(name) || "Mac OS X 10.5+".equals(name)) { return SystemInfo.isMac; } - else if (keymap.getName().equals("Default for GNOME") || keymap.getName().equals("Default for KDE") || - keymap.getName().equals("Default for XWin")) { - return SystemInfo.isLinux; + else if (KeymapManager.X_WINDOW_KEYMAP.equals(name) || "Default for GNOME".equals(name) || "Default for KDE".equals(name)) { + return SystemInfo.isUnix && !SystemInfo.isMac; } return true; } diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java index e0b934380c2b..79165ee931dc 100644 --- a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java +++ b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable; public abstract class KeymapManager { @NonNls public static final String DEFAULT_IDEA_KEYMAP = "$default"; @NonNls public static final String MAC_OS_X_KEYMAP = "Mac OS X"; + @NonNls public static final String X_WINDOW_KEYMAP = "Default for XWin"; public abstract Keymap getActiveKeymap(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/DefaultKeymap.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/DefaultKeymap.java index 0a8f3b1a6c19..d9840e39b9eb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/DefaultKeymap.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/DefaultKeymap.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -68,7 +68,8 @@ public class DefaultKeymap { } private void loadKeymapsFromElement(final Element element) throws InvalidDataException { - for (Element child : (List)element.getChildren()) { + @SuppressWarnings("unchecked") final List children = (List)element.getChildren(); + for (Element child : children) { if (KEY_MAP.equals(child.getName())) { String keymapName = child.getAttributeValue(NAME_ATTRIBUTE); DefaultKeymapImpl keymap = keymapName.startsWith(KeymapManager.MAC_OS_X_KEYMAP) ? new MacOSDefaultKeymap() : new DefaultKeymapImpl(); @@ -84,7 +85,15 @@ public class DefaultKeymap { } public String getDefaultKeymapName() { - return SystemInfo.isMac ? KeymapManager.MAC_OS_X_KEYMAP : KeymapManager.DEFAULT_IDEA_KEYMAP; + if (SystemInfo.isMac) { + return KeymapManager.MAC_OS_X_KEYMAP; + } + else if (SystemInfo.isLinux) { + return KeymapManager.X_WINDOW_KEYMAP; + } + else { + return KeymapManager.DEFAULT_IDEA_KEYMAP; + } } public String getKeymapPresentableName(KeymapImpl keymap) { From c09797873d7416cee34c4546b01ad0b10bda98eb Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Dec 2011 18:05:49 +0100 Subject: [PATCH 17/32] Ignore commented lines in .vmoptions --- bin/nix/idea.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/nix/idea.sh b/bin/nix/idea.sh index 5e56bac6d5d3..32360201fba4 100755 --- a/bin/nix/idea.sh +++ b/bin/nix/idea.sh @@ -124,7 +124,7 @@ fi # if VM options file exists - use it if [ -r "$VM_OPTIONS_FILE" ]; then - JVM_ARGS=`tr '\n' ' ' < "$VM_OPTIONS_FILE"` + JVM_ARGS=`cat "$VM_OPTIONS_FILE" | grep -ve "^#.*" | tr '\n' ' '` JVM_ARGS="$JVM_ARGS -Djb.vmOptionsFile=\"$VM_OPTIONS_FILE\"" # only extract properties (not VM options) from Info.plist INFO_PLIST_PARSER_OPTIONS="" From 65b345599b494bd7a792272886c12dad1409db77 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Dec 2011 19:06:30 +0100 Subject: [PATCH 18/32] Fix checkbox tree rendering under Nimbus L&F --- .../src/com/intellij/ui/CheckboxTreeBase.java | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java index ef7b0201d619..c924393d5982 100644 --- a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java +++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.ui; import com.intellij.ui.treeStructure.Tree; @@ -32,9 +31,7 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Enumeration; - public class CheckboxTreeBase extends Tree { - private final CheckPolicy myCheckPolicy; private static final CheckPolicy DEFAULT_POLICY = new CheckPolicy(true, true, false, true); @@ -297,14 +294,7 @@ public class CheckboxTreeBase extends Tree { myUsePartialStatusForParentNodes = usePartialStatusForParentNodes; myCheckbox = new JCheckBox(); myTextRenderer = new ColoredTreeCellRenderer() { - public void customizeCellRenderer(JTree tree, - Object value, - boolean selected, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { - } + public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { } }; myTextRenderer.setOpaque(opaque); add(myCheckbox, BorderLayout.WEST); @@ -315,13 +305,7 @@ public class CheckboxTreeBase extends Tree { this(true); } - public final Component getTreeCellRendererComponent(JTree tree, - Object value, - boolean selected, - boolean expanded, - boolean leaf, - int row, - boolean hasFocus) { + public final Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { invalidate(); if (value instanceof CheckedTreeNode) { CheckedTreeNode node = (CheckedTreeNode)value; @@ -338,15 +322,17 @@ public class CheckboxTreeBase extends Tree { myCheckbox.setVisible(false); } myTextRenderer.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); - // Fix GTK background + if (UIUtil.isUnderGTKLookAndFeel()) { final Color background = selected ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeTextBackground(); UIUtil.changeBackGround(this, background); } + else if (UIUtil.isUnderNimbusLookAndFeel()) { + UIUtil.changeBackGround(this, UIUtil.TRANSPARENT_COLOR); + } customizeRenderer(tree, value, selected, expanded, leaf, row, hasFocus); revalidate(); - return this; } From 1e5e4830b3d73d5822527666a31a56f0d6c0aecd Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 14 Dec 2011 22:51:31 +0100 Subject: [PATCH 19/32] Cleanup --- .../ui/AbstractMemberSelectionTable.java | 42 ++++++++----------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java b/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java index fa33c12636dd..578b811818d8 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java +++ b/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -28,9 +28,8 @@ import com.intellij.refactoring.classMembers.MemberInfoChange; import com.intellij.refactoring.classMembers.MemberInfoChangeListener; import com.intellij.refactoring.classMembers.MemberInfoModel; import com.intellij.ui.*; -import com.intellij.util.containers.Convertor; +import com.intellij.ui.table.JBTable; import com.intellij.util.ui.EmptyIcon; -import com.intellij.util.ui.Table; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -45,22 +44,23 @@ import java.util.List; /** * @author Dennis.Ushakov */ -public abstract class AbstractMemberSelectionTable> extends Table implements TypeSafeDataProvider { +public abstract class AbstractMemberSelectionTable> extends JBTable implements TypeSafeDataProvider { protected static final int CHECKED_COLUMN = 0; protected static final int DISPLAY_NAME_COLUMN = 1; protected static final int ABSTRACT_COLUMN = 2; protected static final Icon OVERRIDING_METHOD_ICON = IconLoader.getIcon("/general/overridingMethod.png"); protected static final Icon IMPLEMENTING_METHOD_ICON = IconLoader.getIcon("/general/implementingMethod.png"); protected static final Icon EMPTY_OVERRIDE_ICON = EmptyIcon.ICON_16; - protected final String myAbstractColumnHeader; protected static final String DISPLAY_NAME_COLUMN_HEADER = RefactoringBundle.message("member.column"); + protected static final int OVERRIDE_ICON_POSITION = 2; + protected static final int VISIBILITY_ICON_POSITION = 1; + protected static final int MEMBER_ICON_POSITION = 0; + + protected final String myAbstractColumnHeader; protected List myMemberInfos; protected final boolean myAbstractEnabled; protected MemberInfoModel myMemberInfoModel; protected MyTableModel myTableModel; - protected static final int OVERRIDE_ICON_POSITION = 2; - protected static final int VISIBILITY_ICON_POSITION = 1; - protected static final int MEMBER_ICON_POSITION = 0; public AbstractMemberSelectionTable(Collection memberInfos, MemberInfoModel memberInfoModel, String abstractColumnHeader) { myAbstractEnabled = abstractColumnHeader != null; @@ -83,11 +83,8 @@ public abstract class AbstractMemberSelectionTable(this)); @@ -143,10 +140,11 @@ public abstract class AbstractMemberSelectionTable changedMembers) { Object[] list = listenerList.getListenerList(); - MemberInfoChange event = new MemberInfoChange(changedMembers); + MemberInfoChange event = new MemberInfoChange(changedMembers); for (Object element : list) { if (element instanceof MemberInfoChangeListener) { - ((MemberInfoChangeListener)element).memberInfoChanged(event); + @SuppressWarnings("unchecked") final MemberInfoChangeListener changeListener = (MemberInfoChangeListener)element; + changeListener.memberInfoChanged(event); } } } @@ -389,18 +387,14 @@ public abstract class AbstractMemberSelectionTable Date: Wed, 14 Dec 2011 23:15:33 +0100 Subject: [PATCH 20/32] Fix boolean table cell renderer for GTK+/Nimbus L&F --- .../intellij/ui/BooleanTableCellRenderer.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java b/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java index 67337270d5ec..5c5426dd244a 100644 --- a/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java +++ b/platform/platform-api/src/com/intellij/ui/BooleanTableCellRenderer.java @@ -16,6 +16,8 @@ package com.intellij.ui; +import com.intellij.util.ui.UIUtil; + import javax.swing.*; import javax.swing.table.TableCellRenderer; import java.awt.*; @@ -32,17 +34,18 @@ public class BooleanTableCellRenderer extends JCheckBox implements TableCellRend setHorizontalAlignment(CENTER); setVerticalAlignment(CENTER); setBorder(null); + setOpaque(true); + myPanel.setOpaque(true); } - public Component getTableCellRendererComponent(JTable table, Object value, - boolean isSel, boolean hasFocus, - int row, int column) { - final Color bg = table.getBackground(); + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSel, boolean hasFocus, int row, int column) { + final Color bg = UIUtil.isUnderNimbusLookAndFeel() && row % 2 == 1 ? UIUtil.TRANSPARENT_COLOR : table.getBackground(); final Color fg = table.getForeground(); final Color selBg = table.getSelectionBackground(); final Color selFg = table.getSelectionForeground(); - if(value == null) { + if (value == null) { myPanel.setBackground(isSel ? selBg : bg); return myPanel; } @@ -52,7 +55,8 @@ public class BooleanTableCellRenderer extends JCheckBox implements TableCellRend if (value instanceof String) { setSelected(Boolean.parseBoolean((String)value)); - } else { + } + else { setSelected(((Boolean)value).booleanValue()); } setEnabled(table.isCellEditable(row, column)); From ed08f14006869d2ff48b81ca5c8e5b5a3ad8c8b7 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 16:05:19 +0400 Subject: [PATCH 21/32] IDEA-77833 Turning on/off soft-wraps for Rails console does not work 1. 'History editor' is configured to always respect additional columns; 2. 'Additional columns' are always respected if soft wraps are off; --- .../src/com/intellij/execution/console/LanguageConsoleImpl.java | 2 +- .../src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 1fb72208c642..da3d82636502 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -681,7 +681,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { // deal with width final int width = Math.max(editorSize.width, historySize.width); newEditorSize.width = width + editor.getScrollPane().getHorizontalScrollBar().getHeight(); - editor.getSoftWrapModel().forceAdditionalColumnsUsage(); + history.getSoftWrapModel().forceAdditionalColumnsUsage(); editor.getSettings().setAdditionalColumnsCount(2 + (width - editorSize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, editor)); history.getSettings().setAdditionalColumnsCount(2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, history)); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index e7916cc79493..6070885e959e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -211,7 +211,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi @Override public boolean isRespectAdditionalColumns() { - return myForceAdditionalColumns || myApplianceManager.hasLinesWithFailedWrap(); + return myForceAdditionalColumns || !isSoftWrappingEnabled() || myApplianceManager.hasLinesWithFailedWrap(); } @Override From ab1cd20c186e8312a51f26aeb97d24a48ee38667 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 16:11:04 +0400 Subject: [PATCH 22/32] EA-32436 - NPE: LocalFileSystemBase.findFileByIoFile --- .../org/jetbrains/plugins/gradle/util/GradleLibraryManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java index d7a61268ab8a..cd1621f70b2b 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleLibraryManager.java @@ -142,7 +142,7 @@ public class GradleLibraryManager { } final File home = getGradleHome(project); - return LocalFileSystem.getInstance().findFileByIoFile(home); + return home == null ? null : LocalFileSystem.getInstance().findFileByIoFile(home); } /** From eb8ed358376005f9e398211a789636aded7c9bcb Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 16:15:53 +0400 Subject: [PATCH 23/32] EA-32287 - IOOBE: EditorImpl.a --- .../intellij/codeInsight/folding/CodeFoldingManager.java | 3 ++- .../codeInsight/folding/impl/CodeFoldingManagerImpl.java | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java index ba99b14f5d2a..be52c03fed31 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/CodeFoldingManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -38,6 +38,7 @@ public abstract class CodeFoldingManager { @Nullable public abstract Runnable updateFoldRegionsAsync(@NotNull Editor editor, boolean firstTime); + @Nullable public abstract FoldRegion findFoldRegion(@NotNull Editor editor, int startOffset, int endOffset); public abstract FoldRegion[] getFoldRegionsAtOffset(@NotNull Editor editor, int offset); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java index 31d7799409d2..fcb172b585cc 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/CodeFoldingManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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,7 +19,6 @@ package com.intellij.codeInsight.folding.impl; import com.intellij.codeInsight.folding.CodeFoldingManager; import com.intellij.codeInsight.hint.EditorFragmentComponent; import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.editor.*; @@ -102,7 +101,7 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec MouseEvent mouseEvent = e.getMouseEvent(); FoldRegion fold = ((EditorEx)editor).getGutterComponentEx().findFoldingAnchorAt(mouseEvent.getX(), mouseEvent.getY()); - if (fold == null) return; + if (fold == null || !fold.isValid()) return; if (fold == myCurrentFold && myCurrentHint != null) { hint = myCurrentHint; return; @@ -231,7 +230,8 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec public void projectClosed() { } - + + @Nullable public FoldRegion findFoldRegion(@NotNull Editor editor, int startOffset, int endOffset) { return FoldingUtil.findFoldRegion(editor, startOffset, endOffset); } From 2bb70b80a978c19264ff310fef3de228fdb79bb0 Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 17:52:42 +0400 Subject: [PATCH 24/32] EA-32257 - assert: CaretModelImpl.moveToOffset Debug info is added --- .../com/intellij/diagnostic/LogMessageEx.java | 28 +++++++++++++ .../openapi/editor/impl/CaretModelImpl.java | 39 +++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java index b0ef4ea01c4a..9eb4a2184d79 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java @@ -1,8 +1,25 @@ +/* + * Copyright 2000-2011 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.diagnostic; import com.intellij.diagnostic.errordialog.Attachment; import com.intellij.openapi.diagnostic.IdeaLoggingEvent; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.util.SmartList; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.PrintStream; @@ -112,6 +129,17 @@ public class LogMessageEx extends LogMessage { }; } + public static void error(@NotNull Logger logger, @NotNull String message, @NotNull String... details) { + StringBuilder detailsBuffer = new StringBuilder(); + for (String detail : details) { + detailsBuffer.append(detail).append(","); + } + if (details.length > 0 && detailsBuffer.length() > 0) { + detailsBuffer.setLength(detailsBuffer.length() - 1); + } + logger.error(createEvent(message, detailsBuffer.toString(), null, null, (Attachment)null)); + } + /** * @param userMessage user-friendly message description (short, single line if possible) * @param details technical details (exception stack trace etc.) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java index b1276690d020..6560ad8b1cdd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java @@ -24,6 +24,7 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.diagnostic.LogMessageEx; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -69,6 +70,25 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, private RangeMarker savedBeforeBulkCaretMarker; private boolean ignoreWrongMoves = false; + /** + * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However, + * it's possible that the following situation occurs: + *

+ *

+   * 
    + *
  1. Some client subscribes to caret change events;
  2. + *
  3. {@link #moveToLogicalPosition(LogicalPosition)} is called;
  4. + *
  5. Caret position is changed during {@link #moveToLogicalPosition(LogicalPosition)} processing;
  6. + *
  7. The client receives caret position change event and adjusts the position;
  8. + *
  9. {@link #moveToLogicalPosition(LogicalPosition)} processing is finished;
  10. + *
  11. {@link #moveToLogicalPosition(LogicalPosition)} reports an error because the caret is not located at the target offset;
  12. + *
+ *
+ *

+ * This field serves as a flag that reports unexpected caret position change requests nested from {@link #moveToOffset(int, boolean)}. + */ + private boolean myReportCaretMoves; + /** * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve @@ -116,6 +136,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, public void moveToVisualPosition(@NotNull VisualPosition pos) { assertIsDispatchThread(); validateCallContext(); + if (myReportCaretMoves) { + LogMessageEx.error(LOG, "Unexpected caret move request"); + } myDesiredX = -1; int column = pos.column; int line = pos.line; @@ -218,6 +241,9 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, boolean scrollToCaret) { assertIsDispatchThread(); + if (myReportCaretMoves) { + LogMessageEx.error(LOG, "Unexpected caret move request"); + } SelectionModel selectionModel = myEditor.getSelectionModel(); int selectionStart = selectionModel.getLeadSelectionOffset(); LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection() @@ -366,6 +392,19 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, } private void moveToLogicalPosition(@NotNull LogicalPosition pos, boolean locateBeforeSoftWrap, @Nullable StringBuilder debugBuffer) { + if (myReportCaretMoves) { + LogMessageEx.error(LOG, "Unexpected caret move request"); + } + myReportCaretMoves = true; + try { + doMoveToLogicalPosition(pos, locateBeforeSoftWrap, debugBuffer); + } + finally { + myReportCaretMoves = false; + } + } + + private void doMoveToLogicalPosition(@NotNull LogicalPosition pos, boolean locateBeforeSoftWrap, @Nullable StringBuilder debugBuffer) { assertIsDispatchThread(); if (debugBuffer != null) { debugBuffer.append(String.format( From 3a59a32773bdf7b2c62083d927f71ea2df20ed8c Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 17:57:40 +0400 Subject: [PATCH 25/32] EA-32145 - IOOBE: EditorImpl.a --- .../com/intellij/openapi/editor/actions/EditorActionUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index 13cafcc0a946..403cd4370b65 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -170,7 +170,7 @@ public class EditorActionUtil { } } - editor.getCaretModel().moveToOffset(newCaretOffset); + editor.getCaretModel().moveToOffset(Math.min(document.getTextLength(), newCaretOffset)); } private static boolean shouldUseSmartTabs(Project project, Editor editor) { From 071ae0688deae07d59828baf074209c242c1435d Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 18:07:40 +0400 Subject: [PATCH 26/32] EA-32609 - assert: AbstractMappingStrategy.processFoldRegion --- .../mapping/AbstractMappingStrategy.java | 21 +++++++++++++------ .../LogicalToVisualMappingStrategy.java | 6 +++--- .../softwrap/mapping/MappingStrategy.java | 12 +++++------ .../OffsetToLogicalCalculationStrategy.java | 6 +++--- .../VisualToLogicalCalculationStrategy.java | 13 +++--------- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java index 2eef57fc2ef5..cb7fd4cf07d6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/AbstractMappingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -15,10 +15,13 @@ */ package com.intellij.openapi.editor.impl.softwrap.mapping; +import com.intellij.diagnostic.LogMessageEx; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.LogicalPosition; +import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.impl.EditorTextRepresentationHelper; import com.intellij.openapi.editor.impl.softwrap.SoftWrapsStorage; import org.jetbrains.annotations.NotNull; @@ -37,7 +40,9 @@ import java.util.List; * @param resulting document dimension type */ abstract class AbstractMappingStrategy implements MappingStrategy { - + + private static final Logger LOG = Logger.getInstance("#" + AbstractMappingStrategy.class.getName()); + protected static final CacheEntry SEARCH_KEY = new CacheEntry(0, null, null, null); protected final Editor myEditor; @@ -121,7 +126,7 @@ abstract class AbstractMappingStrategy implements MappingStrategy { } @Override - public T advance(EditorPosition position, int offset) { + public T advance(@NotNull EditorPosition position, int offset) { Document document = myEditor.getDocument(); if (offset >= myLastEntryOffset || offset >= document.getTextLength()) { return build(position); @@ -155,7 +160,7 @@ abstract class AbstractMappingStrategy implements MappingStrategy { protected abstract T buildIfExceeds(EditorPosition position, int offset); @Override - public T processFoldRegion(EditorPosition position, @NotNull FoldRegion foldRegion) { + public T processFoldRegion(@NotNull EditorPosition position, @NotNull FoldRegion foldRegion) { T result = buildIfExceeds(position, foldRegion); if (result != null) { return result; @@ -171,7 +176,11 @@ abstract class AbstractMappingStrategy implements MappingStrategy { collapsedSymbolsWidthInColumns = foldingData.getCollapsedSymbolsWidthInColumns(); } else { - assert false : String.format("Problem fold region: %s. Soft wraps cache: %s", foldRegion, myCache); + String details = ""; + if (myEditor instanceof EditorImpl) { + details = ((EditorImpl)myEditor).dumpState(); + } + LogMessageEx.error(LOG, "Unexpected fold region is found: " + foldRegion, details); } } else { @@ -195,7 +204,7 @@ abstract class AbstractMappingStrategy implements MappingStrategy { protected abstract T buildIfExceeds(@NotNull EditorPosition context, @NotNull FoldRegion foldRegion); @Override - public T processTabulation(EditorPosition position, TabData tabData) { + public T processTabulation(@NotNull EditorPosition position, TabData tabData) { T result = buildIfExceeds(position, tabData); if (result != null) { return result; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java index 0010d8a0f213..57f77e5f9fc9 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/LogicalToVisualMappingStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -158,7 +158,7 @@ class LogicalToVisualMappingStrategy extends AbstractMappingStrategy { * and given offset if any; null otherwise */ @Nullable - T advance(EditorPosition position, int offset); + T advance(@NotNull EditorPosition position, int offset); /** * Notifies current strategy that soft wrap is encountered during the processing. There are two ways to continue the processing then: @@ -74,7 +74,7 @@ interface MappingStrategy { * @return target document dimension if it's located within the bounds of the given soft wrap; null otherwise */ @Nullable - T processSoftWrap(EditorPosition position, SoftWrap softWrap); + T processSoftWrap(@NotNull EditorPosition position, SoftWrap softWrap); /** * Notifies current strategy that collapsed fold region is encountered during the processing. There are two ways to @@ -92,7 +92,7 @@ interface MappingStrategy { * null otherwise */ @Nullable - T processFoldRegion(EditorPosition position, @NotNull FoldRegion foldRegion); + T processFoldRegion(@NotNull EditorPosition position, @NotNull FoldRegion foldRegion); /** * Notifies current strategy that tabulation symbols is encountered during the processing. Tabulation symbols @@ -111,7 +111,7 @@ interface MappingStrategy { * null otherwise */ @Nullable - T processTabulation(EditorPosition position, TabData tabData); + T processTabulation(@NotNull EditorPosition position, TabData tabData); /** * This method is assumed to be called when there are no special symbols between the document position identified by the @@ -122,5 +122,5 @@ interface MappingStrategy { * @return resulting dimension that is built on the basis of the given position and target anchor dimension */ @NotNull - T build(EditorPosition position); + T build(@NotNull EditorPosition position); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java index 1b58428bfff2..7a72b05d1b3c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/OffsetToLogicalCalculationStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2011 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. @@ -195,7 +195,7 @@ class OffsetToLogicalCalculationStrategy extends AbstractMappingStrategy Date: Wed, 14 Dec 2011 18:11:03 +0400 Subject: [PATCH 27/32] EA-32126 - SOE: EditorImpl.moveCaretToScreenPos Debug info is added --- .../com/intellij/openapi/editor/impl/EditorImpl.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 98f8edf25419..3f3d808a88cf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.hint.EditorFragmentComponent; import com.intellij.codeInsight.hint.TooltipController; import com.intellij.codeInsight.hint.TooltipGroup; import com.intellij.concurrency.JobScheduler; +import com.intellij.diagnostic.LogMessageEx; import com.intellij.ide.*; import com.intellij.ide.dnd.DnDManager; import com.intellij.openapi.actionSystem.ActionManager; @@ -3233,10 +3234,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return logicalToVisualPosition(logicalPos, true); } - // TODO den remove before v.11 is released. + // TODO den remove as soon as the problem is fixed. private final ThreadLocal stackDepth = new ThreadLocal(); - // TODO den remove before v.11 is released. + // TODO den remove as soon as the problem is fixed. @Override @NotNull public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) { @@ -3257,7 +3258,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (offset < getDocument().getTextLength()) { offset = outermostCollapsed.getStartOffset(); LogicalPosition foldStart = offsetToLogicalPosition(offset); - // TODO den remove before v.11 is released. + // TODO den remove as soon as the problem is fixed. Integer depth = stackDepth.get(); if (depth >= 0) { stackDepth.set(depth + 1); @@ -3269,7 +3270,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi stackDepth.set(-1); } } - // TODO den unwrap before v.11 is released. + // TODO den remove as soon as the problem is fixed. try { return doLogicalToVisualPosition(foldStart, true); } @@ -3507,6 +3508,9 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (newY > 0 && newY == y) { newY = visibleLineToY(getVisibleLogicalLinesCount()); } + if (newY >= y) { + LogMessageEx.error(LOG, "cycled moveCaretToScreenPos() detected", String.format("x=%d, y=%d%nstate=%s", x, y, dumpState())); + } moveCaretToScreenPos(x, newY); return; } From 640f47d6cf5a9e73964135b4d609cda955cdf8fc Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Wed, 14 Dec 2011 18:33:48 +0400 Subject: [PATCH 28/32] EA-31980 - assert: AbstractMappingStrategy.processFoldRegion --- .../src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index 6070885e959e..84a4de25a325 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -665,6 +665,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myDataMapper.release(); myApplianceManager.reset(); myStorage.removeAll(); + myApplianceManager.recalculateIfNecessary(); try { task.run(true); } From f1004bb0b31019e59f5c998b9f82e529f240915b Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 14 Dec 2011 18:16:19 +0400 Subject: [PATCH 29/32] diagnostics --- .../openapi/editor/impl/IntervalTreeImpl.java | 15 +++++++++++++-- .../openapi/editor/impl/IterationState.java | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java index 1ed9f04a40b9..67b8ff194e43 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/IntervalTreeImpl.java @@ -68,7 +68,6 @@ public abstract class IntervalTreeImpl extends RedBla intervals = new SmartList>(createGetter(key)); } - @Override public IntervalNode getLeft() { return (IntervalNode)left; @@ -159,6 +158,12 @@ public abstract class IntervalTreeImpl extends RedBla public WeakReferencedGetter(T referent, ReferenceQueue q) { super(referent, q); } + + @NonNls + @Override + public String toString() { + return "Ref: " + get(); + } } protected int computeDeltaUpToRoot() { @@ -306,6 +311,12 @@ public abstract class IntervalTreeImpl extends RedBla t.modCount = (int)value; t.allDeltasUpAreNull = ((value >> 32) & 1) != 0; } + + @NonNls + @Override + public String toString() { + return "Node: " + intervals; + } } static class NodeCachedOffsets { @@ -575,7 +586,7 @@ public abstract class IntervalTreeImpl extends RedBla // next node in in-order traversal private IntervalNode nextNode(@NotNull IntervalNode root) { - assert root.isValid(); + assert root.isValid() : root; int delta = deltaUpToRootExclusive + root.delta; int myMaxEnd = maxEndOf(root, deltaUpToRootExclusive); if (startOffset > myMaxEnd) return null; // tree changed diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java index 44250317f389..0aa4b4666b5b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/IterationState.java @@ -541,6 +541,7 @@ public final class IterationState { } public void pushBack(T element) { + assert myPushedBack == null : "Pushed already: " + myPushedBack; myPushedBack = element; } } From ac8c5cf0ea9a24a0f2521cb1288825853a5ccd19 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 15 Dec 2011 11:30:24 +0400 Subject: [PATCH 30/32] EA-26313 - assert: EditorWindow.hostToInjected --- .../InjectedSelfElementInfo.java | 48 +++++++++++++------ .../injected/InjectedLanguageManagerImpl.java | 37 +++++++------- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java index 2fe466980254..1dfa279a8d69 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/smartPointers/InjectedSelfElementInfo.java @@ -28,6 +28,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; /** @@ -65,22 +66,39 @@ class InjectedSelfElementInfo extends SelfElementInfo { final Ref result = new Ref(); final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(getProject()); - InjectedLanguageUtil.enumerate(hostContext, hostContext.getContainingFile(), true, new PsiLanguageInjectionHost.InjectedPsiVisitor() { - @Override - public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { - if (result.get() != null) return; - TextRange hostRange = manager.injectedToHost(injectedPsi, new TextRange(0, injectedPsi.getTextLength())); - Document document = PsiDocumentManager.getInstance(getProject()).getDocument(injectedPsi); - if (hostRange.contains(rangeInHostFile) && document instanceof DocumentWindow) { - int start = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getStartOffset()); - int end = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getEndOffset()); - PsiElement element = findElementInside(injectedPsi, start, end, anchorClass, anchorLanguage); - result.set(element); - } - } - }); + PsiFile hostFile = hostContext.getContainingFile(); - return result.get(); + PsiLanguageInjectionHost.InjectedPsiVisitor visitor = new PsiLanguageInjectionHost.InjectedPsiVisitor() { + @Override + public void visit(@NotNull PsiFile injectedPsi, @NotNull List places) { + if (result.get() != null) return; + TextRange hostRange = manager.injectedToHost(injectedPsi, new TextRange(0, injectedPsi.getTextLength())); + Document document = PsiDocumentManager.getInstance(getProject()).getDocument(injectedPsi); + if (hostRange.contains(rangeInHostFile) && document instanceof DocumentWindow) { + int start = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getStartOffset()); + int end = ((DocumentWindow)document).hostToInjected(rangeInHostFile.getEndOffset()); + PsiElement element = findElementInside(injectedPsi, start, end, anchorClass, anchorLanguage); + result.set(element); + } + } + }; + + PsiDocumentManager documentManager = PsiDocumentManager.getInstance(hostFile.getProject()); + Document document = documentManager.getDocument(hostFile); + if (document != null && documentManager.isUncommited(document)) { + List documents = InjectedLanguageUtil.getCachedInjectedDocuments(hostFile); + for (DocumentWindow documentWindow : documents) { + PsiFile injected = documentManager.getPsiFile(documentWindow); + if (injected != null) { + visitor.visit(injected, Collections.emptyList()); + } + } + } + else { + InjectedLanguageUtil.enumerate(hostContext, hostFile, true, visitor); + } + + return result.get(); } @Override diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java index ccfac053b4d9..b99e9eef400c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java @@ -40,7 +40,9 @@ import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.ProperTextRange; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.PsiDocumentManagerImpl; @@ -117,15 +119,16 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme public void dispose() { } - public boolean startRunInjectors(@NotNull Document hostDocument, final boolean synchronously) { - if (myProject.isDisposed()) return true; + public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) { + if (myProject.isDisposed()) return; assert synchronously || !ApplicationManager.getApplication().isWriteAccessAllowed(); // use cached to avoid recreate PSI in alien project - final PsiFile hostPsiFile = PsiDocumentManager.getInstance(myProject).getCachedPsiFile(hostDocument); - if (hostPsiFile == null) return true; + final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); + final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument); + if (hostPsiFile == null) return; final List injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile); - if (injected.isEmpty()) return true; + if (injected.isEmpty()) return; if (myProgress.isCanceled()) { myProgress = new DaemonProgressIndicator(); @@ -135,6 +138,8 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme @Override public boolean process(DocumentWindow documentWindow) { ProgressManager.checkCanceled(); + if (documentManager.isUncommited(hostDocument)) return false; // will be committed later + RangeMarker rangeMarker = documentWindow.getHostRanges()[0]; PsiElement element = rangeMarker.isValid() ? hostPsiFile.findElementAt(rangeMarker.getStartOffset()) : null; if (element == null) { @@ -161,36 +166,30 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager impleme return true; } }; - final Computable commitRunnable = new Computable() { + final Runnable commitInjectionsRunnable = new Runnable() { @Override - public Boolean compute() { - return JobUtil.invokeConcurrentlyUnderProgress(new ArrayList(injected), myProgress, !synchronously, commitProcessor); + public void run() { + JobUtil.invokeConcurrentlyUnderProgress(new ArrayList(injected), myProgress, !synchronously, commitProcessor); } }; if (synchronously) { if (Thread.holdsLock(PsiLock.LOCK)) { - // hack for the case when docCommit was called from within PSI modification, e.g. in formatter + // hack for the case when docCommit was called from within PSI modification, e.g. in formatter. // we can't spawn threads to do injections there or deadlock is imminent - return ContainerUtil.process(injected, commitProcessor); + ContainerUtil.process(injected, commitProcessor); } else { - return commitRunnable.compute(); + commitInjectionsRunnable.run(); } } else { JobUtil.submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() { @Override public void run() { - ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() { - @Override - public void run() { - commitRunnable.compute(); - } - }); + ApplicationManagerEx.getApplicationEx().tryRunReadAction(commitInjectionsRunnable); } }); - return true; } } From d3ab91ec7daf5cad0fddb1a48b5a9012211e4360 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 15 Dec 2011 11:31:11 +0400 Subject: [PATCH 31/32] EA-29780 - assert: RangeMarkerImpl.documentChanged --- .../com/intellij/openapi/editor/impl/RangeMarkerImpl.java | 8 ++------ .../com/intellij/openapi/editor/impl/RangeMarkerTree.java | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java index a160814198eb..72180cd2ec84 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerImpl.java @@ -19,7 +19,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.RangeMarkerEx; -import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.util.Processor; import org.jetbrains.annotations.NonNls; @@ -60,6 +59,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx } protected boolean unregisterInTree() { + if (!isValid()) return false; IntervalTreeImpl tree = myNode.getTree(); tree.checkMax(true); boolean b = myDocument.removeRangeMarker(this); @@ -74,9 +74,7 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx @Override public void dispose() { - if(isValid()) { - unregisterInTree(); - } + unregisterInTree(); } @Override @@ -258,8 +256,6 @@ public class RangeMarkerImpl extends UserDataHolderBase implements RangeMarkerEx return node != null && node.isValid(); } - private static final Key TRACK_INVALIDATION_KEY = new Key("TRACK_INVALIDATION_KEY"); - @Override public boolean setValid(boolean value) { RangeMarkerTree.RMNode node = myNode; diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java index 9f951c14f468..eb979312e590 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/RangeMarkerTree.java @@ -218,6 +218,7 @@ public class RangeMarkerTree extends IntervalTreeImpl Date: Thu, 15 Dec 2011 11:35:08 +0400 Subject: [PATCH 32/32] EA-30140 - IOOBE: SegmentArray.findSegmentIndex --- .../codeInsight/daemon/impl/ShowIntentionsPass.java | 12 ++++++------ .../com/intellij/openapi/editor/impl/EditorImpl.java | 4 ++-- .../openapi/editor/impl/EditorMarkupModelImpl.java | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java index 11b628f781cd..5bcb9bd50dd5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ShowIntentionsPass.java @@ -218,18 +218,18 @@ public class ShowIntentionsPass extends TextEditorHighlightingPass { List actions = QuickFixAction.getAvailableActions(hostEditor, hostFile, passIdToShowIntentionsFor); final DaemonCodeAnalyzer codeAnalyzer = DaemonCodeAnalyzer.getInstance(project); - final Document document = hostEditor.getDocument(); - HighlightInfo infoAtCursor = ((DaemonCodeAnalyzerImpl)codeAnalyzer).findHighlightByOffset(document, offset, true); + final Document hostDocument = hostEditor.getDocument(); + HighlightInfo infoAtCursor = ((DaemonCodeAnalyzerImpl)codeAnalyzer).findHighlightByOffset(hostDocument, offset, true); if (infoAtCursor == null || infoAtCursor.getSeverity() == HighlightSeverity.ERROR) { intentions.errorFixesToShow.addAll(actions); } else { intentions.inspectionFixesToShow.addAll(actions); } - final int line = document.getLineNumber(offset); - DaemonCodeAnalyzerImpl.processHighlights(document, project, null, - document.getLineStartOffset(line), - document.getLineEndOffset(line), new Processor() { + final int line = hostDocument.getLineNumber(offset); + DaemonCodeAnalyzerImpl.processHighlights(hostDocument, project, null, + hostDocument.getLineStartOffset(line), + hostDocument.getLineEndOffset(line), new Processor() { @Override public boolean process(HighlightInfo info) { final GutterIconRenderer renderer = info.getGutterIconRenderer(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 3f3d808a88cf..2f83e2241f10 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -321,8 +321,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public void attributesChanged(@NotNull RangeHighlighterEx highlighter) { int textLength = myDocument.getTextLength(); - int start = Math.min(Math.max(highlighter.getAffectedAreaStartOffset(), 0), textLength - 1); - int end = Math.min(Math.max(highlighter.getAffectedAreaEndOffset(), 0), textLength - 1); + int start = Math.min(Math.max(highlighter.getAffectedAreaStartOffset(), 0), textLength); + int end = Math.min(Math.max(highlighter.getAffectedAreaEndOffset(), 0), textLength); int startLine = start == -1 ? 0 : myDocument.getLineNumber(start); int endLine = end == -1 ? myDocument.getLineCount() : myDocument.getLineNumber(end); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java index af3064934e2d..698ddff7dabd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java @@ -854,14 +854,14 @@ public class EditorMarkupModelImpl extends MarkupModelImpl implements EditorMark } int endY; + int endLineNumber = offsetToLine(end, document); if (end == -1 || start == -1) { endY = Math.min(myEditorSourceHeight, myEditorTargetHeight); } - else if (start == end || document.getLineNumber(start) == document.getLineNumber(end)) { + else if (start == end || offsetToLine(start,document) == endLineNumber) { endY = startY; // both offsets are on the same line, no need to recalc Y position } else { - int endLineNumber = offsetToLine(end, document); if (myEditorSourceHeight < myEditorTargetHeight) { endY = myEditorScrollbarTop + endLineNumber * myEditor.getLineHeight(); }