Merge branch 'master' of git.labs.intellij.net:idea/community
authorYann Cébron <yann@yc.local>
Tue, 17 Aug 2010 15:54:30 +0000 (17:54 +0200)
committerYann Cébron <yann@yc.local>
Tue, 17 Aug 2010 15:54:30 +0000 (17:54 +0200)
65 files changed:
java/java-impl/src/com/intellij/lang/java/JavaRefactoringSupportProvider.java
java/jsp-base-openapi/src/com/intellij/psi/jsp/BaseJspFile.java
platform/lang-api/src/com/intellij/lang/LanguageRefactoringSupport.java
platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java [deleted file]
platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
platform/lang-api/src/com/intellij/usageView/BaseUsageViewDescriptor.java [new file with mode: 0644]
platform/lang-api/src/com/intellij/usageView/UsageViewDescriptor.java
platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonListeners.java
platform/lang-impl/src/com/intellij/codeInsight/template/TemplateManager.java
platform/lang-impl/src/com/intellij/codeInsight/template/actions/SaveAsTemplateAction.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/EditTemplateDialog.java
platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateListPanel.java
platform/lang-impl/src/com/intellij/formatting/templateLanguages/DataLanguageBlockWrapper.java
platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java
platform/platform-api/src/com/intellij/openapi/ui/ComponentWithBrowseButton.java
platform/platform-api/src/com/intellij/openapi/ui/TreeComboBox.java
platform/platform-api/src/com/intellij/ui/HyperlinkAdapter.java [new file with mode: 0644]
platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacro.java
platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java
platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretModelImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/SelectionModelImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManager.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapApplianceManager.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapsStorage.java
platform/platform-impl/src/com/intellij/openapi/project/ex/ProjectEx.java
platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java
platform/platform-impl/src/com/intellij/util/ui/ChangesTrackingTableView.java
platform/platform-impl/src/com/intellij/util/ui/ValidatingTableEditor.java
platform/platform-impl/testSrc/com/intellij/openapi/editor/impl/softwrap/DefaultSoftWrapApplianceManagerTest.java
platform/platform-resources/src/idea/PlatformActions.xml
platform/util/src/com/intellij/util/ArrayUtil.java
platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequest.java
platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/IncomingChangesIndicator.java
platform/vcs-impl/src/com/intellij/openapi/vcs/readOnlyHandler/VcsHandleTypeFactory.java
platform/vcs-impl/src/com/intellij/platform/PlatformVcsDetector.java
plugins/ant/src/com/intellij/lang/ant/config/impl/AntBuildModelImpl.java
plugins/ant/src/com/intellij/lang/ant/dom/AntDomAntCall.java
plugins/ant/src/com/intellij/lang/ant/dom/AntDomDefaultTargetConverter.java
plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java
plugins/ant/src/com/intellij/lang/ant/dom/AntDomTargetDependsListConverter.java
plugins/ant/src/com/intellij/lang/ant/dom/AntDomTargetReference.java [new file with mode: 0644]
plugins/ant/src/com/intellij/lang/ant/dom/PropertyProviderFinder.java
plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java
plugins/properties/src/com/intellij/lang/properties/PropertiesRefactoringSupportProvider.java
plugins/relaxng/src/org/intellij/plugins/relaxNG/compact/psi/impl/RncFileImpl.java
plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathLanguage.java
plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/psi/impl/XsltLanguage.java
plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XsltRefactoringSupportProvider.java [new file with mode: 0644]
plugins/xpath/xpath-lang/test/org/intellij/lang/xpath/TestBase.java
plugins/xpath/xpath.iml
resources/src/idea/IdeaActions.xml
xml/impl/src/com/intellij/psi/formatter/xml/SyntheticBlock.java
xml/impl/src/com/intellij/psi/impl/source/xml/XmlFileImpl.java
xml/impl/src/com/intellij/xml/util/XmlApplicationComponent.java
xml/impl/src/com/intellij/xml/util/XmlResourceResolver.java
xml/impl/src/com/intellij/xml/util/XmlUtil.java
xml/openapi/src/com/intellij/psi/xml/XmlFile.java

index aa153df182abbe61349b06e381f5a9ffed72e506..c6b29ae7a98f59f9de9220afcabfff5171c6608c 100644 (file)
@@ -15,7 +15,7 @@
  */
 package com.intellij.lang.java;
 
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.psi.*;
 import com.intellij.psi.javadoc.PsiDocComment;
 import com.intellij.psi.search.LocalSearchScope;
@@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable;
 /**
  * @author ven
  */
-public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportProvider {
+public class JavaRefactoringSupportProvider extends RefactoringSupportProvider {
   public boolean isSafeDeleteAvailable(PsiElement element) {
     return element instanceof PsiClass || element instanceof PsiMethod || element instanceof PsiField ||
            (element instanceof PsiParameter && ((PsiParameter)element).getDeclarationScope() instanceof PsiMethod) ||
@@ -53,7 +53,7 @@ public class JavaRefactoringSupportProvider extends DefaultRefactoringSupportPro
     return new IntroduceFieldHandler();
   }
 
-  public boolean doInplaceRenameFor(final PsiElement element, final PsiElement context) {
+  public boolean isInplaceRenameAvailable(final PsiElement element, final PsiElement context) {
     return mayRenameInplace(element, context);
   }
 
index 4b39c8b346d93c556f718b93699d41040141ed56..f34cba04c224f4f9f4e93a0faa2468bbd0f3e25a 100644 (file)
@@ -33,6 +33,7 @@ public interface BaseJspFile extends XmlFile {
 
   XmlTag[] getDirectiveTags(JspDirectiveKind directiveKind, final boolean searchInIncludes);
   XmlTag createDirective(XmlTag context, JspDirectiveKind directiveKind);
+  XmlTag createDirective(JspDirectiveKind directiveKind);
 
   /**
    * Method with a bad name. Returns file corresponding to getTemplateDataLanguage() method of ViewProvider
@@ -47,4 +48,6 @@ public interface BaseJspFile extends XmlFile {
 
   @NotNull
   JspxFileViewProvider getViewProvider();
+
+  XmlTag getRootTag();
 }
index 3e4538e41c6f83da725a26f1f41b9375aaeb8b4f..0fc5351defc5ac1fd0f42cb037d19a626062fb51 100644 (file)
  */
 package com.intellij.lang;
 
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
 import com.intellij.lang.refactoring.RefactoringSupportProvider;
 
 public class LanguageRefactoringSupport extends LanguageExtension<RefactoringSupportProvider> {
   public static final LanguageRefactoringSupport INSTANCE = new LanguageRefactoringSupport();
 
   private LanguageRefactoringSupport() {
-    super("com.intellij.lang.refactoringSupport", new DefaultRefactoringSupportProvider());
+    super("com.intellij.lang.refactoringSupport", new RefactoringSupportProvider() {});
   }
 }
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/DefaultRefactoringSupportProvider.java
deleted file mode 100644 (file)
index 5a4cb9c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2000-2009 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.lang.refactoring;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.refactoring.RefactoringActionHandler;
-import com.intellij.refactoring.changeSignature.ChangeSignatureHandler;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Default implementation of <code>RefactoringSupportProvider</code> to inherit from
- */
-public class DefaultRefactoringSupportProvider implements RefactoringSupportProvider {
-  public boolean isSafeDeleteAvailable(PsiElement element) {
-    return false;
-  }
-
-  @Nullable
-  public RefactoringActionHandler getIntroduceVariableHandler() {
-    return null;
-  }
-
-  @Nullable
-  public RefactoringActionHandler getExtractMethodHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getIntroduceConstantHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getIntroduceFieldHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getIntroduceParameterHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getPullUpHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getPushDownHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getExtractInterfaceHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getExtractModuleHandler() {
-    return null;
-  }
-
-  public RefactoringActionHandler getExtractSuperClassHandler() {
-    return null;
-  }
-
-  public boolean doInplaceRenameFor(final PsiElement element, final PsiElement context) {
-    return false;
-  }
-
-  public ChangeSignatureHandler getChangeSignatureHandler() {
-    return null;
-  }
-}
index ac244743397b5ebf1de5a1e0ed0a3d6423e979d3..ff70ad408a82fb1d834bebfc72347c0cf5276a1a 100644 (file)
@@ -26,8 +26,7 @@ import org.jetbrains.annotations.Nullable;
  *
  * @author ven
  */
-
-public interface RefactoringSupportProvider {
+public abstract class RefactoringSupportProvider {
   /**
    * Checks if the Safe Delete refactoring can be applied to the specified element
    * in the language. The Safe Delete refactoring also requires the plugin to implement
@@ -36,73 +35,84 @@ public interface RefactoringSupportProvider {
    * @param element the element for which Safe Delete was invoked
    * @return true if Safe Delete is available, false otherwise.
    */
-  boolean isSafeDeleteAvailable(PsiElement element);
+  public boolean isSafeDeleteAvailable(PsiElement element) { return false; }
 
   /**
    * @return handler for introducing local variables in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getIntroduceVariableHandler();
+  @Nullable
+  public RefactoringActionHandler getIntroduceVariableHandler() { return null; }
 
   /**
    * @return handler for extracting methods in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getExtractMethodHandler();
+  @Nullable
+  public RefactoringActionHandler getExtractMethodHandler() { return null; }
 
   /**
    * @return handler for introducing constants in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getIntroduceConstantHandler();
+  @Nullable
+  public RefactoringActionHandler getIntroduceConstantHandler() { return null; }
 
   /**
    * @return handler for introducing fields in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getIntroduceFieldHandler();
+  @Nullable
+  public RefactoringActionHandler getIntroduceFieldHandler() { return null; }
 
   /**
    * @return  handler for introducing parameters in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getIntroduceParameterHandler();
+  @Nullable
+  public RefactoringActionHandler getIntroduceParameterHandler() { return null; }
 
   /**
    * @return  handler for pulling up members in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getPullUpHandler();
+  @Nullable
+  public RefactoringActionHandler getPullUpHandler() { return null; }
 
   /**
    * @return  handler for pushing down members in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getPushDownHandler();
+  @Nullable
+  public RefactoringActionHandler getPushDownHandler() { return null; }
 
   /**
    * @return  handler for extracting members to an interface in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getExtractInterfaceHandler();
+  @Nullable
+  public RefactoringActionHandler getExtractInterfaceHandler() { return null; }
 
   /**
    * @return  handler for extracting members to some module in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getExtractModuleHandler();
+  @Nullable
+  public RefactoringActionHandler getExtractModuleHandler() { return null; }
 
   /**
    * @return  handler for extracting super class in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable RefactoringActionHandler getExtractSuperClassHandler();
+  @Nullable
+  public RefactoringActionHandler getExtractSuperClassHandler() { return null; }
 
   /**
    * @return  handler for changing signature in this language
    * @see com.intellij.refactoring.RefactoringActionHandler
    */
-  @Nullable ChangeSignatureHandler getChangeSignatureHandler();
+  @Nullable
+  public ChangeSignatureHandler getChangeSignatureHandler() { return null; }
 
-  boolean doInplaceRenameFor(PsiElement element, PsiElement context);
+  public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) { return false; }
 }
diff --git a/platform/lang-api/src/com/intellij/usageView/BaseUsageViewDescriptor.java b/platform/lang-api/src/com/intellij/usageView/BaseUsageViewDescriptor.java
new file mode 100644 (file)
index 0000000..f1296dd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2010 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.usageView;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.RefactoringBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class BaseUsageViewDescriptor implements UsageViewDescriptor {
+
+  private PsiElement[] myElements;
+
+  public BaseUsageViewDescriptor(PsiElement... elements) {
+    myElements = elements;
+  }
+
+  @NotNull
+  @Override
+  public PsiElement[] getElements() {
+    return myElements;
+  }
+
+  @Override
+  public String getProcessedElementsHeader() {
+    return "Element(s) to be refactored:";
+  }
+
+  @Override
+  public String getCodeReferencesText(int usagesCount, int filesCount) {
+    return RefactoringBundle.message("references.to.be.changed", UsageViewBundle.getReferencesString(usagesCount, filesCount));
+  }
+
+  @Nullable
+  @Override
+  public String getCommentReferencesText(int usagesCount, int filesCount) {
+    return null;
+  }
+}
index f74737e34bb3283e77f49a94fc572aaacbbd7172..6800e0eb8562823094ee595871ce6d7da79004c7 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.usageView;
 
 import com.intellij.psi.PsiElement;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 public interface UsageViewDescriptor {
   /**
@@ -29,5 +30,6 @@ public interface UsageViewDescriptor {
 
   String getCodeReferencesText(int usagesCount, int filesCount);
 
+  @Nullable
   String getCommentReferencesText(int usagesCount, int filesCount);
 }
\ No newline at end of file
index b3561b6bd82c6e4147c49b555d61c70acea32d93..d968fa3c55c769535f984805415fda1e5d0d6085 100644 (file)
@@ -450,10 +450,16 @@ public class DaemonListeners implements Disposable {
 
       boolean shown = false;
       try {
-        LogicalPosition pos = editor.xyToLogicalPosition(e.getMouseEvent().getPoint());
+        // There is a possible case that cursor is located at soft wrap-introduced virtual space (that is mapped to offset
+        // of the document symbol just after soft wrap). We don't want to show any tooltips for it then.
+        VisualPosition visual = editor.xyToVisualPosition(e.getMouseEvent().getPoint());
+        if (editor.getSoftWrapModel().isInsideSoftWrap(visual)) {
+          return;
+        }
+        LogicalPosition logical = editor.visualToLogicalPosition(visual);
         if (e.getArea() == EditorMouseEventArea.EDITING_AREA) {
-          int offset = editor.logicalPositionToOffset(pos);
-          if (editor.offsetToLogicalPosition(offset).column != pos.column) return; // we are in virtual space
+          int offset = editor.logicalPositionToOffset(logical);
+          if (editor.offsetToLogicalPosition(offset).column != logical.column) return; // we are in virtual space
           HighlightInfo info = myDaemonCodeAnalyzer.findHighlightByOffset(editor.getDocument(), offset, false);
           if (info == null || info.description == null) return;
           DaemonTooltipUtil.showInfoTooltip(info, editor, offset);
index 8caeba8c6095c22c9412d377071ff8984fdb7b1f..7a73098179c401cbf2d499bbdf5604966e0f55fd 100644 (file)
@@ -41,7 +41,7 @@ public abstract class TemplateManager {
                                      @NotNull final Template template,
                                      boolean inSeparateCommand,
                                      Map<String, String> predefinedVarValues,
-                                     TemplateEditingListener listener);
+                                     @Nullable TemplateEditingListener listener);
 
   public abstract void startTemplate(@NotNull Editor editor,
                                      @NotNull Template template,
index ffccbbb8c73024a2733e842b7460dc69b1f257d2..ed9c81274c3bc86060a67bb4105f4472e8e0b16c 100644 (file)
@@ -46,12 +46,11 @@ import com.intellij.psi.*;
 import com.intellij.psi.util.PsiElementFilter;
 import com.intellij.psi.util.PsiTreeUtil;
 import com.intellij.util.containers.HashMap;
-import org.jetbrains.annotations.NonNls;
 
+import javax.swing.*;
 import java.util.Map;
 
 public class SaveAsTemplateAction extends AnAction {
-  public static final @NonNls String JAVA_LANG_PACKAGE_PREFIX = "java.lang";
 
   public void actionPerformed(AnActionEvent e) {
     DataContext dataContext = e.getDataContext();
@@ -120,6 +119,13 @@ public class SaveAsTemplateAction extends AnAction {
       template.getTemplateContext().setEnabled(contextType, contextType.isInContext(fileType));
     }
 
+    if (editTemplate(template, editor.getComponent(), true)) return;
+    templateSettings.addTemplate(template);
+  }
+
+  public static boolean editTemplate(TemplateImpl template, JComponent component, final boolean newTemplate) {
+
+    TemplateSettings templateSettings = TemplateSettings.getInstance();
     String defaultShortcut = "";
     if (templateSettings.getDefaultShortcutChar() == TemplateSettings.ENTER_CHAR) {
       defaultShortcut = CodeInsightBundle.message("template.shortcut.enter");
@@ -135,20 +141,20 @@ public class SaveAsTemplateAction extends AnAction {
     Map<TemplateContextType, Boolean> context = template.createContext();
 
     EditTemplateDialog dialog = new EditTemplateDialog(
-      editor.getComponent(),
+      component,
       CodeInsightBundle.message("dialog.edit.live.template.title"),
       template,
       templateSettings.getTemplateGroups(),
-      defaultShortcut, options, context);
+      defaultShortcut, options, context, newTemplate);
     dialog.show();
     if (!dialog.isOK()) {
-      return;
+      return true;
     }
     dialog.apply();
     template.applyOptions(options);
     template.applyContext(context);
-    templateSettings.addTemplate(template);
     templateSettings.setLastSelectedTemplateKey(template.getKey());
+    return false;
   }
 
   public void update(AnActionEvent e) {
index 34a2449309d462175c673ed62ecd4685e064d588..229b5e0f33dcc0dc636ddfb0a8724830514e3d1a 100644 (file)
@@ -33,6 +33,7 @@ import com.intellij.openapi.ui.ComboBox;
 import com.intellij.openapi.ui.DialogWrapper;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.ui.IdeBorderFactory;
+import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
 import javax.swing.event.ChangeEvent;
@@ -67,12 +68,16 @@ public class EditTemplateDialog extends DialogWrapper {
   private static final String ENTER = CodeInsightBundle.message("template.shortcut.enter");
   private final Map<TemplateOptionalProcessor, Boolean> myOptions;
   private final Map<TemplateContextType, Boolean> myContext;
+  private final boolean myNewTemplate;
 
   public EditTemplateDialog(Component parent, String title, TemplateImpl template, List<TemplateGroup> groups, String defaultShortcut,
-                            Map<TemplateOptionalProcessor, Boolean> options, Map<TemplateContextType, Boolean> context) {
+                            Map<TemplateOptionalProcessor, Boolean> options,
+                            Map<TemplateContextType, Boolean> context,
+                            boolean newTemplate) {
     super(parent, true);
     myOptions = options;
     myContext = context;
+    myNewTemplate = newTemplate;
     setOKButtonText(CommonBundle.getOkButtonText());
     setTitle(title);
 
@@ -137,13 +142,17 @@ public class EditTemplateDialog extends DialogWrapper {
     myEditVariablesButton.setMaximumSize(myEditVariablesButton.getPreferredSize());
     panel.add(myEditVariablesButton, gbConstraints);
 
-    gbConstraints.weighty = 0;
-    gbConstraints.gridwidth = 1;
-    gbConstraints.gridy++;
-    panel.add(createTemplateOptionsPanel(), gbConstraints);
+    JPanel templateOptionsPanel = createTemplateOptionsPanel();
+    JPanel contextPanel = createContextPanel();
+    if (myNewTemplate) {
+      gbConstraints.weighty = 0;
+      gbConstraints.gridwidth = 1;
+      gbConstraints.gridy++;
+      panel.add(templateOptionsPanel, gbConstraints);
 
-    gbConstraints.gridx = 1;
-    panel.add(createContextPanel(), gbConstraints);
+      gbConstraints.gridx = 1;
+      panel.add(contextPanel, gbConstraints);
+    }
 
     myKeyField.getDocument().addDocumentListener(new com.intellij.ui.DocumentAdapter() {
       protected void textChanged(javax.swing.event.DocumentEvent e) {
@@ -170,7 +179,11 @@ public class EditTemplateDialog extends DialogWrapper {
     return panel;
   }
 
+  @Nullable
   protected JComponent createNorthPanel() {
+    if (!myNewTemplate) {
+      return null;
+    }
     JPanel panel = new JPanel(new GridBagLayout());
     GridBagConstraints gbConstraints = new GridBagConstraints();
     gbConstraints.insets = new Insets(4,4,4,4);
index e212476b5c043f3cd4a5eece0e5c4f57265509b4..e5781ea9ed0bcd64b8de3607553a9d11ff598094 100644 (file)
@@ -452,7 +452,7 @@ class TemplateListPanel extends JPanel {
     String oldGroupName = template.getGroupName();
 
     EditTemplateDialog dialog = new EditTemplateDialog(this, CodeInsightBundle.message("dialog.edit.live.template.title"), template, getTemplateGroups(),
-                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template));
+                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template), true);
     dialog.show();
     if (!dialog.isOK()) return;
 
@@ -536,7 +536,7 @@ class TemplateListPanel extends JPanel {
     myTemplateOptions.put(getKey(template), template.createOptions());
     myTemplateContext.put(getKey(template), template.createContext());
     EditTemplateDialog dialog = new EditTemplateDialog(this, CodeInsightBundle.message("dialog.add.live.template.title"), template, getTemplateGroups(),
-                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template));
+                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template), true);
     dialog.show();
     if (!dialog.isOK()) return;
     dialog.apply();
@@ -558,7 +558,7 @@ class TemplateListPanel extends JPanel {
     myTemplateOptions.put(getKey(template), getOptions(orTemplate));
     myTemplateContext.put(getKey(template), getContext(orTemplate));
     EditTemplateDialog dialog = new EditTemplateDialog(this, CodeInsightBundle.message("dialog.copy.live.template.title"), template, getTemplateGroups(),
-                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template));
+                                                       (String)myExpandByCombo.getSelectedItem(), getOptions(template), getContext(template), true);
     dialog.show();
     if (!dialog.isOK()) return;
 
index f43eabb0160148cd3328edd81162f6ba358d442f..108e089ab6cf8338cd9d634c001f54fb76c9a173 100644 (file)
@@ -122,7 +122,7 @@ public class DataLanguageBlockWrapper implements ASTBlock, BlockWithParent {
     tlBlock.setParent(this);
   }
 
-  Block getOriginal() {
+  public Block getOriginal() {
     return myOriginal;
   }
 
index cacf6cf002bbe08905868a977635969bbc0f4999..b3a7e5a63f20699c8174563ccf5807d153f5a8bd 100644 (file)
@@ -94,7 +94,7 @@ public abstract class BaseRefactoringProcessor {
    *
    * @param elements - refreshed elements that are returned by UsageViewDescriptor.getElements()
    */
-  protected abstract void refreshElements(PsiElement[] elements);
+  protected void refreshElements(PsiElement[] elements) {}
 
   /**
    * Is called inside atomic action.
index d6bcf26fc118b22fc18321c3959273fc7fe91895..3714808801a34bb8efab6a900d9f55a0159ed070 100644 (file)
@@ -57,7 +57,7 @@ public class VariableInplaceRenameHandler implements RenameHandler {
       supportProvider = element != null ? LanguageRefactoringSupport.INSTANCE.forLanguage(element.getLanguage()):null;
     return supportProvider != null &&
            editor.getSettings().isVariableInplaceRenameEnabled() &&
-           supportProvider.doInplaceRenameFor(element, nameSuggestionContext);
+           supportProvider.isInplaceRenameAvailable(element, nameSuggestionContext);
   }
 
   public final boolean isRenaming(final DataContext dataContext) {
index 9e7943e7a8d33e85c3b14e91b2ccc1dd3efbae51..cf50b004d23eaa7b045a6db6d894a5602a20bbad 100644 (file)
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.vfs.LocalFileSystem;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.UIBundle;
+import com.intellij.util.Consumer;
 import com.intellij.util.ui.update.LazyUiDisposable;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -204,10 +205,15 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
         fileChooserDescriptor.setDescription(myDescription);
       }
       VirtualFile initialFile = getInitialFile();
-      VirtualFile[] files = doChoose(fileChooserDescriptor, initialFile);
-      if (files != null && files.length != 0) {
-        onFileChoosen(files[0]);
-      }
+
+      FileChooser.chooseFilesWithSlideEffect(fileChooserDescriptor, myProject, initialFile, new Consumer<VirtualFile[]>() {
+        @Override
+        public void consume(VirtualFile[] virtualFiles) {
+          if (virtualFiles != null && virtualFiles.length > 0) {
+            onFileChoosen(virtualFiles[0]);
+          }
+        }
+      });
     }
 
     @Nullable
@@ -233,14 +239,6 @@ public class ComponentWithBrowseButton<Comp extends JComponent> extends JPanel i
       myAccessor.setText(myTextComponent.getChildComponent(), chosenFile.getPresentableUrl());
     }
 
-    private VirtualFile[] doChoose(FileChooserDescriptor fileChooserDescriptor, VirtualFile initialFile) {
-      if (myProject == null) {
-        return FileChooser.chooseFiles(myTextComponent, fileChooserDescriptor, initialFile);
-      }
-      else {
-        return FileChooser.chooseFiles(myProject, fileChooserDescriptor, initialFile);
-      }
-    }
   }
 
   public final void requestFocus() {
index 1339698cb73b4fabd2e2c840f5e451fba2cddcee..8e79587d20648de3746e8c40b274880069483a58 100644 (file)
@@ -24,7 +24,6 @@ import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import javax.swing.border.Border;
-import javax.swing.tree.DefaultTreeCellRenderer;
 import javax.swing.tree.TreeModel;
 import javax.swing.tree.TreePath;
 import java.awt.*;
@@ -36,14 +35,19 @@ import java.util.Enumeration;
  */
 public class TreeComboBox extends JComboBox {
   final static int INDENT = UIManager.getInt("Tree.leftChildIndent");
+  private TreeModel myTreeModel;
 
   public TreeComboBox(@NotNull final TreeModel model) {
-    setModel(new TreeModelWrapper(model));
+    myTreeModel = model;
+    setModel(new TreeModelWrapper(myTreeModel));
     setRenderer(new TreeListCellRenderer(this, model));
-    setSelectedIndex(0);
     if (SystemInfo.isMac) setMaximumRowCount(25);
   }
 
+  public TreeModel getTreeModel() {
+    return myTreeModel;
+  }
+
   private static class TreeListCellRenderer extends JLabel implements ListCellRenderer {
     private static final Border SELECTION_PAINTER = (Border)UIManager.get("MenuItem.selectedBackgroundPainter");
 
diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkAdapter.java b/platform/platform-api/src/com/intellij/ui/HyperlinkAdapter.java
new file mode 100644 (file)
index 0000000..2fecaa3
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2010 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.ui;
+
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public abstract class HyperlinkAdapter implements HyperlinkListener {
+  
+  @Override
+  public void hyperlinkUpdate(HyperlinkEvent e) {
+    if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+      hyperlinkActivated(e);
+    }
+  }
+
+  protected abstract void hyperlinkActivated(HyperlinkEvent e);
+}
index 7928e8d277f2d57f654d89076c0afbcc24425b81..403f14ac16f21a4db05effa77f24563bb79ec53e 100644 (file)
@@ -27,7 +27,6 @@ import org.jdom.Element;
 import org.jetbrains.annotations.NonNls;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
@@ -83,7 +82,13 @@ public class ActionMacro implements JDOMExternalizable {
       Element action = (Element)iterator.next();
       if (ELEMENT_TYPING.equals(action.getName())) {
         Pair<List<Integer>, List<Integer>> codes = parseKeyCodes(action.getAttributeValue(ATTRIBUTE_KEY_CODES));
-        myActions.add(new TypedDescriptor(action.getAttributeValue(ATTRIBUTE_TEXT), codes.getFirst(), codes.getSecond()));
+
+        String text = action.getText();
+        if (text == null || text.length() == 0) {
+          text = action.getAttributeValue(ATTRIBUTE_TEXT);
+        }
+
+        myActions.add(new TypedDescriptor(text, codes.getFirst(), codes.getSecond()));
       }
       else if (ELEMENT_ACTION.equals(action.getName())) {
         myActions.add(new IdActionDescriptor(action.getAttributeValue(ATTRIBUTE_ID)));
@@ -111,7 +116,7 @@ public class ActionMacro implements JDOMExternalizable {
         actionNode = new Element(ELEMENT_TYPING);
         TypedDescriptor typedDescriptor = (TypedDescriptor)action;
         final String t = typedDescriptor.getText();
-        actionNode.setAttribute(ATTRIBUTE_TEXT, JDOMUtil.escapeText(t));
+        actionNode.setText(t);
         actionNode.setAttribute(ATTRIBUTE_KEY_CODES, unparseKeyCodes(new Pair<List<Integer>, List<Integer>>(typedDescriptor.getKeyCodes(), typedDescriptor.getKeyModifiers())));
       }
       else if (action instanceof IdActionDescriptor) {
index 215f5632b3fd601553ab613dbf3b4e151b849392..10c0dfafc8f70505a548681e4d9c3269115c90ef 100644 (file)
@@ -402,7 +402,8 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
               @Override
               public void run() {
                 if (finalLine >= 0) {
-                  myRightSide.scrollToFirstDiff(finalLine);
+                  final int line = myLineBlocks.transform(myRightSide.getSide(), finalLine);
+                  myLeftSide.scrollToFirstDiff(line);
                 } else {
                   scrollCurrentToFirstDiff();
                 }
@@ -458,9 +459,16 @@ public class DiffPanelImpl implements DiffPanelEx, ContentChangeListener, TwoSid
         @Override
         public void run() {
           final int startLine = myDocument.getLineNumber(textRange.getStartOffset());
-          final int endLine = myDocument.getLineNumber(textRange.getEndOffset());
+          final int endFragmentOffset = textRange.getEndOffset();
+          final int endLine = myDocument.getLineNumber(endFragmentOffset);
           for (int i = startLine; i <= endLine; i++) {
-            String text = myDocument.getText().substring(myDocument.getLineStartOffset(i), myDocument.getLineEndOffset(i));
+            int lineEndOffset = myDocument.getLineEndOffset(i);
+            final int lineStartOffset = myDocument.getLineStartOffset(i);
+            if (lineEndOffset > endFragmentOffset && (endFragmentOffset == lineStartOffset)) {
+              lineEndOffset = endFragmentOffset;
+            }
+            if (lineStartOffset > lineEndOffset) continue;
+            String text = myDocument.getText().substring(lineStartOffset, lineEndOffset);
             myBuffer.add(new Pair<Integer, String>(i, text));
           }
         }
index 6d9cd2083c405c7c95a42c32bbf7ad06a8c49af7..34dc39f1b53118ee5779f31c28f33cf26d83486d 100644 (file)
@@ -29,6 +29,8 @@ import com.intellij.openapi.actionSystem.Presentation;
 import com.intellij.openapi.editor.*;
 import com.intellij.openapi.editor.actionSystem.EditorAction;
 import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.util.Pair;
 
 public class DuplicateAction extends EditorAction {
   public DuplicateAction() {
@@ -47,35 +49,39 @@ public class DuplicateAction extends EditorAction {
 
   private static void duplicateLineOrSelectedBlockAtCaret(Editor editor) {
     Document document = editor.getDocument();
+    CaretModel caretModel = editor.getCaretModel();
+    ScrollingModel scrollingModel = editor.getScrollingModel();
     if(editor.getSelectionModel().hasSelection()) {
       int start = editor.getSelectionModel().getSelectionStart();
       int end = editor.getSelectionModel().getSelectionEnd();
       String s = document.getCharsSequence().subSequence(start, end).toString();
       document.insertString(end, s);
-      editor.getCaretModel().moveToOffset(end+s.length());
-      editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+      caretModel.moveToOffset(end+s.length());
+      scrollingModel.scrollToCaret(ScrollType.RELATIVE);
       editor.getSelectionModel().removeSelection();
       editor.getSelectionModel().setSelection(end, end+s.length());
     }
     else {
-      VisualPosition caret = editor.getCaretModel().getVisualPosition();
-      LogicalPosition lineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line, 0));
-      LogicalPosition nextLineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line + 1, 0));
-      if (nextLineStart.line == lineStart.line) {
-        nextLineStart = new LogicalPosition(lineStart.line+1, 0);
-      }
+      Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLinesRange(editor);
+      int offset = caretModel.getOffset();
 
+      LogicalPosition lineStart = lines.first;
+      LogicalPosition nextLineStart = lines.second;
       int start = editor.logicalPositionToOffset(lineStart);
       int end = editor.logicalPositionToOffset(nextLineStart);
       String s = document.getCharsSequence().subSequence(start, end).toString();
       final int lineToCheck = nextLineStart.line - 1;
 
+      int newOffset = end + offset - start;
       if(lineToCheck == document.getLineCount () /*empty document*/ ||
          document.getLineSeparatorLength(lineToCheck) == 0) {
         s = "\n"+s;
+        newOffset++;
       }
       document.insertString(end, s);
-      editor.getCaretModel().moveCaretRelatively(0, 1, false, false, true);
+
+      caretModel.moveToOffset(newOffset);
+      scrollingModel.scrollToCaret(ScrollType.RELATIVE);
     }
   }
 
index cefdd7dac27b09ac7204bffa7dc5569b4227e1a1..5d45a2a573b4b434808aabf80128f1093047f0ed 100644 (file)
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.ex.EditorEx;
 import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry;
 import com.intellij.openapi.editor.impl.FontInfo;
 import com.intellij.openapi.editor.impl.IterationState;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import org.jetbrains.annotations.NotNull;
 
@@ -420,7 +421,7 @@ public class EditorUtil {
     int startToUse = start;
 
     // Skip all lines except the last.
-    for (int i = StringUtil.lastIndexOf(text, '\n', start, end); i >= 0; i = StringUtil.lastIndexOf(text, '\n', start, end)) {
+    for (int i = StringUtil.lastIndexOf(text, '\n', startToUse, end); i >= 0; i = StringUtil.lastIndexOf(text, '\n', startToUse, end)) {
       startToUse = i + 1;
     }
 
@@ -522,6 +523,29 @@ public class EditorUtil {
     }
     return result;
   }
+
+  /**
+   * Calculates the closest non-soft-wrapped logical positions for current caret position.
+   *
+   * @param editor    target editor to use
+   * @return          pair of non-soft-wrapped logical positions closest to the caret position of the given editor
+   */
+  public static Pair<LogicalPosition, LogicalPosition> calcCaretLinesRange(Editor editor) {
+    VisualPosition caret = editor.getCaretModel().getVisualPosition();
+    int visualLine = caret.line;
+
+    LogicalPosition lineStart = editor.visualToLogicalPosition(new VisualPosition(visualLine, 0));
+    while (lineStart.softWrapLinesOnCurrentLogicalLine > 0) {
+      lineStart = editor.visualToLogicalPosition(new VisualPosition(--visualLine, 0));
+    }
+
+    visualLine = caret.line + 1;
+    LogicalPosition nextLineStart = editor.visualToLogicalPosition(new VisualPosition(caret.line + 1, 0));
+    while (nextLineStart.line == lineStart.line) {
+      nextLineStart = editor.visualToLogicalPosition(new VisualPosition(++visualLine, 0));
+    }
+    return new Pair<LogicalPosition, LogicalPosition>(lineStart, nextLineStart);
+  }
 }
 
 
index 503ff6715dfd118f1bf142383e6a60616b5998d8..d6e0d4b1be3ca509eb6d5a08c0cf2af3305e79d1 100644 (file)
@@ -301,9 +301,16 @@ public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener {
     VerticalInfo oldInfo = myCaretInfo;
     LogicalPosition oldCaretPosition = myLogicalCaret;
 
-    setCurrentLogicalCaret(new LogicalPosition(
-      line, column, softWrapLinesBefore, softWrapLinesCurrent, softWrapColumns, pos.foldedLines, pos.foldingColumnDiff
-    ));
+    LogicalPosition logicalPositionToUse;
+    if (pos.visualPositionAware) {
+      logicalPositionToUse = new LogicalPosition(
+        line, column, softWrapLinesBefore, softWrapLinesCurrent, softWrapColumns, pos.foldedLines, pos.foldingColumnDiff
+      );
+    }
+    else {
+      logicalPositionToUse = new LogicalPosition(line, column);
+    }
+    setCurrentLogicalCaret(logicalPositionToUse);
 
     final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);
 
index 880ccebfe0c9a1d3331f5431cdb4602daf5c1f91..75271a01e5131fd8bdda114640a233f3da631e74 100644 (file)
@@ -1666,7 +1666,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
     while (!iterationState.atEnd() && !lIterator.atEnd()) {
       int hEnd = iterationState.getEndOffset();
       int lEnd = lIterator.getEnd();
-      getSoftWrapModel().registerSoftWrapIfNecessary(myDocument.getRawChars(), start, hEnd, position.x, fontType);
+      getSoftWrapModel().registerSoftWrapIfNecessary(text, start, hEnd, position.x, fontType);
 
       if (hEnd >= lEnd) {
         FoldRegion collapsedFolderAt = myFoldingModel.getCollapsedRegionAtOffset(start);
@@ -1726,7 +1726,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
     flushBackground(g, clip);
 
     if (lIterator.getLineNumber() >= lastLineIndex && position.y <= clip.y + clip.height) {
-      getSoftWrapModel().registerSoftWrapIfNecessary(myDocument.getRawChars(), start, myDocument.getTextLength(), position.x, fontType);
+      getSoftWrapModel().registerSoftWrapIfNecessary(text, start, myDocument.getTextLength(), position.x, fontType);
       paintAfterFileEndBackground(iterationState, g, position, clip, lineHeight, defaultBackground, caretRowPainted);
     }
 
index 56ac422beb0eb0c0b82ec6d8e6ed356a68416565..7c3ff3f102e003b7dc479a4a008e80a40ecae456 100644 (file)
@@ -40,9 +40,11 @@ import com.intellij.openapi.editor.event.SelectionEvent;
 import com.intellij.openapi.editor.event.SelectionListener;
 import com.intellij.openapi.editor.ex.DocumentEx;
 import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
 import com.intellij.openapi.editor.markup.TextAttributes;
 import com.intellij.openapi.ide.CopyPasteManager;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.containers.ContainerUtil;
@@ -448,9 +450,9 @@ public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentLi
       return;
     }
 
-    VisualPosition caret = myEditor.getCaretModel().getVisualPosition();
-    LogicalPosition lineStart = myEditor.visualToLogicalPosition(new VisualPosition(caret.line, 0));
-    LogicalPosition nextLineStart = myEditor.visualToLogicalPosition(new VisualPosition(caret.line + 1, 0));
+    Pair<LogicalPosition, LogicalPosition> lines = EditorUtil.calcCaretLinesRange(myEditor);
+    LogicalPosition lineStart = lines.first;
+    LogicalPosition nextLineStart = lines.second;
 
     int start = myEditor.logicalPositionToOffset(lineStart);
     int end = myEditor.logicalPositionToOffset(nextLineStart);
index 1c8967076f5ff145aa1f9863c015e37d1888989a..11e1c6c9a7113f16bd1531ed9fbd925d2a5ccdba 100644 (file)
@@ -172,7 +172,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
     return result;
   }
 
-  public void registerSoftWrapIfNecessary(@NotNull char[] chars, int start, int end, int x, int fontType) {
+  public void registerSoftWrapIfNecessary(@NotNull CharSequence text, int start, int end, int x, int fontType) {
     if (!isSoftWrappingEnabled()) {
       return;
     }
@@ -180,7 +180,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
 
     myActive++;
     try {
-      myApplianceManager.registerSoftWrapIfNecessary(chars, start, end, x, fontType);
+      myApplianceManager.registerSoftWrapIfNecessary(text, start, end, x, fontType);
     }
     finally {
       myActive--;
@@ -301,8 +301,8 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
       return false;
     }
 
-    // We consider visual positions that point after the last symbol before soft wrap and the first symbol after soft wrap to not
-    // belong to soft wrap-introduced virtual space.
+    // We consider visual position that points after the last symbol before soft wrap belong to soft wrap-introduced virtual space
+    // and visual position that points to the first document symbol after soft wrap not belong to soft wrap-introduced virtual space.
     VisualPosition visualAfterSoftWrap = myEditor.offsetToVisualPosition(offset);
     if (visualAfterSoftWrap.line == visual.line && visualAfterSoftWrap.column <= visual.column) {
       return false;
@@ -320,7 +320,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
     }
     int width = EditorUtil.textWidthInColumns(myEditor, myEditor.getDocument().getCharsSequence(), offset - 1, offset, columnOffset);
     int softWrapStartColumn = visualBeforeSoftWrap.column  + width;
-    return visual.line > visualBeforeSoftWrap.line || visual.column > softWrapStartColumn;
+    return visual.line > visualBeforeSoftWrap.line || visual.column >= softWrapStartColumn;
   }
 
   @Override
@@ -384,6 +384,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
 
   @Override
   public void beforeDocumentChange(DocumentEvent event) {
+    if (!isSoftWrappingEnabled()) {
+      return;
+    }
     for (DocumentListener listener : myDocumentListeners) {
       listener.beforeDocumentChange(event);
     }
@@ -391,6 +394,9 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, DocumentListener {
 
   @Override
   public void documentChanged(DocumentEvent event) {
+    if (!isSoftWrappingEnabled()) {
+      return;
+    }
     for (DocumentListener listener : myDocumentListeners) {
       listener.documentChanged(event);
     }
index af05cbbc9800e1f76000cc5b473b36a9b1e11d24..c54eff21b8e1d6ca6e5a8b49f7e13f08761b5285 100644 (file)
@@ -31,6 +31,7 @@ import gnu.trove.TIntArrayList;
 import gnu.trove.TIntHashSet;
 import org.jetbrains.annotations.NotNull;
 
+import java.awt.*;
 import java.nio.CharBuffer;
 
 /**
@@ -115,8 +116,16 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
     }
 
     private void dropData(int startLine, int endLine) {
+      Document document = myEditor.getDocument();
       for (int i = startLine; i <= endLine; i++) {
         myProcessedLogicalLines.remove(i);
+
+        // Calculate approximate soft wraps positions using plain font.
+        // Note: we don't update 'myProcessedLogicalLines' collection here, i.e. soft wraps will be recalculated precisely
+        // during standard editor repainting iteration.
+        if (i < document.getLineCount()) {
+          processLogicalLine(document.getCharsSequence(), i, Font.PLAIN, IndentType.NONE);
+        }
       }
     }
   };
@@ -141,10 +150,10 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
 
   @SuppressWarnings({"AssignmentToForLoopParameter"})
   @Override
-  public void registerSoftWrapIfNecessary(@NotNull char[] chars, int start, int end, int x, int fontType) {
+  public void registerSoftWrapIfNecessary(@NotNull CharSequence text, int start, int end, int x, int fontType) {
     dropDataIfNecessary();
 
-    if (start >= end) {
+    if (myVisibleAreaWidth <= 0 || start >= end) {
       return;
     }
 
@@ -157,7 +166,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
         if (!myEditor.isViewer() && !document.isWritable()) {
           indent = IndentType.TO_PREV_LINE_NON_WS_START;
         }
-        processLogicalLine(chars, i, fontType, indent);
+        processLogicalLine(text, i, fontType, indent);
         myProcessedLogicalLines.add(i);
       }
     }
@@ -179,11 +188,18 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
     myVisibleAreaWidth = currentVisibleAreaWidth;
   }
 
-  private void processLogicalLine(char[] text, int line, int fontType, IndentType indentType) {
+  private void processLogicalLine(CharSequence text, int line, int fontType, IndentType indentType) {
     Document document = myEditor.getDocument();
     int startOffset = document.getLineStartOffset(line);
     int endOffset = document.getLineEndOffset(line);
 
+    // There is a possible case that this method is called for the approximate soft wraps positions calculation. E.g. the
+    // user can insert a long string to the end of the document and we don't want to perform horizontal scrolling to its end.
+    // Hence, we approximately define soft wraps for the inserted text assuming that there precise calculation will be performed
+    // on regular editor repainting iteration. However, we need to drop all those temporary soft wraps registered for
+    // the same line before.
+    myStorage.removeInRange(startOffset, endOffset);
+
     if (indentType == IndentType.NONE) {
       TIntArrayList offsets = calculateSoftWrapOffsets(text, startOffset, endOffset, fontType, 0);
       registerSoftWraps(offsets, 0);
@@ -221,7 +237,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
   }
 
   @SuppressWarnings({"AssignmentToForLoopParameter"})
-  private TIntArrayList calculateSoftWrapOffsets(char[] text, int start, int end, int fontType, int reservedWidth) {
+  private TIntArrayList calculateSoftWrapOffsets(CharSequence text, int start, int end, int fontType, int reservedWidth) {
     TIntArrayList result = new TIntArrayList();
 
     // Find offsets where soft wraps should be applied for the logical line in case of no indent usage.
@@ -281,10 +297,10 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
    * @param max         max offset to use (inclusive)
    * @return            wrapping offset to use (given <code>'max'</code> value should be returned if no more suitable point is found)
    */
-  private static int calculateSoftWrapOffset(char[] text, int preferred, int min, int max) {
+  private static int calculateSoftWrapOffset(CharSequence text, int preferred, int min, int max) {
     // Try to find target offset that is not greater than preferred position.
     for (int i = preferred; i > min; i--) {
-      char c = text[i];
+      char c = text.charAt(i);
 
       if (WHITE_SPACES.contains(c)) {
         return i < preferred ? i + 1 : i;
@@ -292,7 +308,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
 
       // Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement
       // like 'foo(int... args)'. We don't want to wrap on the second or third dots then.
-      if (i > min + 1 && !isIdSymbol(c) && !isIdSymbol(text[i - 1])) {
+      if (i > min + 1 && !isIdSymbol(c) && !isIdSymbol(text.charAt(i - 1))) {
         continue;
       }
       if (SPECIAL_SYMBOLS_TO_WRAP_AFTER.contains(c)) {
@@ -307,20 +323,20 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
 
       // Don't wrap on a non-id symbol followed by non-id symbol, e.g. don't wrap between two pluses at i++.
       // Also don't wrap before non-id symbol preceded by a space - wrap on space instead;
-      if (!isIdSymbol(c) && (i < min + 2 || (isIdSymbol(text[i - 1]) && !WHITE_SPACES.contains(text[i - 1])))) {
+      if (!isIdSymbol(c) && (i < min + 2 || (isIdSymbol(text.charAt(i - 1)) && !WHITE_SPACES.contains(text.charAt(i - 1))))) {
         return i;
       }
     }
 
     // Try to find target offset that is greater than preferred position.
     for (int i = preferred + 1; i < max; i++) {
-      char c = text[i];
+      char c = text.charAt(i);
       if (WHITE_SPACES.contains(c)) {
         return i;
       }
       // Don't wrap on the non-id symbol preceded by another non-id symbol. E.g. consider that we have a statement
       // like 'foo(int... args)'. We don't want to wrap on the second or third dots then.
-      if (i < max - 1 && !isIdSymbol(c) && !isIdSymbol(text[i + 1]) && !isIdSymbol(text[i - 1])) {
+      if (i < max - 1 && !isIdSymbol(c) && !isIdSymbol(text.charAt(i + 1)) && !isIdSymbol(text.charAt(i - 1))) {
         continue;
       }
       if (SPECIAL_SYMBOLS_TO_WRAP_BEFORE.contains(c)) {
@@ -331,7 +347,7 @@ public class DefaultSoftWrapApplianceManager implements SoftWrapApplianceManager
       }
 
       // Don't wrap on a non-id symbol followed by non-id symbol, e.g. don't wrap between two pluses at i++;
-      if (!isIdSymbol(c) && (i >= max || isIdSymbol(text[i + 1]))) {
+      if (!isIdSymbol(c) && (i >= max - 1 || isIdSymbol(text.charAt(i + 1)))) {
         return i;
       }
     }
index 90d4db3503859b12871d94a466effbf6488e0d8f..ccbef464f82c8eef4576446546658f485135f4ee 100644 (file)
@@ -32,18 +32,18 @@ public interface SoftWrapApplianceManager {
    * Defines a callback that is invoked on request to draw target text fragment and that can register new soft wraps in order
    * to correctly represent it.
    * <p/>
-   * Target text fragment to represent belongs to the given char array and lays at <code>[start; end)</code> interval.
+   * Target text fragment to represent belongs to the given char sequence and lays at <code>[start; end)</code> interval.
    * <p/>
    * Please note that it's possible for soft wrap to occur inside <code>[start; end)</code> region - e.g. there is a possible
    * case that particular single token is too long and we want to split it.
    * <p/>
    * <b>Note:</b> it's assumed that this method is called only on editor repainting.
    *
-   * @param chars     target text holder
+   * @param text      target text holder
    * @param start     start offset of the token to process within the given char array (inclusive)
    * @param end       end offset of the token to process within the given char array (exclusive)
    * @param x         <code>'x'</code> coordinate within the given graphics buffer that will be used to start drawing the text
    * @param fontType  font type used for the target text fragment representation
    */
-  void registerSoftWrapIfNecessary(@NotNull char[] chars, int start, int end, int x, int fontType);
+  void registerSoftWrapIfNecessary(@NotNull CharSequence text, int start, int end, int x, int fontType);
 }
index e6bca4da9e718d21ea9e2ab95a4df1a62a51a1f9..fe8f785fc8bb595158276377b84f82c195f40225 100644 (file)
@@ -126,6 +126,36 @@ public class SoftWrapsStorage {
     return removed;
   }
 
+  /**
+   * Allows to remove all soft wraps registered at the current storage with offsets from <code>[start; end)</code> range if any.
+   *
+   * @param startOffset   start offset to use (inclusive)
+   * @param endOffset     end offset to use (exclusive)
+   */
+  public void removeInRange(int startOffset, int endOffset) {
+    int startIndex = getSoftWrapIndex(startOffset);
+    if (startIndex < 0) {
+      startIndex = -startIndex - 1;
+    }
+
+    if (startIndex >= myWraps.size()) {
+      return;
+    }
+
+    int endIndex = startIndex;
+    for (; endIndex < myWraps.size(); endIndex++) {
+      TextChangeImpl softWrap = myWraps.get(endIndex);
+      if (softWrap.getStart() >= endOffset) {
+        break;
+      }
+    }
+    
+    if (endIndex > startIndex) {
+      myWraps.subList(startIndex, endIndex).clear();
+      notifyListenersAboutRemoval();
+    }
+  }
+
   /**
    * Removes all soft wraps registered at the current storage.
    */
index 21bc05e604374f5e73366b1731ba38af023bf5f8..0787795beda1d49199ec557d962530ee438ebf41 100644 (file)
@@ -17,9 +17,14 @@ package com.intellij.openapi.project.ex;
 
 import com.intellij.openapi.components.impl.stores.IProjectStore;
 import com.intellij.openapi.project.Project;
+import com.intellij.util.messages.Topic;
 import org.jetbrains.annotations.NotNull;
 
 public interface ProjectEx extends Project {
+  interface ProjectSaved {
+    Topic<ProjectSaved> TOPIC = Topic.create("SaveProjectTopic", ProjectSaved.class, Topic.BroadcastDirection.NONE);
+    void saved(@NotNull final Project project);
+  }
 
   @NotNull
   IProjectStore getStateStore();
index 542c37501cca78b33398355042e421182a5a8ebc..7d4fd37606feacea6d01993b5076df5e5b227df4 100644 (file)
@@ -55,7 +55,6 @@ import org.picocontainer.defaults.CachingComponentAdapter;
 import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
 
 import java.io.IOException;
-import java.text.MessageFormat;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -267,6 +266,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx {
         LOG.info("Error saving project", e);
       } finally {
         mySavingInProgress.set(false);
+        ApplicationManager.getApplication().getMessageBus().syncPublisher(ProjectSaved.TOPIC).saved(this);
       }
     }
   }
index cd29df86201383c7e166e28b9d93d2903bcae012..2ca398b2b819ac12e20825f0f39901f2cae6a804 100644 (file)
@@ -115,8 +115,14 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
 
       if (mySheetCallback != null) {
         final Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
-        if (activeWindow != null && activeWindow instanceof Frame) {
-          final String frameTitle = ((Frame)activeWindow).getTitle();
+        if (activeWindow != null) {
+          String activeWindowTitle = null;
+          if (activeWindow instanceof Frame) {
+            activeWindowTitle = ((Frame)activeWindow).getTitle();
+          } else if (activeWindow instanceof JDialog) {
+            activeWindowTitle = ((JDialog)activeWindow).getTitle();
+          }
+          if (activeWindowTitle == null || activeWindowTitle.length() == 0) return;
 
           final ID sharedApplication = invoke("NSApplication", "sharedApplication");
           final ID windows = invoke(sharedApplication, "windows");
@@ -130,7 +136,10 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog {
 
             final ID windowTitle = invoke(window, "title");
             final String titleString = Foundation.toStringViaUTF8(windowTitle);
-            if (titleString.equals(frameTitle)) focusedWindow = window;
+            if (titleString.equals(activeWindowTitle)) {
+              focusedWindow = window;
+              break;
+            }
           }
 
           if (focusedWindow != null) {
index 9e2e05d0af93e3b1185ce85b0eaeaa34d007bad8..e69774c3ee917aac9013ad774cdcd389d0841c2e 100644 (file)
  */
 package com.intellij.util.ui;
 
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
 import com.intellij.ui.DocumentAdapter;
 import com.intellij.ui.table.TableView;
 
 import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
 import javax.swing.event.DocumentEvent;
 import javax.swing.table.TableCellEditor;
+import javax.swing.text.Document;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.EventObject;
 
 public abstract class ChangesTrackingTableView<T> extends TableView<T> {
 
-  private DocumentAdapter myMessageUpdater;
+  private Disposable myEditorListenerDisposable;
 
-  protected abstract void onTextChanged(int row, int column, String value);
+  protected abstract void onCellValueChanged(int row, int column, Object value);
 
   protected abstract void onEditingStopped();
 
@@ -43,21 +51,18 @@ public abstract class ChangesTrackingTableView<T> extends TableView<T> {
   @Override
   public boolean editCellAt(final int row, final int column, EventObject e) {
     if (super.editCellAt(row, column, e)) {
-      assert myMessageUpdater == null;
-      final JTextField textField;
-      if (getEditorComponent() instanceof CellEditorComponentWithBrowseButton) {
-        textField = (JTextField)((CellEditorComponentWithBrowseButton)editorComp).getChildComponent();
-      }
-      else {
-        textField = (JTextField)getEditorComponent();
-      }
-      myMessageUpdater = new DocumentAdapter() {
+      assert myEditorListenerDisposable == null;
+      myEditorListenerDisposable = new Disposable() {
         @Override
-        protected void textChanged(DocumentEvent e) {
-          onTextChanged(row, column, textField.getText());
+        public void dispose() {
         }
       };
-      textField.getDocument().addDocumentListener(myMessageUpdater);
+      addChangeListener(getEditorComponent(), new ChangeListener() {
+        @Override
+        public void stateChanged(ChangeEvent e) {
+          onCellValueChanged(row, column, getValue(getEditorComponent()));
+        }
+      }, myEditorListenerDisposable);
       return true;
     }
     return false;
@@ -65,19 +70,67 @@ public abstract class ChangesTrackingTableView<T> extends TableView<T> {
 
   @Override
   public void removeEditor() {
-    if (myMessageUpdater != null) {
-      final JTextField textField;
-      if (getEditorComponent() instanceof CellEditorComponentWithBrowseButton) {
-        textField = (JTextField)((CellEditorComponentWithBrowseButton)editorComp).getChildComponent();
-      }
-      else {
-        textField = (JTextField)getEditorComponent();
-      }
-      textField.getDocument().removeDocumentListener(myMessageUpdater);
-      myMessageUpdater = null;
+    if (myEditorListenerDisposable != null) {
+      Disposer.dispose(myEditorListenerDisposable);
+      myEditorListenerDisposable = null;
     }
 
     onEditingStopped();
     super.removeEditor();
   }
-}
+
+  public static Object getValue(Component component) {
+    if (component instanceof CellEditorComponentWithBrowseButton) {
+      final JTextField textField = (JTextField)((CellEditorComponentWithBrowseButton)component).getChildComponent();
+      return textField.getText();
+    }
+    else if (component instanceof JTextField) {
+      return ((JTextField)component).getText();
+    }
+    else if (component instanceof JComboBox) {
+      return ((JComboBox)component).getSelectedItem();
+    }
+    throw new UnsupportedOperationException("editor control of type " + component.getClass().getName() + " is not supported");
+  }
+
+  private static void addChangeListener(final Component component, final ChangeListener listener, Disposable parentDisposable) {
+    if (component instanceof CellEditorComponentWithBrowseButton) {
+      addChangeListener(((CellEditorComponentWithBrowseButton)component).getChildComponent(), listener, parentDisposable);
+    }
+    else if (component instanceof JTextField) {
+      final DocumentAdapter documentListener = new DocumentAdapter() {
+        @Override
+        protected void textChanged(DocumentEvent e) {
+          listener.stateChanged(new ChangeEvent(component));
+        }
+      };
+      final Document document = ((JTextField)component).getDocument();
+      document.addDocumentListener(documentListener);
+      Disposer.register(parentDisposable, new Disposable() {
+        @Override
+        public void dispose() {
+          document.removeDocumentListener(documentListener);
+        }
+      });
+    }
+    else if (component instanceof JComboBox) {
+      final ActionListener comboListener = new ActionListener() {
+        @Override
+        public void actionPerformed(ActionEvent e) {
+          listener.stateChanged(new ChangeEvent(component));
+        }
+      };
+      ((JComboBox)component).addActionListener(comboListener);
+      Disposer.register(parentDisposable, new Disposable() {
+        @Override
+        public void dispose() {
+          ((JComboBox)component).removeActionListener(comboListener);
+        }
+      });
+    }
+    else {
+      throw new UnsupportedOperationException("editor control of type " + component.getClass().getName() + " is not supported");
+    }
+  }
+
+}
\ No newline at end of file
index 5f8e3b7f475b75b7b37c29325e238c4fa7991fec..ea810e7d12f70dca2bb61648d47efe5f7d560d20 100644 (file)
@@ -53,16 +53,16 @@ public abstract class ValidatingTableEditor<Item> {
     String getTitle();
   }
 
-  private class ColumnInfoWrapper extends ColumnInfo<Item, String> {
-    private final ColumnInfo<Item, String> myDelegate;
+  private class ColumnInfoWrapper extends ColumnInfo<Item, Object> {
+    private final ColumnInfo<Item, Object> myDelegate;
 
-    public ColumnInfoWrapper(ColumnInfo<Item, String> delegate) {
+    public ColumnInfoWrapper(ColumnInfo<Item, Object> delegate) {
       super(delegate.getName());
       myDelegate = delegate;
     }
 
     @Override
-    public String valueOf(Item item) {
+    public Object valueOf(Item item) {
       return myDelegate.valueOf(item);
     }
 
@@ -72,7 +72,7 @@ public abstract class ValidatingTableEditor<Item> {
     }
 
     @Override
-    public void setValue(Item item, String value) {
+    public void setValue(Item item, Object value) {
       myDelegate.setValue(item, value);
       updateMessage(-1, null);
     }
@@ -81,6 +81,11 @@ public abstract class ValidatingTableEditor<Item> {
     public TableCellEditor getEditor(Item item) {
       return myDelegate.getEditor(item);
     }
+
+    @Override
+    public int getWidth(JTable table) {
+      return myDelegate.getWidth(table);
+    }
   }
 
   private JPanel myContentPane;
@@ -146,10 +151,10 @@ public abstract class ValidatingTableEditor<Item> {
 
   private void createUIComponents() {
     myTable = new ChangesTrackingTableView<Item>() {
-      protected void onTextChanged(int row, int column, String value) {
+      protected void onCellValueChanged(int row, int column, Object value) {
         final Item original = getItems().get(row);
         Item override = cloneOf(original);
-        final ColumnInfo<Item, String> columnInfo = getTableModel().getColumnInfos()[column];
+        final ColumnInfo<Item, Object> columnInfo = getTableModel().getColumnInfos()[column];
         columnInfo.setValue(override, value);
         updateMessage(row, override);
       }
@@ -235,7 +240,7 @@ public abstract class ValidatingTableEditor<Item> {
     return (ListTableModel<Item>)myTable.getModel();
   }
 
-  public void setModel(ColumnInfo<Item, String>[] valueColumns, List<Item> items) {
+  public void setModel(ColumnInfo<Item, Object>[] valueColumns, List<Item> items) {
     ColumnInfo[] columns = new ColumnInfo[valueColumns.length + 1];
     IconColumn iconColumn = new IconColumn();
     int maxHeight = iconColumn.getRowHeight();
@@ -265,15 +270,7 @@ public abstract class ValidatingTableEditor<Item> {
   private List<Item> doGetItems() {
     List<Item> items = new ArrayList<Item>(getTableModel().getItems());
     if (myTable.isEditing()) {
-      Component c = myTable.getEditorComponent();
-      final JTextField textField;
-      if (c instanceof CellEditorComponentWithBrowseButton) {
-        textField = (JTextField)((CellEditorComponentWithBrowseButton)c).getChildComponent();
-      }
-      else {
-        textField = (JTextField)c;
-      }
-      String value = textField.getText();
+      Object value = ChangesTrackingTableView.getValue(myTable.getEditorComponent());
       ColumnInfo column = ((ListTableModel)myTable.getModel()).getColumnInfos()[myTable.getEditingColumn()];
       ((ColumnInfoWrapper)column).myDelegate.setValue(items.get(myTable.getEditingRow()), value);
     }
@@ -308,7 +305,11 @@ public abstract class ValidatingTableEditor<Item> {
       current.set(index, override);
     }
 
-    Pair<String, Fix> messageAndFix = validate(current, myWarnings);
+    displayMessageAndFix(validate(current, myWarnings));
+    myTable.repaint();
+  }
+
+  protected void displayMessageAndFix(@Nullable Pair<String, Fix> messageAndFix) {
     if (messageAndFix != null) {
       myMessageLabel.setText(messageAndFix.first);
       myMessageLabel.setIcon(WARNING_ICON);
@@ -323,7 +324,11 @@ public abstract class ValidatingTableEditor<Item> {
       myFixLink.setVisible(false);
       myFixRunnable = null;
     }
-    myTable.repaint();
+  }
+
+  public void hideMessageLabel() {
+    myMessageLabel.setVisible(false);
+    myFixLink.setVisible(false);
   }
 
   public JComponent getPreferredFocusedComponent() {
@@ -354,5 +359,11 @@ public abstract class ValidatingTableEditor<Item> {
     return myContentPane;
   }
 
+  public void setColumnReorderingAllowed(boolean value) {
+    JTableHeader header = myTable.getTableHeader();
+    if (header != null) {
+      header.setReorderingAllowed(value);
+    }
+  }
 
 }
index 3baa67b01c81052060d2ed68dee33cd4dc22d6c5..5a74d03f650bbcd6eca59fa825fd570ff3d13d13 100644 (file)
@@ -76,6 +76,7 @@ public class DefaultSoftWrapApplianceManagerTest {
 
       // Storage.
       allowing(myStorage).removeAll();
+      allowing(myStorage).removeInRange(with(any(int.class)), with(any(int.class)));
 
       // Soft wrap drawings.
       allowing(myPainter).getMinDrawingWidth(with(any(SoftWrapDrawingType.class))); will(returnValue(SOFT_WRAP_DRAWING_SIZE));
@@ -110,8 +111,7 @@ public class DefaultSoftWrapApplianceManagerTest {
       allowing(myScrollingModel).getVisibleArea(); will(returnValue(new Rectangle(0, 0, context.visualWidth, Integer.MAX_VALUE)));
       allowing(myDocument).getLineEndOffset(0); will(returnValue(context.document.length()));
     }});
-    char[] documentChars = context.document.toCharArray();
-    myManager.registerSoftWrapIfNecessary(documentChars, 0, documentChars.length, 0, Font.PLAIN);
+    myManager.registerSoftWrapIfNecessary(context.document, 0, context.document.length(), 0, Font.PLAIN);
   }
 
   private static TextChangeImpl createSoftWrap(int offset, int indent) {
index 5f89db231ef478ca69d4ffb44fb29e725500fae1..3c5b8ce9c23b501a7debc6674d7ab1152a48c091 100644 (file)
               text="Add Test Notification"/>
       <action id="TestMessageBoxAction" internal="true" class="com.intellij.diagnostic.TestMessageBoxAction" text="Show Test Dialog"/>
       <separator/>
+      <action id="FocusDebugger" internal="true" class="com.intellij.internal.focus.FocusDebuggerAction" text="Start Focus Debugger"/>
+      <action id="UiInspector" internal="true" class="com.intellij.internal.inspector.UiInspectorAction" text="UI Inspector"/>
+      <separator/>
       <reference ref="MaintenanceGroup"/>
-      
+
       <add-to-group group-id="ToolsMenu" anchor="last"/>
     </group>
 
index fb19c3287c7b1ec19d113a5076e8ee65ce99d1ef..af1a4fe9e302b0d7286d05a19d5cacd60103bdea 100644 (file)
@@ -20,6 +20,7 @@ import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.text.CharArrayCharSequence;
 import gnu.trove.Equality;
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 
 import java.lang.reflect.Array;
 import java.util.Collection;
@@ -547,4 +548,9 @@ public class ArrayUtil {
 
     return (E[])Array.newInstance(sample.getClass().getComponentType(), count);
   }
+
+  @Nullable
+  public static <T> T getLastElement(T[] array) {
+    return array.length > 0 ? array[array.length -1] : null;
+  }
 }
index 1b4b3afb7d7514cb19f5a38a5de87e14ad12c490..b6176b88909fbab3cb0a3ca416d708966df7c237 100644 (file)
@@ -498,7 +498,6 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
       myFileAnnotation = fileAnnotation;
       myVcs = vcs;
       myFile = file;
-      final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider();
       currentLine = -1;
     }
 
@@ -593,12 +592,35 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
     private DiffNavigationContext createDiffNavigationContext(final int actualLine) {
       final MyContentsLines contentsLines = new MyContentsLines(myFileAnnotation.getAnnotatedContent());
 
+      final Pair<Integer, String> pair = correctActualLineIfTextEmpty(contentsLines, actualLine);
       return new DiffNavigationContext(new Iterable<String>() {
         @Override
         public Iterator<String> iterator() {
-          return new CacheOneStepIterator<String>(new ContextLineIterator(contentsLines, myFileAnnotation, actualLine));
+          return new CacheOneStepIterator<String>(new ContextLineIterator(contentsLines, myFileAnnotation, pair.getFirst()));
         }
-      }, contentsLines.getLineContents(actualLine));
+      }, pair.getSecond());
+    }
+
+    private final static int ourVicinity = 5;
+    private Pair<Integer, String> correctActualLineIfTextEmpty(final MyContentsLines contentsLines, final int actualLine) {
+      final VcsRevisionNumber revision = myFileAnnotation.getLineRevisionNumber(actualLine);
+
+      for (int i = actualLine; (i < (actualLine + ourVicinity)) && (! contentsLines.isLineEndsFinished()); i++) {
+        if (! revision.equals(myFileAnnotation.getLineRevisionNumber(i))) continue;
+        final String lineContents = contentsLines.getLineContents(i);
+        if (! StringUtil.isEmptyOrSpaces(lineContents)) {
+          return new Pair<Integer, String>(i, lineContents);
+        }
+      }
+      int bound = Math.max(actualLine - ourVicinity, 0);
+      for (int i = actualLine - 1; (i >= bound); --i) {
+        if (! revision.equals(myFileAnnotation.getLineRevisionNumber(i))) continue;
+        final String lineContents = contentsLines.getLineContents(i);
+        if (! StringUtil.isEmptyOrSpaces(lineContents)) {
+          return new Pair<Integer, String>(i, lineContents);
+        }
+      }
+      return new Pair<Integer, String>(actualLine, contentsLines.getLineContents(actualLine));
     }
 
     private static class MySplittingIterator implements Iterator<Integer> {
@@ -679,10 +701,15 @@ public class AnnotateToggleAction extends ToggleAction implements DumbAware {
                                                  (number + 1 >= myLinesStartOffsets.size())
                                                  ? myContents.length()
                                                  : myLinesStartOffsets.get(number + 1));
-        text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text.substring(0, text.length() - 1);
+        text = text.endsWith("\r\n") ? text.substring(0, text.length() - 2) : text;
+        text = (text.endsWith("\r") || text.endsWith("\n")) ? text.substring(0, text.length() - 1) : text;
         return text;
       }
 
+      public boolean isLineEndsFinished() {
+        return myLineEndsFinished;
+      }
+
       public int getKnownLinesNumber() {
         return myLineEndsFinished ? myLinesStartOffsets.size() : -1;
       }
index 1730c0d339993541ee2d2e478180d74ec6e8ad65..c441956a1349f65cb51fdcc9d6eb97bb4b9e6407 100644 (file)
@@ -119,6 +119,10 @@ public class ChangeDiffRequest implements ChangeRequestChain {
       }
       if (DiffPresentationReturnValue.removeFromList.equals(returnValue)) {
         mySteps.remove(nextIdx);
+        if (moveDirection.direction() < 0) {
+          // our position moves to head
+          myIndex += moveDirection.direction();
+        }
         continue;
       }
       final DiffRequest request = result.getRequest();
index 26cd7b3980eb3de0c41d146f8b832a67c165ee18..9ba87cd555daa6f277bc73c1fa56e74b33071d23 100644 (file)
@@ -130,6 +130,7 @@ public class IncomingChangesIndicator implements ProjectComponent {
     private void update(@NotNull final Icon icon, @Nullable final String toolTipText) {
       myCurrentIcon = icon;
       myToolTipText = toolTipText;
+      myStatusBar.updateWidget(ID());
     }
 
     @NotNull
index 2d26a8ab6a60e479563e4cfd2fabb2c58630b56b..68254c2590d7a6fae3cd2450a9703dc298213f6c 100644 (file)
@@ -34,6 +34,7 @@ public class VcsHandleTypeFactory implements HandleTypeFactory {
 
   @Nullable
   public HandleType createHandleType(final VirtualFile file) {
+    if (! myProject.isInitialized()) return null;
     AbstractVcs vcs = ProjectLevelVcsManager.getInstance(myProject).getVcsFor(file);
     if (vcs != null) {
       boolean fileExistsInVcs = vcs.fileExistsInVcs(new FilePathImpl(file));
index 4eb897633fa80ea3340f56b3c98c1baac86a1040..e6c4adf0f9dd188e46fc031dfaf8538cd57a8ed8 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.platform;
 
 import com.intellij.openapi.components.ProjectComponent;
+import com.intellij.openapi.project.DumbAwareRunnable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.startup.StartupManager;
 import com.intellij.openapi.vcs.AbstractVcs;
@@ -37,7 +38,7 @@ public class PlatformVcsDetector implements ProjectComponent {
   }
 
   public void projectOpened() {
-    StartupManager.getInstance(myProject).registerStartupActivity(new Runnable() {
+    StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
       public void run() {
         VirtualFile file = ProjectBaseDirectory.getInstance(myProject).getBaseDir(myProject.getBaseDir());
         AbstractVcs vcs = myVcsManager.findVersioningVcs(file);
index c92999342be57d8d5453d6f5b559b15da0fd83a3..66b4cb69f83a47174610f6f95bc5810b439b740c 100644 (file)
@@ -21,7 +21,7 @@ import com.intellij.lang.ant.dom.*;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.util.Comparing;
 import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Trinity;
+import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.psi.PsiFile;
 import com.intellij.psi.PsiFileSystemItem;
@@ -29,7 +29,10 @@ import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.xml.GenericAttributeValue;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 public class AntBuildModelImpl implements AntBuildModelBase {
 
@@ -43,9 +46,11 @@ public class AntBuildModelImpl implements AntBuildModelBase {
   public String getDefaultTargetName() {
     final AntDomProject antDomProject = getAntProject();
     if (antDomProject != null) {
-      final Trinity<AntDomTarget,String,Map<String,AntDomTarget>> defTarget = antDomProject.getDefaultTarget().getValue();
-      if (defTarget != null) {
-        return defTarget.getSecond();
+      final GenericAttributeValue<TargetResolver.Result> attrib = antDomProject.getDefaultTarget();
+      final TargetResolver.Result result = attrib.getValue();
+      if (result != null) {
+        final Pair<AntDomTarget,String> targetWithName = result.getResolvedTarget(attrib.getRawText());
+        return targetWithName != null? targetWithName.getSecond() : null;
       }
     }
     return "";
@@ -152,12 +157,10 @@ public class AntBuildModelImpl implements AntBuildModelBase {
           }
           myProcessed.add(sourceFile);
           if (!myIsImported) {
-            final GenericAttributeValue<Trinity<AntDomTarget,String,Map<String,AntDomTarget>>> defTarget = project.getDefaultTarget();
-            if (defTarget != null) {
-              final Trinity<AntDomTarget, String, Map<String, AntDomTarget>> trinity = defTarget.getValue();
-              if (trinity != null) {
-                myDefaultTarget = trinity.getFirst();
-              }
+            final TargetResolver.Result result = project.getDefaultTarget().getValue();
+            if (result != null) {
+              final Pair<AntDomTarget,String> targetWithName = result.getResolvedTarget(project.getDefaultTarget().getRawText());
+              myDefaultTarget = targetWithName != null? targetWithName.getFirst() : null;
             }
           }
           for (final AntDomTarget target : project.getDeclaredTargets()) {
index 699251fc4c151bdb9c3e6e7c0bfaefd6a866b6e8..0d13e97271fb9035bfec94ae621caefdf74211ff 100644 (file)
  */
 package com.intellij.lang.ant.dom;
 
-import com.intellij.openapi.util.Trinity;
 import com.intellij.util.xml.Attribute;
 import com.intellij.util.xml.Convert;
 import com.intellij.util.xml.GenericAttributeValue;
 import com.intellij.util.xml.SubTagList;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * @author Eugene Zhuravlev
@@ -32,7 +30,7 @@ public abstract class AntDomAntCall extends AntDomElement {
   
   @Attribute("target")
   @Convert(value = AntDomDefaultTargetConverter.class)
-  public abstract GenericAttributeValue<Trinity<AntDomTarget, String, Map<String, AntDomTarget>>> getTarget();
+  public abstract GenericAttributeValue<TargetResolver.Result> getTarget();
 
   @Attribute("inheritall")
   @Convert(value = AntBooleanConverterDefaultTrue.class)
index 5d13393cbd913ad79e353ff942a2caedc9c5bd09..39c24d79f82aa9a54f1cf149d01d345dd468868f 100644 (file)
  */
 package com.intellij.lang.ant.dom;
 
-import com.intellij.lang.ant.AntBundle;
 import com.intellij.lang.ant.AntSupport;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Trinity;
-import com.intellij.pom.references.PomService;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.xml.*;
+import com.intellij.util.xml.ConvertContext;
+import com.intellij.util.xml.Converter;
+import com.intellij.util.xml.CustomReferenceConverter;
+import com.intellij.util.xml.GenericDomValue;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.Map;
-import java.util.Set;
-
 /**
  * @author Eugene Zhuravlev
  *         Date: Apr 16, 2010
  */
-public class AntDomDefaultTargetConverter extends Converter<Trinity<AntDomTarget, String, Map<String, AntDomTarget>>> implements CustomReferenceConverter<Trinity<AntDomTarget, String, Map<String, AntDomTarget>>>{
-
-  @NotNull public PsiReference[] createReferences(final GenericDomValue<Trinity<AntDomTarget, String, Map<String, AntDomTarget>>> value, PsiElement element, ConvertContext context) {
-    return new PsiReference[] {new AntDomReferenceBase(element, true) {
-      public PsiElement resolve() {
-        final Trinity<AntDomTarget, String, Map<String, AntDomTarget>> trinity = value.getValue();
-        if (trinity == null) {
-          return null;
-        }
-        final DomTarget domTarget = trinity.getFirst() != null? DomTarget.getTarget(trinity.getFirst()) : null;
-        return domTarget != null? PomService.convertToPsi(domTarget) : null;
-      }
+public class AntDomDefaultTargetConverter extends Converter<TargetResolver.Result> implements CustomReferenceConverter<TargetResolver.Result>{
 
-      @NotNull
-      public Object[] getVariants() {
-        final Trinity<AntDomTarget, String, Map<String, AntDomTarget>> trinity = value.getValue();
-        if (trinity == null) {
-          return ArrayUtil.EMPTY_OBJECT_ARRAY;
-        }
-        final Set<String> set = trinity.getThird().keySet();
-        return set.toArray(new Object[set.size()]);
-      }
-
-      public String getUnresolvedMessagePattern() {
-        return AntBundle.message("cannot.resolve.target", getCanonicalText());
-      }
-    }};
+  @NotNull 
+  public PsiReference[] createReferences(final GenericDomValue<TargetResolver.Result> value, PsiElement element, ConvertContext context) {
+    return new PsiReference[] {new AntDomTargetReference(element)};
   }
 
   @Nullable
-  public Trinity<AntDomTarget, String, Map<String, AntDomTarget>> fromString(@Nullable @NonNls String s, ConvertContext context) {
+  public TargetResolver.Result fromString(@Nullable @NonNls String s, ConvertContext context) {
     final AntDomElement element = AntSupport.getInvocationAntDomElement(context);
     if (element != null && s != null) {
       final AntDomProject project = element.getAntProject();
       final TargetResolver.Result result = TargetResolver.resolve(project.getContextAntProject(), null, s);
-      final Pair<AntDomTarget,String> pair = result.getResolvedTarget(s);
-      return new Trinity<AntDomTarget, String, Map<String, AntDomTarget>>(pair != null? pair.getFirst() : null, pair != null? pair.getSecond() : null, result.getVariants());
+      result.setRefsString(s);
+      return result;
     }
     return null;
   }
 
   @Nullable
-  public String toString(@Nullable Trinity<AntDomTarget, String, Map<String, AntDomTarget>> trinity, ConvertContext context) {
-    return trinity != null? trinity.getSecond() : null;
+  public String toString(@Nullable TargetResolver.Result result, ConvertContext context) {
+    return result != null? result.getRefsString() : null;
   }
+
 }
index b2f1c06c0169dbe60123f203daaeda37d821b025..b4d9f5f490913806b7e9427a6a224cdc1f4bf8a3 100644 (file)
@@ -27,7 +27,6 @@ import com.intellij.openapi.projectRoots.ProjectJdkTable;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.roots.ProjectRootManager;
 import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.Trinity;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.pom.references.PomService;
@@ -63,7 +62,7 @@ public abstract class AntDomProject extends AntDomNamedElement implements Proper
 
   @Attribute("default")
   @Convert(value = AntDomDefaultTargetConverter.class)
-  public abstract GenericAttributeValue<Trinity<AntDomTarget, String, Map<String, AntDomTarget>>> getDefaultTarget();
+  public abstract GenericAttributeValue<TargetResolver.Result> getDefaultTarget();
 
   @Attribute("basedir")
   @Convert(value = AntPathConverter.class)
index 84fda8e3efd9fde8568a276f01109004c4c6e574..1ca97d931b0b751c661ea2666a80d4309eb736e9 100644 (file)
  */
 package com.intellij.lang.ant.dom;
 
-import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementBuilder;
-import com.intellij.lang.ant.AntBundle;
-import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.TextRange;
-import com.intellij.pom.references.PomService;
 import com.intellij.psi.ElementManipulators;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiReference;
@@ -29,12 +23,17 @@ import com.intellij.psi.xml.XmlAttribute;
 import com.intellij.psi.xml.XmlAttributeValue;
 import com.intellij.psi.xml.XmlElement;
 import com.intellij.util.text.StringTokenizer;
-import com.intellij.util.xml.*;
+import com.intellij.util.xml.ConvertContext;
+import com.intellij.util.xml.Converter;
+import com.intellij.util.xml.CustomReferenceConverter;
+import com.intellij.util.xml.GenericDomValue;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * @author Eugene Zhuravlev
@@ -83,18 +82,13 @@ public class AntDomTargetDependsListConverter extends Converter<TargetResolver.R
     if (valueElement == null) {
       return PsiReference.EMPTY_ARRAY;
     }
-    final TargetResolver.Result result = value.getValue();
-    if (result == null) {
+    final String refsString = value.getStringValue();
+    if (refsString == null) {
       return PsiReference.EMPTY_ARRAY;
     }
     final List<PsiReference> refs = new ArrayList<PsiReference>();
-    final StringTokenizer tokenizer = new StringTokenizer(result.getRefsString(), ",", false);
     final TextRange wholeStringRange = ElementManipulators.getValueTextRange(valueElement);
-    final Set<String> existingRefs = new HashSet<String>();
-    final AntDomTarget hostAntTarget = context.getInvocationElement().getParentOfType(AntDomTarget.class, false);
-    if (hostAntTarget != null) {
-      existingRefs.add(hostAntTarget.getName().getRawText()); // avoid setting dependencies onto itself
-    }
+    final StringTokenizer tokenizer = new StringTokenizer(refsString, ",", false);
     while (tokenizer.hasMoreTokens()) {
       final String token = tokenizer.nextToken();
       int tokenStartOffset = tokenizer.getCurrentPosition() - token.length();
@@ -109,42 +103,7 @@ public class AntDomTargetDependsListConverter extends Converter<TargetResolver.R
           }
         }
       }
-      final Pair<AntDomTarget,String> antTarget = result.getResolvedTarget(ref);
-      final DomTarget domTarget = (antTarget != null && antTarget.getFirst() != null) ? DomTarget.getTarget(antTarget.getFirst()) : null;
-      if (domTarget != null) {
-        existingRefs.add(antTarget.getSecond());
-      }
-      refs.add(new AntDomReferenceBase(valueElement, TextRange.from(wholeStringRange.getStartOffset() + tokenStartOffset, ref.length()), true) {
-        public PsiElement resolve() {
-          return domTarget != null? PomService.convertToPsi(domTarget) : null;
-        }
-        @NotNull
-        public Object[] getVariants() {
-          final List<Object> variants = new ArrayList<Object>();
-          for (Map.Entry<String, AntDomTarget> entry : result.getVariants().entrySet()) {
-            final String targetEffectiveName = entry.getKey();
-            if (!existingRefs.contains(targetEffectiveName)) {
-              //final AntDomTarget target = entry.getValue();
-              //final DomTarget _target = DomTarget.getTarget(target);
-              //if (_target == null) {
-              //  continue;
-              //}
-              //final PsiElement psi = PomService.convertToPsi(_target);
-              //if (psi == null) {
-              //  continue;
-              //}
-              final LookupElementBuilder builder = LookupElementBuilder.create(/*psi, */targetEffectiveName);
-              final LookupElement element = AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE.applyPolicy(builder);
-              variants.add(element);
-            }
-          }
-          return variants.toArray();
-        }
-
-        public String getUnresolvedMessagePattern() {
-          return AntBundle.message("cannot.resolve.target", getCanonicalText());
-        }
-      });
+      refs.add(new AntDomTargetReference(element, TextRange.from(wholeStringRange.getStartOffset() + tokenStartOffset, ref.length())));
     }
     return refs.toArray(new PsiReference[refs.size()]);
   }
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomTargetReference.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomTargetReference.java
new file mode 100644 (file)
index 0000000..6223b85
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2000-2010 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.lang.ant.dom;
+
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.lang.ant.AntBundle;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.pom.PomTarget;
+import com.intellij.pom.PomTargetPsiElement;
+import com.intellij.pom.references.PomService;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
+import com.intellij.psi.impl.PsiManagerEx;
+import com.intellij.psi.impl.source.resolve.ResolveCache;
+import com.intellij.refactoring.rename.BindablePsiReference;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ArrayListSet;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.text.StringTokenizer;
+import com.intellij.util.xml.DomElement;
+import com.intellij.util.xml.DomTarget;
+import com.intellij.util.xml.DomUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+* @author Eugene Zhuravlev
+*         Date: Aug 17, 2010
+*/
+class AntDomTargetReference extends AntDomReferenceBase implements BindablePsiReference{
+
+  public AntDomTargetReference(PsiElement element) {
+    super(element, true);
+  }
+
+  public AntDomTargetReference(PsiElement element, TextRange range) {
+    super(element, range, true);
+  }
+
+  public PsiElement resolve() {
+    return ((PsiManagerEx)getElement().getManager()).getResolveCache().resolveWithCaching(this, MyResolver.INSTANCE, false, false);
+  }
+
+  public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+    final DomElement targetDomElement = toDomElement(element);
+    if (targetDomElement != null) {
+      final AntDomTarget pointingToTarget = targetDomElement.getParentOfType(AntDomTarget.class, false);
+      if (pointingToTarget != null) {
+          // the aim here is to receive all variants available at this particular context
+          final TargetResolver.Result result = doResolve(null);
+          if (result != null) {
+            final Map<String, AntDomTarget> variants = result.getVariants();
+            for (Map.Entry<String, AntDomTarget> entry : variants.entrySet()) {
+              if (pointingToTarget.equals(entry.getValue())) {
+                handleElementRename(entry.getKey());
+                break;
+              }
+            }
+          }
+      }
+    }
+    return getElement();
+  }
+
+  @Nullable 
+  private AntDomElement getHostingAntDomElement() {
+    final DomElement selfElement = DomUtil.getDomElement(getElement());
+    if (selfElement == null) {
+      return null;
+    }
+    return selfElement.getParentOfType(AntDomElement.class, false);
+  }
+  
+  @Nullable 
+  public static DomElement toDomElement(PsiElement resolve) {
+    if (resolve instanceof PomTargetPsiElement) {
+      final PomTarget target = ((PomTargetPsiElement)resolve).getTarget();
+      if(target instanceof DomTarget) {
+        return ((DomTarget)target).getDomElement();
+      }
+      return null;
+    }
+    return DomUtil.getDomElement(resolve);
+  }
+
+  @NotNull
+  public Object[] getVariants() {
+    final TargetResolver.Result result = doResolve(getCanonicalText());
+    if (result == null) {
+      return EMPTY_ARRAY;
+    }
+    final Map<String, AntDomTarget> variants = result.getVariants();                                                                          
+    final List resVariants = new ArrayList();
+    final Set<String> existing = getExistingNames();
+    for (String s : variants.keySet()) {
+      if (existing.contains(s)){
+        continue;
+      }
+      final LookupElementBuilder builder = LookupElementBuilder.create(s);
+      final LookupElement element = AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE.applyPolicy(builder);
+      resVariants.add(element);
+    }
+    return ContainerUtil.toArray(resVariants, new Object[resVariants.size()]);
+  }
+
+  @Nullable
+  private TargetResolver.Result doResolve(@Nullable final String referenceText) {
+    final AntDomElement hostingElement = getHostingAntDomElement();
+    if (hostingElement == null) {
+      return null;
+    }
+    final AntDomTarget contextTarget = hostingElement.getParentOfType(AntDomTarget.class, false);
+    return TargetResolver.resolve(hostingElement.getContextAntProject(), contextTarget, referenceText == null? Collections.<String>emptyList() : Collections.singletonList(referenceText));
+  }
+  
+  private Set<String> getExistingNames() {
+    final AntDomElement hostingElement = getHostingAntDomElement();
+    if (hostingElement == null) {
+      return Collections.emptySet();
+    }
+    final AntDomTarget contextTarget = hostingElement.getParentOfType(AntDomTarget.class, false);
+    if (contextTarget == null) {
+      return Collections.emptySet();
+    }
+    final Set<String> existing = new ArrayListSet<String>();
+    final String selfName = contextTarget.getName().getStringValue();
+    if (selfName != null) {
+      existing.add(selfName);
+    }
+    final String dependsString = contextTarget.getDependsList().getStringValue();
+    if (dependsString != null) {
+      final StringTokenizer tokenizer = new StringTokenizer(dependsString, ",", false);
+      while (tokenizer.hasMoreTokens()) {
+        existing.add(tokenizer.nextToken().trim());
+      }
+    }
+    return existing;
+  }
+
+  public String getUnresolvedMessagePattern() {
+    return AntBundle.message("cannot.resolve.target", getCanonicalText());
+  }
+
+  private static class MyResolver implements ResolveCache.Resolver {
+    static final MyResolver INSTANCE = new MyResolver();
+    
+    public PsiElement resolve(PsiReference psiReference, boolean incompleteCode) {
+      final TargetResolver.Result result = ((AntDomTargetReference)psiReference).doResolve(psiReference.getCanonicalText());
+      if (result == null) {
+        return null;
+      }
+      final Pair<AntDomTarget,String> pair = result.getResolvedTarget(psiReference.getCanonicalText());
+      final DomTarget domTarget = pair != null && pair.getFirst() != null ? DomTarget.getTarget(pair.getFirst()) : null;
+      return domTarget != null? PomService.convertToPsi(domTarget) : null;
+    }
+  }
+}
index 335a815e4bebab8334654fc3976a23ea334b89df..8a9115f8539f179d66f7342be55ee6163a4ba1b0 100644 (file)
@@ -46,6 +46,7 @@ public abstract class PropertyProviderFinder extends AntDomRecursiveVisitor {
   private Map<String, List<String>> myDependenciesMap = new HashMap<String, List<String>>();   // target effective name -> dependencies effective names
 
   private Set<String> myProcessedTargets = new HashSet<String>();
+  private Set<AntDomProject> myVisitedProjects = new HashSet<AntDomProject>();
 
   protected PropertyProviderFinder(DomElement contextElement) {
     myContextElement = contextElement != null? contextElement.getParentOfType(AntDomElement.class, false) : null;
@@ -201,6 +202,13 @@ public abstract class PropertyProviderFinder extends AntDomRecursiveVisitor {
     processFileInclusion(importTag, InclusionKind.IMPORT);
   }
 
+  public void visitProject(AntDomProject project) {
+    if (!myVisitedProjects.contains(project)) {
+      myVisitedProjects.add(project);
+      super.visitProject(project);
+    }
+  }
+
   private void processFileInclusion(AntDomIncludingDirective directive, final InclusionKind kind) {
     if (directive.equals(myContextElement)) {
       stop();
index 5aac8711dfe6fc00ae9dba7ce600c65b49869878..1b5c37d30a8b551cc58e860c9fc69815e494cf15 100644 (file)
@@ -16,7 +16,7 @@
 
 package org.jetbrains.plugins.groovy.refactoring;
 
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.search.LocalSearchScope;
 import com.intellij.psi.search.SearchScope;
@@ -34,7 +34,7 @@ import org.jetbrains.plugins.groovy.refactoring.introduceVariable.GroovyIntroduc
 /**
  * @author ilyas
  */
-public class GroovyRefactoringSupportProvider extends DefaultRefactoringSupportProvider {
+public class GroovyRefactoringSupportProvider extends RefactoringSupportProvider {
 
   public static final GroovyRefactoringSupportProvider INSTANCE = new GroovyRefactoringSupportProvider();
 
@@ -61,7 +61,7 @@ public class GroovyRefactoringSupportProvider extends DefaultRefactoringSupportP
   }
 
   @Override
-  public boolean doInplaceRenameFor(PsiElement element, PsiElement context) {
+  public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) {
     if (!(element instanceof GrVariable)) return false;
     if (element instanceof GrField) return false;
 
index 88fe9ef59c531708e0c0bbee3a4d7f28454fae11..6396ad198c42341ba6e3448beabb3dceb4d71ffe 100644 (file)
  */
 package com.intellij.lang.properties;
 
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.psi.PsiElement;
 
-public class PropertiesRefactoringSupportProvider extends DefaultRefactoringSupportProvider {
+public class PropertiesRefactoringSupportProvider extends RefactoringSupportProvider {
   public boolean isSafeDeleteAvailable(PsiElement element) {
     return true;
   }
index 37636492d5be2466525aa767d2f1050ac1773143..daeb05e783d064b65005d6e426a4394f5afbf22d 100644 (file)
@@ -29,6 +29,7 @@ import com.intellij.psi.search.PsiElementProcessor;
 import com.intellij.psi.tree.TokenSet;
 import com.intellij.psi.xml.XmlDocument;
 import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
 import com.intellij.util.IncorrectOperationException;
 import org.intellij.plugins.relaxNG.compact.RncElementTypes;
 import org.intellij.plugins.relaxNG.compact.RncFileType;
@@ -63,6 +64,11 @@ public class RncFileImpl extends PsiFileBase implements RncFile, XmlFile {
     return document;
   }
 
+  @Override
+  public XmlTag getRootTag() {
+    return getDocument().getRootTag();
+  }
+
   @Override
   public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState substitutor, PsiElement lastParent, @NotNull PsiElement place) {
     //processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, this);
index 71d287c954fa0081dd43055508ac17c8c89473fc..35867bc469d949498d9593f4923cf65dd67fa39a 100644 (file)
@@ -493,7 +493,9 @@ public class SvnCommittedChangesProvider implements CachingCommittedChangesProvi
 
   @Override
   public Pair<SvnChangeList, FilePath> getOneList(final VirtualFile file, VcsRevisionNumber number) throws VcsException {
-    final VirtualFile root = ProjectLevelVcsManager.getInstance(myProject).getVcsRootFor(file);
+    final RootUrlInfo rootUrlInfo = myVcs.getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath()));
+    final VirtualFile root = rootUrlInfo.getVirtualFile();
+    if (root == null) return null;
     final SvnRepositoryLocation svnRootLocation = (SvnRepositoryLocation)getLocationFor(new FilePathImpl(root));
     if (svnRootLocation == null) return null;
     final String url = svnRootLocation.getURL();
index b4132432237ca7cc4b415c7c92dc0f8e8a5ddb25..0b1af1f034a3353175e148fe3362897e2751725b 100644 (file)
@@ -21,14 +21,12 @@ import com.intellij.lang.PairedBraceMatcher;
 import com.intellij.lang.cacheBuilder.SimpleWordsScanner;
 import com.intellij.lang.cacheBuilder.WordsScanner;
 import com.intellij.lang.findUsages.FindUsagesProvider;
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
 import com.intellij.lang.refactoring.NamesValidator;
 import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.navigation.ItemPresentation;
 import com.intellij.navigation.NavigationItem;
 import com.intellij.openapi.actionSystem.DataContext;
 import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileTypes.FileType;
 import com.intellij.openapi.fileTypes.SingleLazyInstanceSyntaxHighlighterFactory;
 import com.intellij.openapi.fileTypes.SyntaxHighlighter;
 import com.intellij.openapi.project.Project;
@@ -157,7 +155,7 @@ public final class XPathLanguage extends Language {
         }
     }
 
-    public static class XPathRefactoringSupportProvider extends DefaultRefactoringSupportProvider {
+    public static class XPathRefactoringSupportProvider extends RefactoringSupportProvider {
         @Override
         public boolean isSafeDeleteAvailable(PsiElement element) {
             if (!element.isWritable() || element.getContainingFile() == null) return false;
@@ -166,10 +164,10 @@ public final class XPathLanguage extends Language {
         }
 
         @Override
-        public boolean doInplaceRenameFor(PsiElement element, PsiElement context) {
+        public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) {
             if (!element.isWritable() || element.getContainingFile() == null) return false;
             final RefactoringSupportProvider realProvider = ContextProvider.getContextProvider(element).getRefactoringSupportProvider();
-            return realProvider != null && realProvider.doInplaceRenameFor(element, context);
+            return realProvider != null && realProvider.isInplaceRenameAvailable(element, context);
         }
 
         @Override
index c5fa0cda20c800e6bc388ceab5191b73cd019942..db48306abc6bb56988956eb882542d50bba8d75f 100644 (file)
@@ -20,7 +20,7 @@ import com.intellij.lang.LanguageRefactoringSupport;
 import com.intellij.lang.cacheBuilder.WordsScanner;
 import com.intellij.lang.findUsages.FindUsagesProvider;
 import com.intellij.lang.findUsages.LanguageFindUsages;
-import com.intellij.lang.refactoring.DefaultRefactoringSupportProvider;
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
 import com.intellij.lang.xml.XMLLanguage;
 import com.intellij.navigation.ItemPresentation;
 import com.intellij.navigation.NavigationItem;
@@ -46,9 +46,9 @@ public class XsltLanguage extends Language {
     XsltLanguage() {
         super(ID);
         LanguageFindUsages.INSTANCE.addExplicitExtension(this, new MyFindUsagesProvider());
-        LanguageRefactoringSupport.INSTANCE.addExplicitExtension(this, new DefaultRefactoringSupportProvider() {
+        LanguageRefactoringSupport.INSTANCE.addExplicitExtension(this, new RefactoringSupportProvider() {
             @Override
-            public boolean doInplaceRenameFor(PsiElement element, PsiElement context) {
+            public boolean isInplaceRenameAvailable(PsiElement element, PsiElement context) {
                 return element instanceof XsltVariable && element.getUseScope() instanceof LocalSearchScope;
             }
 
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XsltRefactoringSupportProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/XsltRefactoringSupportProvider.java
new file mode 100644 (file)
index 0000000..32989ba
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2010 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 org.intellij.lang.xpath.xslt.refactoring;
+
+import com.intellij.lang.refactoring.RefactoringSupportProvider;
+import com.intellij.refactoring.RefactoringActionHandler;
+import org.intellij.lang.xpath.xslt.refactoring.introduceParameter.XsltIntroduceParameterAction;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class XsltRefactoringSupportProvider extends RefactoringSupportProvider {
+
+  @Override
+  public RefactoringActionHandler getIntroduceParameterHandler() {
+    return new XsltIntroduceParameterAction();
+  }
+}
index 4879dbe47688e1944df1a418fec7572bdf8ccd74..b34866ed68aca9dc417766b1f9cc06f1f86f70fc 100644 (file)
@@ -16,6 +16,7 @@
 package org.intellij.lang.xpath;
 
 import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.testFramework.IdeaTestCase;
 import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
 import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
 import com.intellij.testFramework.fixtures.JavaTestFixtureFactory;
@@ -27,7 +28,12 @@ import junit.framework.TestCase;
 * Date: 17.12.2008
 */
 public abstract class TestBase extends TestCase {
-    protected CodeInsightTestFixture myFixture;
+
+  protected TestBase() {
+    IdeaTestCase.initPlatformPrefix();
+  }
+
+  protected CodeInsightTestFixture myFixture;
 
     @Override
     protected void setUp() throws Exception {
index 04772ebac7838b429882036c20c934856feaec10..84962b9d939b05b18a7bae4489f5962ca4427b47 100644 (file)
     <orderEntry type="module" module-name="xml" />
     <orderEntry type="library" name="commons-collections" level="project" />
     <orderEntry type="module" module-name="xslt-rt" />
-    <orderEntry type="library" name="JUnit4" level="project" />
-    <orderEntry type="module" module-name="testFramework-java" />
     <orderEntry type="module" module-name="lvcs-impl" />
     <orderEntry type="module" module-name="jam-support-impl" />
     <orderEntry type="module" module-name="execution-openapi" />
     <orderEntry type="module" module-name="annotations" />
     <orderEntry type="library" name="Jaxen" level="project" />
+    <orderEntry type="module" module-name="resources-en" />
+    <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+    <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
   </component>
 </module>
 
index c34d1bd9065784ce56fc822a2a006c4642ab8be8..6e9373e393e893e8f174b6d32ca16aa513c47760 100644 (file)
       <separator/>
       <action id="GenerateVisitorByHierarchy" internal="true" class="com.intellij.internal.GenerateVisitorByHierarchyAction" text="Generate Hierarchy Visitor"/>
       <separator/>
-      <action id="FocusDebugger" internal="true" class="com.intellij.internal.focus.FocusDebuggerAction" text="Start Focus Debugger"/>
-      <action id="UiInspector" internal="true" class="com.intellij.internal.inspector.UiInspectorAction" text="UI Inspector"/>
-      <separator/>
       <action id="DumpLookupElementWeights" internal="true" class="com.intellij.internal.DumpLookupElementWeights" text="Dump lookup element weights"/>
       <action id="CheckVfsSanity" internal="true" class="com.intellij.openapi.vfs.newvfs.persistent.CheckSanityAction" text="Check VFS sanity"/>
 
index f4258ec7f2722c20e6ad1d4e9288f7f14527ccf8..2e8c3fd268fde27d293273e9bc8f65ece5ab6a79 100644 (file)
@@ -216,4 +216,8 @@ public class SyntheticBlock extends AbstractSyntheticBlock implements Block, Rea
   public boolean endsWithAttribute() {
     return isAttributeBlock(getSubBlocks().get(getSubBlocks().size() - 1));
   }
+
+  public Indent getChildIndent() {
+    return myChildIndent;
+  }
 }
index dc848fe8c297b299a15a9006d336ee136a970d80..f598c4f0c6d2f38f41dfaf0028301718cb285f3a 100644 (file)
@@ -30,6 +30,7 @@ import com.intellij.psi.search.PsiElementProcessor;
 import com.intellij.psi.tree.IElementType;
 import com.intellij.psi.xml.XmlDocument;
 import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
 import org.jetbrains.annotations.NotNull;
 
 /**
@@ -51,6 +52,12 @@ public class XmlFileImpl extends PsiFileImpl implements XmlFile {
     return null;
   }
 
+  @Override
+  public XmlTag getRootTag() {
+    XmlDocument document = getDocument();
+    return document == null ? null : document.getRootTag();
+  }
+
   public boolean processElements(PsiElementProcessor processor, PsiElement place){
     final XmlDocument document = getDocument();
     return document == null || document.processElements(processor, place);
index 11a4e78043b65c7500f22fb3607525f11e9721db..764db5ac479d55822778eb0685504999eeb93c52 100644 (file)
@@ -22,6 +22,7 @@ import com.intellij.psi.filters.position.TargetNamespaceFilter;
 import com.intellij.psi.meta.MetaDataContributor;
 import com.intellij.psi.meta.MetaDataRegistrar;
 import com.intellij.psi.xml.*;
+import com.intellij.xml.impl.dtd.XmlNSDescriptorImpl;
 import com.intellij.xml.impl.schema.NamedObjectDescriptor;
 import com.intellij.xml.impl.schema.SchemaNSDescriptor;
 import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl;
@@ -53,6 +54,7 @@ public class XmlApplicationComponent implements MetaDataContributor {
                   new ContentFilter(
                     new OrFilter(
                       new ClassFilter(XmlElementDecl.class),
+                      new ClassFilter(XmlEntityDecl.class),
                       new ClassFilter(XmlConditionalSection.class),
                       new ClassFilter(XmlEntityRef.class)
                     )
@@ -61,7 +63,7 @@ public class XmlApplicationComponent implements MetaDataContributor {
               ),
               new ClassFilter(XmlMarkupDecl.class)
           ),
-          com.intellij.xml.impl.dtd.XmlNSDescriptorImpl.class
+          XmlNSDescriptorImpl.class
       );
     }
 
index 36166a63b96f6264b634950b7d8673c9a00f55f9..bbfcaa8dc55c8fd735dab768ba1e66f15a7a7e04 100644 (file)
@@ -200,11 +200,14 @@ public class XmlResourceResolver implements XMLEntityResolver {
 
     final PsiFile psiFile = result[0];
     if (psiFile != null) {
-      final String url = psiFile.getVirtualFile().getUrl();
-      if (LOG.isDebugEnabled()) {
-        LOG.debug("Adding external resource ref:"+systemId+","+url+","+super.toString());
+      final VirtualFile file = psiFile.getVirtualFile();
+      if (file != null) {
+        final String url = file.getUrl();
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Adding external resource ref:"+systemId+","+url+","+super.toString());
+        }
+        myExternalResourcesMap.put(systemId,url);
       }
-      myExternalResourcesMap.put(systemId,url);
     }
     return psiFile;
   }
@@ -241,9 +244,11 @@ public class XmlResourceResolver implements XMLEntityResolver {
     XMLInputSource source = new XMLInputSource(xmlResourceIdentifier);
     if (xmlResourceIdentifier.getLiteralSystemId() == null) {
       VirtualFile virtualFile = psiFile.getVirtualFile();
-      final String url = VfsUtil.fixIDEAUrl(virtualFile.getUrl());
-      source.setBaseSystemId(url);
-      source.setSystemId(url);
+      if (virtualFile != null) {
+        final String url = VfsUtil.fixIDEAUrl(virtualFile.getUrl());
+        source.setBaseSystemId(url);
+        source.setSystemId(url);
+      }
     }
     source.setPublicId(publicId);
     source.setCharacterStream(new StringReader(psiFile.getText()));
index 5d7e3834e6c39fba558151364cc9c4619d344325..3b6f19448cd4565dbb826dcc7af186da334ce8ba 100644 (file)
@@ -190,17 +190,9 @@ public class XmlUtil {
     return null;
   }
 
-  @SuppressWarnings({"ConstantConditions"})
-  public static XmlTag getRootTag(XmlFile file) {
-    if (file == null) return null;
-    final XmlDocument document = file.getDocument();
-    if (document == null) return null;
-    return document.getRootTag();
-  }
-
   @Nullable
   public static String findNamespacePrefixByURI(XmlFile file, @NonNls String uri) {
-    final XmlTag tag = getRootTag(file);
+    final XmlTag tag = file.getRootTag();
     if (tag == null) return null;
 
     for (XmlAttribute attribute : tag.getAttributes()) {
index 84dcfca3d26d8d82ee3e805a3d7ec2d1f9262c31..16f10cb43a69d860013b7ffac51aa3d0a0964a1d 100644 (file)
@@ -25,4 +25,7 @@ import org.jetbrains.annotations.Nullable;
 public interface XmlFile extends PsiFile, XmlElement, FileResolveScopeProvider {
   @Nullable
   XmlDocument getDocument();
+
+  @Nullable
+  XmlTag getRootTag();
 }