From b3a9c990b0cee9918fb64bea26ec35abaf5b1f16 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 26 Jan 2012 16:06:13 +0400 Subject: [PATCH 001/100] Get rid of exists() call on symlink detection --- .../vfs/impl/local/LocalFileSystemBase.java | 4 +- .../openapi/util/io/FileSystemUtil.java | 60 +++++++++++-------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index 38eeed18a5df..f2ff048a9429 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -188,6 +188,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { return ioFile; } + // todo[r.sh] use NIO2 API after migration to JDK 7 // returns -1 if could not get attributes @MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN}) private static int getBooleanAttributes(@NotNull File f) { @@ -196,8 +197,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f); return ((Integer)flags).intValue(); } - catch (Exception ignored) { - } + catch (Exception ignored) { } } return -1; } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java index c56c28e89536..337395d0b9bd 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -73,9 +73,9 @@ public class FileSystemUtil { private FileSystemUtil() { } - public static boolean isSymLink(@NotNull final File file) { + public static boolean isSymLink(@NotNull final String path) { try { - return ourMediator != null && file.exists() && ourMediator.isSymLink(file.getAbsolutePath()); + return ourMediator != null && ourMediator.isSymLink(path); } catch (Exception e) { LOG.warn(e); @@ -83,15 +83,15 @@ public class FileSystemUtil { } } - public static boolean isSymLink(@NotNull final String path) { - return isSymLink(new File(path)); + public static boolean isSymLink(@NotNull final File file) { + return isSymLink(file.getAbsolutePath()); } @Nullable - public static String resolveSymLink(@NotNull final File file) { - if (file.exists() && ourMediator != null) { + public static String resolveSymLink(@NotNull final String path) { + if (ourMediator != null) { try { - final String realPath = ourMediator.resolveSymLink(file.getAbsolutePath()); + final String realPath = ourMediator.resolveSymLink(path); if (realPath != null && new File(realPath).exists()) { return realPath; } @@ -104,18 +104,14 @@ public class FileSystemUtil { } @Nullable - public static String resolveSymLink(@NotNull final String path) { - return resolveSymLink(new File(path)); + public static String resolveSymLink(@NotNull final File file) { + return resolveSymLink(file.getAbsolutePath()); } public static int getPermissions(@NotNull final String path) { - return getPermissions(new File(path)); - } - - public static int getPermissions(@NotNull final File file) { - if (file.exists() && SystemInfo.isUnix && ourMediator != null) { + if (SystemInfo.isUnix && ourMediator != null) { try { - return ourMediator.getPermissions(file.getAbsolutePath()); + return ourMediator.getPermissions(path); } catch (Exception e) { LOG.warn(e); @@ -124,14 +120,14 @@ public class FileSystemUtil { return -1; } - public static void setPermissions(@NotNull final String path, final int permissions) { - setPermissions(new File(path), permissions); + public static int getPermissions(@NotNull final File file) { + return getPermissions(file.getAbsolutePath()); } - public static void setPermissions(@NotNull final File file, final int permissions) { - if (file.exists() && SystemInfo.isUnix && ourMediator != null) { + public static void setPermissions(@NotNull final String path, final int permissions) { + if (SystemInfo.isUnix && ourMediator != null) { try { - ourMediator.setPermissions(file.getAbsolutePath(), permissions); + ourMediator.setPermissions(path, permissions); } catch (Exception e) { LOG.warn(e); @@ -139,6 +135,10 @@ public class FileSystemUtil { } } + public static void setPermissions(@NotNull final File file, final int permissions) { + setPermissions(file.getAbsolutePath(), permissions); + } + private interface Mediator { boolean isSymLink(@NotNull String path) throws Exception; @@ -156,20 +156,28 @@ public class FileSystemUtil { private final Method myGetPath; private final Method myIsSymbolicLink; private final Object myLinkOptions; + private final Object myNoFollowLinkOptions; private final Method myGetAttribute; private final Method mySetAttribute; private Jdk7MediatorImpl() throws Exception { myDefaultFileSystem = Class.forName("java.nio.file.FileSystems").getMethod("getDefault").invoke(null); + myGetPath = Class.forName("java.nio.file.FileSystem").getMethod("getPath", String.class, String[].class); myGetPath.setAccessible(true); + final Class pathClass = Class.forName("java.nio.file.Path"); myIsSymbolicLink = Class.forName("java.nio.file.Files").getMethod("isSymbolicLink", pathClass); myIsSymbolicLink.setAccessible(true); - myLinkOptions = Array.newInstance(Class.forName("java.nio.file.LinkOption"), 0); - final Class linkOptClass = myLinkOptions.getClass(); - myGetAttribute = Class.forName("java.nio.file.Files").getMethod("getAttribute", pathClass, String.class, linkOptClass); - mySetAttribute = Class.forName("java.nio.file.Files").getMethod("setAttribute", pathClass, String.class, Object.class, linkOptClass); + + final Class linkOptClass = Class.forName("java.nio.file.LinkOption"); + myLinkOptions = Array.newInstance(linkOptClass, 0); + myNoFollowLinkOptions = Array.newInstance(linkOptClass, 1); + Array.set(myNoFollowLinkOptions, 0, linkOptClass.getField("NOFOLLOW_LINKS").get(null)); + + final Class linkOptArrClass = myLinkOptions.getClass(); + myGetAttribute = Class.forName("java.nio.file.Files").getMethod("getAttribute", pathClass, String.class, linkOptArrClass); + mySetAttribute = Class.forName("java.nio.file.Files").getMethod("setAttribute", pathClass, String.class, Object.class, linkOptArrClass); } @Override @@ -189,7 +197,7 @@ public class FileSystemUtil { @Override public int getPermissions(@NotNull final String path) throws Exception { final Object pathObj = myGetPath.invoke(myDefaultFileSystem, path, ArrayUtil.EMPTY_STRING_ARRAY); - final Object attribute = myGetAttribute.invoke(null, pathObj, POSIX_PERMISSIONS_ATTR, myLinkOptions); + final Object attribute = myGetAttribute.invoke(null, pathObj, POSIX_PERMISSIONS_ATTR, myNoFollowLinkOptions); return decodePermissions(attribute); } From 03cbfea688ea43d533b37b82c49e0b36d1228e5d Mon Sep 17 00:00:00 2001 From: Serega Vasiliev Date: Thu, 26 Jan 2012 11:55:17 +0100 Subject: [PATCH 002/100] supported additional spring configurations (AnnotationConfigApplicationContext), refactored filesets and spring processors --- .../com/intellij/ide/actions/GotoRelatedFileAction.java | 7 +++++-- .../src/com/intellij/util/xml/model/impl/DomModelImpl.java | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java index e60a8ccc09a7..52134b1f406a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoRelatedFileAction.java @@ -32,6 +32,8 @@ import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.Processor; +import com.intellij.util.containers.hash.*; +import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,6 +41,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.util.*; +import java.util.HashMap; import java.util.List; /** @@ -207,7 +210,7 @@ public class GotoRelatedFileAction extends AnAction { } } - List items = new ArrayList(); + Set items = new HashSet (); for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) { items.addAll(provider.getItems(contextElement)); @@ -215,7 +218,7 @@ public class GotoRelatedFileAction extends AnAction { items.addAll(provider.getItems(dataContext)); } } - return items; + return new ArrayList(items); } @Override diff --git a/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelImpl.java b/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelImpl.java index 2551b446df90..a3ef1b3a706c 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelImpl.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/model/impl/DomModelImpl.java @@ -17,6 +17,7 @@ package com.intellij.util.xml.model.impl; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; import com.intellij.psi.xml.XmlFile; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; From b157a3a256724417a7fc25e82169228830702f4e Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jan 2012 16:48:53 +0400 Subject: [PATCH 003/100] android: improve "add string resource" intention --- .../messages/AndroidBundle.properties | 10 +- .../android/actions/CreateResourceDialog.form | 2 +- .../actions/CreateXmlResourceDialog.form | 93 +++++++ .../actions/CreateXmlResourceDialog.java | 259 ++++++++++++++++++ .../AndroidAddStringResourceAction.java | 199 +++++++++++--- .../LocalResourceManager.java | 43 +-- .../uipreview/DeviceConfiguratorPanel.java | 2 +- .../android/util/AndroidResourceUtil.java | 39 ++- .../testData/addStringRes/Class10_after.java | 2 +- .../testData/addStringRes/Class11_after.java | 2 +- .../testData/addStringRes/Class12_after.java | 2 +- .../testData/addStringRes/Class13.java | 2 +- .../testData/addStringRes/Class13_after.java | 4 +- .../testData/addStringRes/Class14.java | 2 +- .../testData/addStringRes/Class1_after.java | 2 +- .../testData/addStringRes/Class2_after.java | 2 +- .../testData/addStringRes/Class3_after.java | 2 +- .../testData/addStringRes/Class4_after.java | 2 +- .../testData/addStringRes/Class5_after.java | 2 +- .../testData/addStringRes/Class6_after.java | 2 +- .../testData/addStringRes/Class7_after.java | 2 +- .../android/testData/addStringRes/Class8.java | 2 +- .../testData/addStringRes/Class8_after.java | 4 +- .../android/testData/addStringRes/Class9.java | 2 +- .../testData/addStringRes/Class9_after.java | 4 +- .../addStringRes/ClassEscape_after.java | 2 +- .../AndroidAddStringResourceActionTest.java | 25 +- 27 files changed, 587 insertions(+), 127 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.form create mode 100644 plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index feb398e022a1..2b6ad57b277f 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -1,6 +1,6 @@ command.0.execution.failed.with.exit.code.1=Command \"{0}\" execution failed with exit code {1} aidl.filetype.description=Android IDL files -add.string.resource.intention.text=Add a string resource +add.string.resource.intention.text=Extract string resource resource.name=Resource name intention.family=Android package.not.found.error=Package is not specified in the manifest file @@ -8,8 +8,8 @@ cannot.resolve.flag.error=Cannot resolve flag cannot.resolve.format.error=Cannot resolve format create.resource.quickfix.name=Create resource {0} in {1} quick.fixes.family=Android Quick Fixes -not.resource.file.error="File {0} is not resource file" -check.resource.dir.error=Check if resource directory exists +not.resource.file.error=File {0} is not resource file +check.resource.dir.error=Cannot find resource directory for module {0} choose.device.dialog.title=Choose Device replace.avd.question=AVD {0} already exists. Replace? create.avd.dialog.title=Create Android Virtual Device @@ -147,6 +147,7 @@ create.run.configuration.title=Create Android Run Configuration file.must.be.under.module.error=Cannot compute relative path for {0} android.extract.package.choose.dest.apk=Choose destination APK file android.cannot.create.file.error=Cannot create file {0} +android.cannot.create.dir.error=Cannot create directory {0} android.manifest.not.found.error=AndroidManifest.xml doesn't exist or has incorrect root tag android.apt.settings.title=AAPT Compiler android.aidl.settings.title=AIDL Compiler @@ -305,4 +306,5 @@ android.facet.settings.custom.debug.keystore.label=C&ustom debug keystore\: android.export.package.run.proguard.label=Run &ProGuard android.export.package.proguad.config.label=C&onfig file path\: android.extract.package.specify.proguard.cfg.path.error=Please specify ProGuard config file path -android.inspections.lint.name=Android Lint Validation \ No newline at end of file +android.inspections.lint.name=Android Lint Validation +android.lint.quickfixes.family=Android Lint Quick Fixes \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.form b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.form index efaa03fc30f8..560b404bdd2d 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.form +++ b/plugins/android/src/org/jetbrains/android/actions/CreateResourceDialog.form @@ -3,7 +3,7 @@ - + diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.form b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.form new file mode 100644 index 000000000000..e259ae3a5dad --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.form @@ -0,0 +1,93 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java new file mode 100644 index 000000000000..f6797c5924d5 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java @@ -0,0 +1,259 @@ +package org.jetbrains.android.actions; + +import com.android.AndroidConstants; +import com.android.ide.common.resources.configuration.FolderConfiguration; +import com.android.resources.ResourceFolderType; +import com.android.resources.ResourceType; +import com.intellij.CommonBundle; +import com.intellij.ide.ui.ListCellRendererWrapper; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.ui.components.JBLabel; +import com.intellij.util.containers.HashSet; +import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.resources.Resources; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.facet.AndroidRootUtil; +import org.jetbrains.android.resourceManagers.ResourceManager; +import org.jetbrains.android.uipreview.DeviceConfiguratorPanel; +import org.jetbrains.android.uipreview.InvalidOptionValueException; +import org.jetbrains.android.util.AndroidResourceUtil; +import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Set; + +/** + * @author Eugene.Kudelevsky + */ +public class CreateXmlResourceDialog extends DialogWrapper { + private JPanel myPanel; + private JPanel myDeviceConfigurationWrapper; + private JTextField myNameField; + private JComboBox myModuleCombo; + private JBLabel myModuleLabel; + private JTextField myDirectoryNameField; + private JBLabel myErrorLabel; + private JTextField myFileNameField; + + private final DeviceConfiguratorPanel myDeviceConfiguratorPanel; + private final Module myModule; + private final ResourceType myResourceType; + + public CreateXmlResourceDialog(@NotNull Module module, @NotNull ResourceType resourceType) { + super(module.getProject()); + + myResourceType = resourceType; + + final Set modulesSet = new HashSet(); + modulesSet.add(module); + + for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(module, true)) { + modulesSet.add(depFacet.getModule()); + } + + assert modulesSet.size() > 0; + + if (modulesSet.size() == 1) { + myModule = module; + myModuleLabel.setVisible(false); + myModuleCombo.setVisible(false); + } + else { + myModule = null; + + final Module[] modules = modulesSet.toArray(new Module[modulesSet.size()]); + Arrays.sort(modules, new Comparator() { + @Override + public int compare(Module m1, Module m2) { + return m1.getName().compareTo(m2.getName()); + } + }); + + myModuleCombo.setModel(new DefaultComboBoxModel(modules)); + myModuleCombo.setSelectedItem(module); + + myModuleCombo.setRenderer(new ListCellRendererWrapper(myModuleCombo.getRenderer()) { + @Override + public void customize(JList list, Module module, int index, boolean selected, boolean hasFocus) { + setText(module.getName()); + setIcon(ModuleType.get(module).getNodeIcon(false)); + } + }); + } + + myDeviceConfiguratorPanel = new DeviceConfiguratorPanel(null) { + @Override + public void applyEditors() { + try { + doApplyEditors(); + + final FolderConfiguration config = myDeviceConfiguratorPanel.getConfiguration(); + myErrorLabel.setText(""); + myDirectoryNameField.setText(config.getFolderName(ResourceFolderType.VALUES)); + } + catch (InvalidOptionValueException e) { + myErrorLabel.setText("" + e.getMessage() + ""); + myDirectoryNameField.setText(AndroidConstants.FD_RES_VALUES); + } + } + }; + myDeviceConfigurationWrapper.add(myDeviceConfiguratorPanel, BorderLayout.CENTER); + + final String defaultResFileName = ResourceManager.getDefaultResourceFileName(resourceType.getName()); + if (defaultResFileName != null) { + myFileNameField.setText(defaultResFileName); + } + myDirectoryNameField.setText(AndroidConstants.FD_RES_VALUES); + myDeviceConfiguratorPanel.updateAll(); + + init(); + } + + @Override + protected ValidationInfo doValidate() { + final String resourceName = getResourceName(); + final Module selectedModule = getModule(); + final String directoryName = getDirectoryName(); + final String fileName = getFileName(); + + if (resourceName.length() == 0) { + return new ValidationInfo("specify resource name", myNameField); + } + else if (!AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) { + return new ValidationInfo(resourceName + " is not correct resource name", myNameField); + } + else if (fileName.length() == 0) { + return new ValidationInfo("specify file name", myFileNameField); + } + else if (selectedModule == null) { + return new ValidationInfo("specify module", myModuleCombo); + } + else if (!ResourceFolderType.VALUES.getName().equals( + ResourceManager.getResourceTypeByDirName(directoryName))) { + return new ValidationInfo("directory name is not appropriate for value resources"); + } + + final ValidationInfo info = checkIfResourceAlreadyExists(selectedModule, resourceName, myResourceType, directoryName, fileName); + if (info != null) { + return info; + } + + try { + myDeviceConfiguratorPanel.doApplyEditors(); + } + catch (InvalidOptionValueException e) { + return new ValidationInfo("fix errors in configuration editor"); + } + + return null; + } + + @Nullable + private static ValidationInfo checkIfResourceAlreadyExists(@NotNull Module selectedModule, + @NotNull String resourceName, + @NotNull ResourceType resourceType, + @NotNull String directoryName, + @NotNull String fileName) { + if (resourceName.length() == 0 || + directoryName.length() == 0 || + fileName.length() == 0) { + return null; + } + + final VirtualFile resourceDir = AndroidRootUtil.getResourceDir(selectedModule); + if (resourceDir == null) { + return null; + } + + final VirtualFile resourceSubdir = resourceDir.findChild(directoryName); + if (resourceSubdir == null) { + return null; + } + + final VirtualFile resFile = resourceSubdir.findChild(fileName); + if (resFile == null || resFile.getFileType() != StdFileTypes.XML) { + return null; + } + + final Resources resources = AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class); + if (resources == null) { + return null; + } + + for (ResourceElement element : ResourceManager.getValueResources(resourceType.getName(), resources)) { + if (resourceName.equals(element.getName().getValue())) { + return new ValidationInfo("resource '" + resourceName + "' already exists in " + FileUtil.toSystemDependentName( + resFile.getPath())); + } + } + return null; + } + + @Override + public JComponent getPreferredFocusedComponent() { + return myNameField; + } + + @Override + protected void doOKAction() { + final String resourceName = getResourceName(); + final String fileName = getFileName(); + final String dirName = getDirectoryName(); + final Module module = getModule(); + + if (resourceName.length() == 0) { + Messages.showErrorDialog(myPanel, "Resource name is not specified", CommonBundle.getErrorTitle()); + } + else if (!AndroidResourceUtil.isCorrectAndroidResourceName(resourceName)) { + Messages.showErrorDialog(myPanel, resourceName + " is not correct resource name", CommonBundle.getErrorTitle()); + } + else if (fileName.length() == 0) { + Messages.showErrorDialog(myPanel, "File name is not specified", CommonBundle.getErrorTitle()); + } + else if (dirName.length() == 0) { + Messages.showErrorDialog(myPanel, "Directory name is not specified", CommonBundle.getErrorTitle()); + } + else if (module == null) { + Messages.showErrorDialog(myPanel, "Module is not specified", CommonBundle.getErrorTitle()); + } + else { + super.doOKAction(); + } + } + + @NotNull + public String getResourceName() { + return myNameField.getText().trim(); + } + + @NotNull + public String getDirectoryName() { + return myDirectoryNameField.getText().trim(); + } + + @NotNull + public String getFileName() { + return myFileNameField.getText().trim(); + } + + @Nullable + public Module getModule() { + return myModule != null ? myModule : (Module)myModuleCombo.getSelectedItem(); + } + + @Override + protected JComponent createCenterPanel() { + return myPanel; + } +} diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index 9826b6d9aabe..9b5a38e630ff 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -16,6 +16,7 @@ package org.jetbrains.android.intentions; +import com.android.resources.ResourceType; import com.intellij.CommonBundle; import com.intellij.codeInsight.intention.AbstractIntentionAction; import com.intellij.codeInsight.lookup.LookupElement; @@ -23,35 +24,40 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.template.*; import com.intellij.codeInsight.template.impl.*; import com.intellij.codeInsight.template.macro.VariableOfTypeMacro; +import com.intellij.ide.actions.CreateElementActionBase; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.undo.UndoUtil; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.InputValidatorEx; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.TextRange; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.android.AndroidFileTemplateProvider; +import org.jetbrains.android.actions.CreateXmlResourceDialog; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.resources.Resources; import org.jetbrains.android.facet.AndroidFacet; -import org.jetbrains.android.resourceManagers.LocalResourceManager; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.util.LinkedHashSet; import java.util.Set; -import static com.intellij.openapi.ui.Messages.showInputDialog; import static org.jetbrains.android.util.AndroidUtils.VIEW_CLASS_NAME; /** @@ -62,6 +68,8 @@ import static org.jetbrains.android.util.AndroidUtils.VIEW_CLASS_NAME; * To change this template use File | Settings | File Templates. */ public class AndroidAddStringResourceAction extends AbstractIntentionAction { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.intentions.AndroidAddStringResourceAction"); + private static final String CONTEXT = AndroidUtils.ANDROID_PACKAGE + ".content.Context"; private static final String RESOURCES = AndroidUtils.ANDROID_PACKAGE + ".content.res.Resources"; @@ -124,50 +132,56 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { } static void doInvoke(Project project, Editor editor, PsiFile file, @Nullable String resName) { - AndroidFacet facet = AndroidFacet.getInstance(file); + final AndroidFacet facet = AndroidFacet.getInstance(file); assert facet != null; - PsiElement element = getPsiElement(file, editor); + + final PsiElement element = getPsiElement(file, editor); assert element != null; + String value = getStringLiteralValue(element, file); assert value != null; value = value.replace("'", "\\'").replace("\"", "\\\""); - String aPackage = getPackage(facet); + + final String aPackage = getPackage(facet); if (aPackage == null) { Messages.showErrorDialog(project, AndroidBundle.message("package.not.found.error"), CommonBundle.getErrorTitle()); return; } + if (resName == null) { - resName = - showInputDialog(project, AndroidBundle.message("resource.name"), AndroidBundle.message("add.string.resource.intention.text"), - Messages.getQuestionIcon(), "", new InputValidatorEx() { - public String getErrorText(String inputString) { - if (inputString == null || inputString.length() == 0) return null; - String[] ids = inputString.split("."); - for (String id : ids) { - if (!StringUtil.isJavaIdentifier(id)) { - return AndroidBundle.message("android.identifier.expected", id); - } - } - return null; - } + final CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(facet.getModule(), ResourceType.STRING); + dialog.setTitle("Extract String Resource"); + dialog.show(); + + if (!dialog.isOK()) { + return; + } - public boolean checkInput(String inputString) { - return inputString != null && AndroidResourceUtil.isCorrectAndroidResourceName(inputString); - } + final Module module = dialog.getModule(); + if (module == null) { + return; + } - public boolean canClose(String inputString) { - return checkInput(inputString); - } - }); + final ResourceElement createdElement = + doCreate(module, dialog.getResourceName(), ResourceType.STRING, dialog.getFileName(), dialog.getDirectoryName(), value); + + if (createdElement != null) { + resName = createdElement.getName().getValue(); + } } - if (resName == null) return; - LocalResourceManager manager = facet.getLocalResourceManager(); - String resType = "string"; - ResourceElement resElement = manager.addValueResource(resType, resName, value); - assert resElement != null; - createJavaResourceReference(project, editor, file, element, aPackage, resName, resType); + else { + assert ApplicationManager.getApplication().isUnitTestMode(); + doCreate(facet.getModule(), resName, ResourceType.STRING, "strings.xml", "values", value); + } + + if (resName == null) { + return; + } + + createJavaResourceReference(project, editor, file, element, aPackage, resName, ResourceType.STRING.getName()); PsiDocumentManager.getInstance(project).commitAllDocuments(); UndoUtil.markPsiFileForUndo(file); + ApplicationManager.getApplication().invokeLater(new Runnable() { public void run() { ApplicationManager.getApplication().saveAll(); @@ -188,14 +202,25 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { assert methodName != null; final TemplateImpl template; final boolean inStaticContext = RefactoringUtil.isInStaticContext(element, null); + if (extendsContext && !inStaticContext) { - template = new TemplateImpl("", "$resources$." + methodName + "(" + field + ")", ""); - MacroCallNode node = new MacroCallNode(new MyVarOfTypeExpression("getResources()")); - node.addParameter(new ConstantNode(RESOURCES)); - template.addVariable("resources", node, new ConstantNode(""), true); + if (ResourceType.STRING.getName().equals(resType)) { + template = new TemplateImpl("", methodName + '(' + field + ')', ""); + } + else { + template = new TemplateImpl("", "$resources$." + methodName + "(" + field + ")", ""); + MacroCallNode node = new MacroCallNode(new MyVarOfTypeExpression("getResources()")); + node.addParameter(new ConstantNode(RESOURCES)); + template.addVariable("resources", node, new ConstantNode(""), true); + } } else { - template = new TemplateImpl("", "$context$.getResources()." + methodName + "(" + field + ")", ""); + if (ResourceType.STRING.getName().equals(resType)) { + template = new TemplateImpl("", "$context$." + methodName + "(" + field + ")", ""); + } + else { + template = new TemplateImpl("", "$context$.getResources()." + methodName + "(" + field + ")", ""); + } final boolean extendsView = getContainingInheritorOf(element, VIEW_CLASS_NAME) != null; MacroCallNode node = new MacroCallNode(extendsView && !inStaticContext ? new MyVarOfTypeExpression("getContext()") : new VariableOfTypeMacro()); @@ -242,6 +267,104 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { return true; } + @Nullable + private static ResourceElement doCreate(@NotNull Module module, + @NotNull String resourceName, + @NotNull ResourceType resourceType, + @NotNull String fileName, + @NotNull String dirName, + @NotNull String value) { + final Project project = module.getProject(); + final AndroidFacet facet = AndroidFacet.getInstance(module); + assert facet != null; + + try { + return addValueResource(facet, resourceName, resourceType, fileName, dirName, value); + } + catch (Exception e) { + final String message = CreateElementActionBase.filterMessage(e.getMessage()); + + if (message == null || message.length() == 0) { + LOG.error(e); + } + else { + LOG.info(e); + reportError(project, message); + } + return null; + } + } + + @Nullable + public static ResourceElement addValueResource(@NotNull AndroidFacet facet, + @NotNull String resourceName, + @NotNull ResourceType resourceType, + @NotNull String fileName, + @NotNull String dirName, + @NotNull String value) throws Exception { + final VirtualFile resFile = findOrCreateResourceFile(facet, fileName, dirName); + if (resFile == null) { + return null; + } + + final Resources resources = AndroidUtils.loadDomElement(facet.getModule(), resFile, Resources.class); + if (resources == null) { + reportError(facet.getModule().getProject(), AndroidBundle.message("not.resource.file.error", fileName)); + return null; + } + + final ResourceElement element = AndroidResourceUtil.addValueResource(resourceType.getName(), resources); + element.getName().setValue(resourceName); + + if (value.length() > 0) { + element.setStringValue(value); + } + return element; + } + + @Nullable + private static VirtualFile findOrCreateResourceFile(@NotNull AndroidFacet facet, + @NotNull final String fileName, + @NotNull String dirName) throws Exception { + final Module module = facet.getModule(); + final Project project = module.getProject(); + final VirtualFile resDir = facet.getLocalResourceManager().getResourceDir(); + + if (resDir == null) { + reportError(project, AndroidBundle.message("check.resource.dir.error", module.getName())); + return null; + } + final VirtualFile dir = AndroidUtils.createChildDirectoryIfNotExist(project, resDir, dirName); + final String dirPath = FileUtil.toSystemDependentName(resDir.getPath() + '/' + dirName); + + if (dir == null) { + reportError(project, AndroidBundle.message("android.cannot.create.dir.error", dirPath)); + return null; + } + + final VirtualFile file = dir.findChild(fileName); + if (file != null) { + return file; + } + + AndroidFileTemplateProvider + .createFromTemplate(project, dir, AndroidFileTemplateProvider.VALUE_RESOURCE_FILE_TEMPLATE, fileName); + final VirtualFile result = dir.findChild(fileName); + if (result == null) { + reportError(project, AndroidBundle.message("android.cannot.create.file.error", dirPath + File.separatorChar + fileName)); + } + return result; + } + + private static void reportError(@NotNull Project project, @NotNull String message) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + throw new IncorrectOperationException(message); + } + else { + Messages.showErrorDialog(project, message, CommonBundle.getErrorTitle()); + } + } + private static class MyVarOfTypeExpression extends VariableOfTypeMacro { private final String myDefaultValue; diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java index fc34714eefeb..3722ec9a371b 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/LocalResourceManager.java @@ -208,7 +208,8 @@ public class LocalResourceManager extends ResourceManager { private VirtualFile findOrCreateResourceFile(@NotNull final String fileName) { VirtualFile dir = getResourceDir(); if (dir == null) { - Messages.showErrorDialog(myModule.getProject(), AndroidBundle.message("check.resource.dir.error"), CommonBundle.getErrorTitle()); + Messages.showErrorDialog(myModule.getProject(), AndroidBundle.message("check.resource.dir.error", myModule.getName()), + CommonBundle.getErrorTitle()); return null; } final VirtualFile valuesDir = findOrCreateChildDir(dir, AndroidConstants.FD_RES_VALUES); @@ -240,7 +241,8 @@ public class LocalResourceManager extends ResourceManager { VirtualFile resDir = getResourceDir(); Project project = myModule.getProject(); if (resDir == null) { - Messages.showErrorDialog(project, AndroidBundle.message("check.resource.dir.error"), CommonBundle.getErrorTitle()); + Messages + .showErrorDialog(project, AndroidBundle.message("check.resource.dir.error", myModule.getName()), CommonBundle.getErrorTitle()); return null; } PsiElement[] createdElements = CreateResourceFileAction.createResourceFile(project, resDir, resType, fileOrResourceName); @@ -269,7 +271,7 @@ public class LocalResourceManager extends ResourceManager { CommonBundle.getErrorTitle()); return null; } - ResourceElement element = addValueResource(type, resources); + ResourceElement element = AndroidResourceUtil.addValueResource(type, resources); element.getName().setValue(name); if (value != null) { element.setStringValue(value); @@ -277,41 +279,6 @@ public class LocalResourceManager extends ResourceManager { return element; } - @NotNull - private static ResourceElement addValueResource(@NotNull final String type, @NotNull final Resources resources) { - if (type.equals("string")) { - return resources.addString(); - } - else if (type.equals("dimen")) { - return resources.addDimen(); - } - else if (type.equals("color")) { - return resources.addColor(); - } - else if (type.equals("drawable")) { - return resources.addDrawable(); - } - else if (type.equals("style")) { - return resources.addStyle(); - } - else if (type.equals("array")) { - // todo: choose among string-array, integer-array and array - return resources.addStringArray(); - } - else if (type.equals("integer")) { - return resources.addInteger(); - } - else if (type.equals("bool")) { - return resources.addBool(); - } - else if (type.equals("id")) { - Item item = resources.addItem(); - item.getType().setValue("id"); - return item; - } - throw new IllegalArgumentException("Incorrect resource type"); - } - @Nullable private VirtualFile findOrCreateChildDir(@NotNull final VirtualFile dir, @NotNull final String name) { try { diff --git a/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java b/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java index 19738d60d394..ebb4303166f4 100644 --- a/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java +++ b/plugins/android/src/org/jetbrains/android/uipreview/DeviceConfiguratorPanel.java @@ -252,7 +252,7 @@ public abstract class DeviceConfiguratorPanel extends JPanel { applyEditors(); } - protected void doApplyEditors() throws InvalidOptionValueException { + public void doApplyEditors() throws InvalidOptionValueException { try { final FolderConfiguration newConfig = new FolderConfiguration(); diff --git a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java index b3c0a380d7a8..4d95bb5dc5b1 100644 --- a/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java +++ b/plugins/android/src/org/jetbrains/android/util/AndroidResourceUtil.java @@ -35,9 +35,7 @@ import com.intellij.util.containers.HashSet; import com.intellij.util.indexing.FileBasedIndex; import org.jetbrains.android.AndroidIdIndex; import org.jetbrains.android.dom.manifest.Manifest; -import org.jetbrains.android.dom.resources.Attr; -import org.jetbrains.android.dom.resources.DeclareStyleable; -import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.resources.*; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.resourceManagers.LocalResourceManager; import org.jetbrains.android.resourceManagers.ResourceManager; @@ -402,4 +400,39 @@ public class AndroidResourceUtil { List targets = findResourcesByField(manager, resField); return PsiUtilBase.toPsiElementArray(targets); } + + @NotNull + public static ResourceElement addValueResource(@NotNull final String type, @NotNull final Resources resources) { + if (type.equals("string")) { + return resources.addString(); + } + else if (type.equals("dimen")) { + return resources.addDimen(); + } + else if (type.equals("color")) { + return resources.addColor(); + } + else if (type.equals("drawable")) { + return resources.addDrawable(); + } + else if (type.equals("style")) { + return resources.addStyle(); + } + else if (type.equals("array")) { + // todo: choose among string-array, integer-array and array + return resources.addStringArray(); + } + else if (type.equals("integer")) { + return resources.addInteger(); + } + else if (type.equals("bool")) { + return resources.addBool(); + } + else if (type.equals("id")) { + Item item = resources.addItem(); + item.getType().setValue("id"); + return item; + } + throw new IllegalArgumentException("Incorrect resource type"); + } } diff --git a/plugins/android/testData/addStringRes/Class10_after.java b/plugins/android/testData/addStringRes/Class10_after.java index f4fa6807e3f1..baf3c102a5e4 100644 --- a/plugins/android/testData/addStringRes/Class10_after.java +++ b/plugins/android/testData/addStringRes/Class10_after.java @@ -6,6 +6,6 @@ import p1.p2.R; public class Class extends View { public static void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class11_after.java b/plugins/android/testData/addStringRes/Class11_after.java index 8b6382d95d97..9382074c0fb6 100644 --- a/plugins/android/testData/addStringRes/Class11_after.java +++ b/plugins/android/testData/addStringRes/Class11_after.java @@ -6,6 +6,6 @@ import p1.p2.R; public class Class extends View { public void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class12_after.java b/plugins/android/testData/addStringRes/Class12_after.java index 83e438df6bc1..7e60cc7a2b4e 100644 --- a/plugins/android/testData/addStringRes/Class12_after.java +++ b/plugins/android/testData/addStringRes/Class12_after.java @@ -6,6 +6,6 @@ import p1.p2.R; public class Class extends View { public void f() { - String s = getContext().getResources().getString(R.string.hello); + String s = getContext().getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class13.java b/plugins/android/testData/addStringRes/Class13.java index 88386f469397..9e041435687c 100644 --- a/plugins/android/testData/addStringRes/Class13.java +++ b/plugins/android/testData/addStringRes/Class13.java @@ -4,7 +4,7 @@ import android.content.Context; import android.content.res.Resources; public class Class extends Context { - public void f(Resources resources) { + public void f(Context resources) { String s = "hello"; } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class13_after.java b/plugins/android/testData/addStringRes/Class13_after.java index 5ec2a470edd8..09500911aac2 100644 --- a/plugins/android/testData/addStringRes/Class13_after.java +++ b/plugins/android/testData/addStringRes/Class13_after.java @@ -5,7 +5,7 @@ import android.content.res.Resources; import p1.p2.R; public class Class extends Context { - public void f(Resources resources) { - String s = resources.getString(R.string.hello); + public void f(Context resources) { + String s = getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class14.java b/plugins/android/testData/addStringRes/Class14.java index a878406b7b5e..712cfb75b390 100644 --- a/plugins/android/testData/addStringRes/Class14.java +++ b/plugins/android/testData/addStringRes/Class14.java @@ -4,7 +4,7 @@ import android.content.Context; import android.content.res.Resources; public class Class extends Context { - public void f(Resources resources) { + public void f(Context resources) { String s = "hello"; } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class1_after.java b/plugins/android/testData/addStringRes/Class1_after.java index 9ff6724619a7..97da0a51a00a 100644 --- a/plugins/android/testData/addStringRes/Class1_after.java +++ b/plugins/android/testData/addStringRes/Class1_after.java @@ -5,6 +5,6 @@ import p1.p2.R; public class Class { public void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class2_after.java b/plugins/android/testData/addStringRes/Class2_after.java index 9d15d2e96123..ed96dfac98e1 100644 --- a/plugins/android/testData/addStringRes/Class2_after.java +++ b/plugins/android/testData/addStringRes/Class2_after.java @@ -4,6 +4,6 @@ import p1.p2.R; public class Class { public void f() { - String s = .getResources().getString(R.string.hello); + String s = .getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class3_after.java b/plugins/android/testData/addStringRes/Class3_after.java index 91ccbec6b974..e673d41f2bc3 100644 --- a/plugins/android/testData/addStringRes/Class3_after.java +++ b/plugins/android/testData/addStringRes/Class3_after.java @@ -4,6 +4,6 @@ import android.content.Context; public class Class { public static void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class4_after.java b/plugins/android/testData/addStringRes/Class4_after.java index 9103cc7e9188..bd29df958460 100644 --- a/plugins/android/testData/addStringRes/Class4_after.java +++ b/plugins/android/testData/addStringRes/Class4_after.java @@ -5,6 +5,6 @@ import p1.p2.R; public class Class extends Context { public void f() { - String s = getResources().getString(R.string.hello); + String s = getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class5_after.java b/plugins/android/testData/addStringRes/Class5_after.java index 1e236c780eb5..da79fab7bb17 100644 --- a/plugins/android/testData/addStringRes/Class5_after.java +++ b/plugins/android/testData/addStringRes/Class5_after.java @@ -5,6 +5,6 @@ import p1.p2.R; public class Class extends Context { public void f(Context context) { - String s = r.getString(R.string.hello); + String s = getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class6_after.java b/plugins/android/testData/addStringRes/Class6_after.java index b7c6406839cb..a93565254d49 100644 --- a/plugins/android/testData/addStringRes/Class6_after.java +++ b/plugins/android/testData/addStringRes/Class6_after.java @@ -4,6 +4,6 @@ import android.content.Context; public class Class extends Context { public static void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class7_after.java b/plugins/android/testData/addStringRes/Class7_after.java index e86ce36b99d8..00b2c250ff40 100644 --- a/plugins/android/testData/addStringRes/Class7_after.java +++ b/plugins/android/testData/addStringRes/Class7_after.java @@ -5,6 +5,6 @@ import p1.p2.R; public class Class extends Context { public static void f() { - String s = c.getResources().getString(R.string.hello); + String s = c.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class8.java b/plugins/android/testData/addStringRes/Class8.java index 693f55baf78e..6fc5467ab4e8 100644 --- a/plugins/android/testData/addStringRes/Class8.java +++ b/plugins/android/testData/addStringRes/Class8.java @@ -4,7 +4,7 @@ import android.content.res.Resources; import android.content.Context; public class Class extends Context { - public static void f(Resources resources) { + public static void f(Context resources) { String s = "hello"; } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class8_after.java b/plugins/android/testData/addStringRes/Class8_after.java index 2e14b4212485..f6f6d1ce2364 100644 --- a/plugins/android/testData/addStringRes/Class8_after.java +++ b/plugins/android/testData/addStringRes/Class8_after.java @@ -4,7 +4,7 @@ import android.content.res.Resources; import android.content.Context; public class Class extends Context { - public static void f(Resources resources) { - String s = .getResources().getString(R.string.hello); + public static void f(Context resources) { + String s = resources.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class9.java b/plugins/android/testData/addStringRes/Class9.java index 1e6f044c4f45..47817692eb10 100644 --- a/plugins/android/testData/addStringRes/Class9.java +++ b/plugins/android/testData/addStringRes/Class9.java @@ -4,7 +4,7 @@ import android.content.res.Resources; import android.content.Context; public class Class extends Context { - public void f(Resources resources) { + public void f(Context context) { String s = "hello"; } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/Class9_after.java b/plugins/android/testData/addStringRes/Class9_after.java index 11dd486a73cd..f5529bd3b025 100644 --- a/plugins/android/testData/addStringRes/Class9_after.java +++ b/plugins/android/testData/addStringRes/Class9_after.java @@ -4,7 +4,7 @@ import android.content.res.Resources; import android.content.Context; public class Class extends Context { - public void f(Resources resources) { - String s = getResources().getString(R.string.hello); + public void f(Context context) { + String s = getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/ClassEscape_after.java b/plugins/android/testData/addStringRes/ClassEscape_after.java index 0658a8a53f82..f92cf49160a9 100644 --- a/plugins/android/testData/addStringRes/ClassEscape_after.java +++ b/plugins/android/testData/addStringRes/ClassEscape_after.java @@ -4,6 +4,6 @@ import android.content.Context; public class ClassEscape { public static void f(Context context) { - String s = context.getResources().getString(R.string.hello); + String s = context.getString(R.string.hello); } } \ No newline at end of file diff --git a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java index b58ff1cd2633..462010c04dfc 100644 --- a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java @@ -46,13 +46,7 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { } public void test5() { - doTest(new Runnable() { - @Override - public void run() { - myFixture.type('r'); - TemplateManagerImpl.getTemplateState(myFixture.getEditor()).nextTab(); - } - }); + doTest(); } public void test6() { @@ -70,12 +64,7 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { } public void test8() { - doTest(new Runnable() { - @Override - public void run() { - myFixture.performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM); - } - }); + doTest(); } public void test9() { @@ -101,13 +90,7 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { } public void test13() { - doTest(new Runnable() { - @Override - public void run() { - myFixture.type("r"); - myFixture.performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM); - } - }); + doTest(); } public void test14() { @@ -132,7 +115,7 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { } catch (IncorrectOperationException e) { // in normal mode error dialog will be shown - assertEquals("invalid strings.xml", e.getMessage()); + assertEquals("File strings.xml is not resource file", e.getMessage()); } myFixture.checkResultByFile(BASE_PATH + "Class1.java"); myFixture.checkResultByFile("res/values/strings.xml", BASE_PATH + "strings_invalid.xml", false); From ef2de85e81211d4543144e79a34a8a229a5b4e8b Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jan 2012 17:35:53 +0400 Subject: [PATCH 004/100] IDEA-63248 android: "extract string resource" intention should work in layout xml files --- .../AndroidAddStringResourceAction.java | 18 +++++++++++++++++- .../testData/addStringRes/fromLayout.xml | 11 +++++++++++ .../testData/addStringRes/fromLayout_after.xml | 11 +++++++++++ .../AndroidAddStringResourceActionTest.java | 18 ++++++++++++++++-- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 plugins/android/testData/addStringRes/fromLayout.xml create mode 100644 plugins/android/testData/addStringRes/fromLayout_after.xml diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index 9b5a38e630ff..0715cfc35f90 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -40,12 +40,16 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlFile; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.android.AndroidFileTemplateProvider; import org.jetbrains.android.actions.CreateXmlResourceDialog; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.dom.resources.ResourceElement; +import org.jetbrains.android.dom.resources.ResourceValue; import org.jetbrains.android.dom.resources.Resources; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.util.AndroidBundle; @@ -102,6 +106,9 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { return (String)value; } } + else if (file instanceof XmlFile && element instanceof XmlAttributeValue) { + return ((XmlAttributeValue)element).getValue(); + } return null; } @@ -178,7 +185,16 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { return; } - createJavaResourceReference(project, editor, file, element, aPackage, resName, ResourceType.STRING.getName()); + if (file instanceof PsiJavaFile) { + createJavaResourceReference(project, editor, file, element, aPackage, resName, ResourceType.STRING.getName()); + } + else { + final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class); + if (attribute != null) { + attribute.setValue(ResourceValue.referenceTo('@', null, ResourceType.STRING.getName(), resName).toString()); + } + } + PsiDocumentManager.getInstance(project).commitAllDocuments(); UndoUtil.markPsiFileForUndo(file); diff --git a/plugins/android/testData/addStringRes/fromLayout.xml b/plugins/android/testData/addStringRes/fromLayout.xml new file mode 100644 index 000000000000..1b496cc10ad8 --- /dev/null +++ b/plugins/android/testData/addStringRes/fromLayout.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/fromLayout_after.xml b/plugins/android/testData/addStringRes/fromLayout_after.xml new file mode 100644 index 000000000000..c074c981ecad --- /dev/null +++ b/plugins/android/testData/addStringRes/fromLayout_after.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java index 462010c04dfc..5ccbde1c42bf 100644 --- a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java @@ -121,6 +121,12 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { myFixture.checkResultByFile("res/values/strings.xml", BASE_PATH + "strings_invalid.xml", false); } + public void testFromLayout() { + final VirtualFile javaFile = myFixture.copyFileToProject(BASE_PATH + getTestName(false) + ".xml", "res/layout/layout.xml"); + doExtractAndCheckStringsXml("strings.xml", null, true, "strings_after.xml", javaFile); + myFixture.checkResultByFile(BASE_PATH + getTestName(false) + "_after.xml"); + } + private void doTest() { doTest(getTestName(false), "strings.xml", null, true); } @@ -138,11 +144,20 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { @Nullable final Runnable invokeAfterTemplate, final boolean closePopup, String stringsAfter) { + VirtualFile javaFile = myFixture.copyFileToProject(BASE_PATH + "Class" + testName + ".java", "src/p1/p2/Class.java"); + doExtractAndCheckStringsXml(stringsXml, invokeAfterTemplate, closePopup, stringsAfter, javaFile); + myFixture.checkResultByFile(BASE_PATH + "Class" + testName + "_after.java"); + } + + private void doExtractAndCheckStringsXml(String stringsXml, + final Runnable invokeAfterTemplate, + final boolean closePopup, + String stringsAfter, + VirtualFile javaFile) { if (stringsXml != null) { myFixture.copyFileToProject(BASE_PATH + stringsXml, "res/values/strings.xml"); } myFixture.copyFileToProject(BASE_PATH + "R.java", "src/p1/p2/R.java"); - VirtualFile javaFile = myFixture.copyFileToProject(BASE_PATH + "Class" + testName + ".java", "src/p1/p2/Class.java"); myFixture.configureFromExistingVirtualFile(javaFile); final PsiFile javaPsiFile = myFixture.getFile(); assertTrue(new AndroidAddStringResourceAction().isAvailable(myFixture.getProject(), myFixture.getEditor(), javaPsiFile)); @@ -163,7 +178,6 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { } } }, "", ""); - myFixture.checkResultByFile(BASE_PATH + "Class" + testName + "_after.java"); myFixture.checkResultByFile("res/values/strings.xml", BASE_PATH + stringsAfter, false); } } From 5fc914f545127e146d6c8798ec37f0455f842844 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 24 Jan 2012 18:48:23 +0400 Subject: [PATCH 005/100] 'extract string' android intention: validate xml and dom in dialog --- .../android/actions/CreateXmlResourceDialog.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java index f6797c5924d5..dae344b92ced 100644 --- a/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java +++ b/plugins/android/src/org/jetbrains/android/actions/CreateXmlResourceDialog.java @@ -22,6 +22,7 @@ import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.resourceManagers.ResourceManager; import org.jetbrains.android.uipreview.DeviceConfiguratorPanel; import org.jetbrains.android.uipreview.InvalidOptionValueException; +import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidResourceUtil; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; @@ -182,13 +183,17 @@ public class CreateXmlResourceDialog extends DialogWrapper { } final VirtualFile resFile = resourceSubdir.findChild(fileName); - if (resFile == null || resFile.getFileType() != StdFileTypes.XML) { + if (resFile == null) { return null; } + if (resFile.getFileType() != StdFileTypes.XML) { + return new ValidationInfo("File " + FileUtil.toSystemDependentName(resFile.getPath()) + " is not XML file"); + } + final Resources resources = AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class); if (resources == null) { - return null; + return new ValidationInfo(AndroidBundle.message("not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath()))); } for (ResourceElement element : ResourceManager.getValueResources(resourceType.getName(), resources)) { From c9def85bf0cf5dcaeda13d5683d626c79b777838 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Wed, 25 Jan 2012 13:19:27 +0400 Subject: [PATCH 006/100] android: "extract string" intention should work in manifest and only in attributes allowing string references --- .../ResourceReferenceConverter.java | 7 +- .../AndroidAddStringResourceAction.java | 42 ++++++++-- .../testData/addStringRes/fromLayout1.xml | 11 +++ .../testData/addStringRes/fromManifest.xml | 8 ++ .../testData/addStringRes/fromManifest1.xml | 8 ++ .../addStringRes/fromManifest1_after.xml | 8 ++ .../testData/addStringRes/fromManifest2.xml | 10 +++ .../AndroidAddStringResourceActionTest.java | 81 +++++++++++++------ 8 files changed, 142 insertions(+), 33 deletions(-) create mode 100644 plugins/android/testData/addStringRes/fromLayout1.xml create mode 100644 plugins/android/testData/addStringRes/fromManifest.xml create mode 100644 plugins/android/testData/addStringRes/fromManifest1.xml create mode 100644 plugins/android/testData/addStringRes/fromManifest1_after.xml create mode 100644 plugins/android/testData/addStringRes/fromManifest2.xml diff --git a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java index ad7fee9ff8a5..e77187a20cde 100644 --- a/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java +++ b/plugins/android/src/org/jetbrains/android/dom/converters/ResourceReferenceConverter.java @@ -165,7 +165,12 @@ public class ResourceReferenceConverter extends ResolvingConverter getResourceTypes(ConvertContext context) { - ResourceType resourceType = context.getInvocationElement().getAnnotation(ResourceType.class); + return getResourceTypes(context.getInvocationElement()); + } + + @NotNull + public Set getResourceTypes(@NotNull DomElement element) { + ResourceType resourceType = element.getAnnotation(ResourceType.class); Set types = new HashSet(myResourceTypes); if (resourceType != null) { String s = resourceType.value(); diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index 0715cfc35f90..d22ddd0c21c2 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -45,8 +45,12 @@ import com.intellij.psi.xml.XmlAttributeValue; import com.intellij.psi.xml.XmlFile; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.xml.Converter; +import com.intellij.util.xml.DomManager; +import com.intellij.util.xml.GenericAttributeValue; import org.jetbrains.android.AndroidFileTemplateProvider; import org.jetbrains.android.actions.CreateXmlResourceDialog; +import org.jetbrains.android.dom.converters.ResourceReferenceConverter; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.dom.resources.ResourceElement; import org.jetbrains.android.dom.resources.ResourceValue; @@ -107,7 +111,29 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { } } else if (file instanceof XmlFile && element instanceof XmlAttributeValue) { - return ((XmlAttributeValue)element).getValue(); + final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class); + + if (attribute != null) { + final GenericAttributeValue domAttribute = DomManager.getDomManager(element.getProject()).getDomElement(attribute); + + if (domAttribute != null) { + final Converter converter = domAttribute.getConverter(); + + if (converter instanceof ResourceReferenceConverter) { + final ResourceValue value = (ResourceValue)domAttribute.getValue(); + + if (value != null && !value.isReference()) { + final Set types = ((ResourceReferenceConverter)converter).getResourceTypes(domAttribute); + + for (String type : types) { + if (ResourceType.STRING.getName().equals(type)) { + return ((XmlAttributeValue)element).getValue(); + } + } + } + } + } + } } return null; } @@ -141,25 +167,25 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { static void doInvoke(Project project, Editor editor, PsiFile file, @Nullable String resName) { final AndroidFacet facet = AndroidFacet.getInstance(file); assert facet != null; - + final PsiElement element = getPsiElement(file, editor); assert element != null; - + String value = getStringLiteralValue(element, file); assert value != null; value = value.replace("'", "\\'").replace("\"", "\\\""); - + final String aPackage = getPackage(facet); if (aPackage == null) { Messages.showErrorDialog(project, AndroidBundle.message("package.not.found.error"), CommonBundle.getErrorTitle()); return; } - + if (resName == null) { final CreateXmlResourceDialog dialog = new CreateXmlResourceDialog(facet.getModule(), ResourceType.STRING); dialog.setTitle("Extract String Resource"); dialog.show(); - + if (!dialog.isOK()) { return; } @@ -180,7 +206,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { assert ApplicationManager.getApplication().isUnitTestMode(); doCreate(facet.getModule(), resName, ResourceType.STRING, "strings.xml", "values", value); } - + if (resName == null) { return; } @@ -194,7 +220,7 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { attribute.setValue(ResourceValue.referenceTo('@', null, ResourceType.STRING.getName(), resName).toString()); } } - + PsiDocumentManager.getInstance(project).commitAllDocuments(); UndoUtil.markPsiFileForUndo(file); diff --git a/plugins/android/testData/addStringRes/fromLayout1.xml b/plugins/android/testData/addStringRes/fromLayout1.xml new file mode 100644 index 000000000000..f152f913e39d --- /dev/null +++ b/plugins/android/testData/addStringRes/fromLayout1.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testData/addStringRes/fromManifest.xml b/plugins/android/testData/addStringRes/fromManifest.xml new file mode 100644 index 000000000000..2997ac33cd72 --- /dev/null +++ b/plugins/android/testData/addStringRes/fromManifest.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/plugins/android/testData/addStringRes/fromManifest1.xml b/plugins/android/testData/addStringRes/fromManifest1.xml new file mode 100644 index 000000000000..3b6843287cb9 --- /dev/null +++ b/plugins/android/testData/addStringRes/fromManifest1.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/plugins/android/testData/addStringRes/fromManifest1_after.xml b/plugins/android/testData/addStringRes/fromManifest1_after.xml new file mode 100644 index 000000000000..e7ed000835ae --- /dev/null +++ b/plugins/android/testData/addStringRes/fromManifest1_after.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/plugins/android/testData/addStringRes/fromManifest2.xml b/plugins/android/testData/addStringRes/fromManifest2.xml new file mode 100644 index 000000000000..1f1431a0ecb7 --- /dev/null +++ b/plugins/android/testData/addStringRes/fromManifest2.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java index 5ccbde1c42bf..c2970ace69c0 100644 --- a/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/intentions/AndroidAddStringResourceActionTest.java @@ -11,12 +11,18 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.android.AndroidTestCase; import org.jetbrains.annotations.Nullable; +import java.io.IOException; + /** * @author Eugene.Kudelevsky */ public class AndroidAddStringResourceActionTest extends AndroidTestCase { private static final String BASE_PATH = "addStringRes/"; + public AndroidAddStringResourceActionTest() { + super(false); + } + @Override public void setUp() throws Exception { super.setUp(); @@ -29,31 +35,31 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { super.tearDown(); } - public void test1() { + public void test1() throws IOException { doTest(); } - public void test2() { + public void test2() throws IOException { doTest(); } - public void test3() { + public void test3() throws IOException { doTest(); } - public void test4() { + public void test4() throws IOException { doTest(); } - public void test5() { + public void test5() throws IOException { doTest(); } - public void test6() { + public void test6() throws IOException { doTest(); } - public void test7() { + public void test7() throws IOException { doTest(new Runnable() { @Override public void run() { @@ -63,19 +69,19 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { }); } - public void test8() { + public void test8() throws IOException { doTest(); } - public void test9() { + public void test9() throws IOException { doTest(); } - public void test10() { + public void test10() throws IOException { doTest(); } - public void test11() { + public void test11() throws IOException { doTest(new Runnable() { @Override public void run() { @@ -85,11 +91,11 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { }); } - public void test12() { + public void test12() throws IOException { doTest(); } - public void test13() { + public void test13() throws IOException { doTest(); } @@ -100,15 +106,15 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { assertFalse(new AndroidAddStringResourceAction().isAvailable(myFixture.getProject(), myFixture.getEditor(), javaPsiFile)); } - public void testEscape() { + public void testEscape() throws IOException { doTest(getTestName(false), "strings.xml", null, true, "strings_escape_after.xml"); } - public void testNewFile() { + public void testNewFile() throws IOException { doTest("1", null, null, true); } - public void testInvalidStringsXml() { + public void testInvalidStringsXml() throws IOException { try { doTest("1", "strings_invalid.xml", null, true); fail(); @@ -121,21 +127,47 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { myFixture.checkResultByFile("res/values/strings.xml", BASE_PATH + "strings_invalid.xml", false); } - public void testFromLayout() { - final VirtualFile javaFile = myFixture.copyFileToProject(BASE_PATH + getTestName(false) + ".xml", "res/layout/layout.xml"); - doExtractAndCheckStringsXml("strings.xml", null, true, "strings_after.xml", javaFile); - myFixture.checkResultByFile(BASE_PATH + getTestName(false) + "_after.xml"); + public void testFromLayout() throws IOException { + createManifest(); + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + ".xml", "res/layout/layout.xml"); + doExtractAndCheckStringsXml("strings.xml", null, true, "strings_after.xml", file); + myFixture.checkResultByFile(BASE_PATH + getTestName(true) + "_after.xml"); } - private void doTest() { + public void testFromLayout1() throws IOException { + createManifest(); + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + ".xml", "res/layout/layout.xml"); + myFixture.configureFromExistingVirtualFile(file); + assertFalse(new AndroidAddStringResourceAction().isAvailable(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())); + } + + public void testFromManifest() { + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + ".xml", "AndroidManifest.xml"); + myFixture.configureFromExistingVirtualFile(file); + assertFalse(new AndroidAddStringResourceAction().isAvailable(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())); + } + + public void testFromManifest1() { + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + ".xml", "AndroidManifest.xml"); + doExtractAndCheckStringsXml("strings.xml", null, true, "strings_after.xml", file); + myFixture.checkResultByFile(BASE_PATH + getTestName(true) + "_after.xml"); + } + + public void testFromManifest2() { + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + ".xml", "AndroidManifest.xml"); + myFixture.configureFromExistingVirtualFile(file); + assertFalse(new AndroidAddStringResourceAction().isAvailable(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())); + } + + private void doTest() throws IOException { doTest(getTestName(false), "strings.xml", null, true); } - private void doTest(Runnable invokeAfterTemplate) { + private void doTest(Runnable invokeAfterTemplate) throws IOException { doTest(getTestName(false), "strings.xml", invokeAfterTemplate, false); } - private void doTest(String testName, String stringsXml, final Runnable invokeAfterTemplate, final boolean closePopup) { + private void doTest(String testName, String stringsXml, final Runnable invokeAfterTemplate, final boolean closePopup) throws IOException { doTest(testName, stringsXml, invokeAfterTemplate, closePopup, "strings_after.xml"); } @@ -143,7 +175,8 @@ public class AndroidAddStringResourceActionTest extends AndroidTestCase { String stringsXml, @Nullable final Runnable invokeAfterTemplate, final boolean closePopup, - String stringsAfter) { + String stringsAfter) throws IOException { + createManifest(); VirtualFile javaFile = myFixture.copyFileToProject(BASE_PATH + "Class" + testName + ".java", "src/p1/p2/Class.java"); doExtractAndCheckStringsXml(stringsXml, invokeAfterTemplate, closePopup, stringsAfter, javaFile); myFixture.checkResultByFile(BASE_PATH + "Class" + testName + "_after.java"); From e36a22db6c00a017c9c8171bafaf9f14630551d7 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 26 Jan 2012 16:30:14 +0400 Subject: [PATCH 007/100] android: support quick fixes for lint; tests --- .../messages/AndroidBundle.properties | 17 +- .../lint/AddMissingPrefixQuickFix.java | 72 ++++++ .../AndroidAddStringResourceQuickFix.java | 47 ++++ .../lint/AndroidLintExternalAnnotator.java | 164 +++++++++---- .../AndroidLintGlobalInspectionContext.java | 20 +- .../lint/AndroidLintInspectionBase.java | 71 +++++- .../AndroidLintInspectionToolProvider.java | 124 ++++++++-- .../inspections/lint/AndroidLintQuickFix.java | 20 ++ .../inspections/lint/AndroidLintUtil.java | 57 +++++ .../inspections/lint/ConvertToDpQuickFix.java | 127 ++++++++++ .../android/inspections/lint/FakeNode.java | 200 ++++++++++++++++ .../lint/InefficientWeightQuickFix.java | 54 +++++ .../inspections/lint/IntellijLintClient.java | 6 + .../lint/IntellijLintConfiguration.java | 43 ++++ .../lint/RemoveAttributeQuickFix.java | 33 +++ .../lint/RemoveUselessViewQuickFix.java | 58 +++++ .../lint/SetAttributeQuickFix.java | 74 ++++++ .../lint/SetScrollViewSizeQuickFix.java | 50 ++++ .../inspections/lint/TypographyQuickFix.java | 67 ++++++ .../AndroidAddStringResourceAction.java | 14 +- .../testData/lint/adapterViewChildren.xml | 9 + .../android/testData/lint/baselineWeights.xml | 7 + .../testData/lint/baselineWeights_after.xml | 7 + .../testData/lint/contentDescription.xml | 11 + .../testData/lint/contentDescription1.xml | 11 + .../lint/contentDescription_after.xml | 11 + plugins/android/testData/lint/convertToDp.xml | 6 + .../testData/lint/convertToDp_after.xml | 6 + .../android/testData/lint/duplicatedIds.xml | 17 ++ plugins/android/testData/lint/editText.xml | 6 + .../android/testData/lint/editText_after.xml | 6 + .../android/testData/lint/exportedService.xml | 9 + .../testData/lint/exportedService_after.xml | 9 + .../testData/lint/hardcodedQuickfix.xml | 12 + .../testData/lint/hardcodedQuickfix1.xml | 12 + .../lint/hardcodedQuickfix1_after.xml | 12 + .../testData/lint/hardcodedQuickfix_after.xml | 12 + .../testData/lint/inefficientWeight.xml | 12 + .../testData/lint/inefficientWeight_after.xml | 12 + .../android/testData/lint/missingPrefix.xml | 12 + .../android/testData/lint/missingPrefix1.xml | 12 + .../testData/lint/missingPrefix1_after.xml | 12 + .../testData/lint/missingPrefix_after.xml | 12 + .../testData/lint/obsoleteLayoutParams.xml | 6 + .../lint/obsoleteLayoutParams_after.xml | 6 + .../testData/lint/scrollViewChildren.xml | 10 + .../android/testData/lint/scrollViewSize.xml | 8 + .../testData/lint/scrollViewSize_after.xml | 8 + .../testData/lint/typographyDashes.xml | 4 + .../testData/lint/typographyDashes_after.xml | 4 + .../testData/lint/typographyQuotes.xml | 5 + .../testData/lint/typographyQuotes_after.xml | 5 + plugins/android/testData/lint/uselessLeaf.xml | 6 + .../testData/lint/uselessLeaf_after.xml | 5 + .../android/testData/lint/uselessParent.xml | 8 + .../jetbrains/android/AndroidLintTest.java | 217 ++++++++++++++++++ 56 files changed, 1764 insertions(+), 81 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/AndroidAddStringResourceQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintUtil.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/ConvertToDpQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/FakeNode.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/InefficientWeightQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintConfiguration.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/RemoveAttributeQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/RemoveUselessViewQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java create mode 100644 plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java create mode 100644 plugins/android/testData/lint/adapterViewChildren.xml create mode 100644 plugins/android/testData/lint/baselineWeights.xml create mode 100644 plugins/android/testData/lint/baselineWeights_after.xml create mode 100644 plugins/android/testData/lint/contentDescription.xml create mode 100644 plugins/android/testData/lint/contentDescription1.xml create mode 100644 plugins/android/testData/lint/contentDescription_after.xml create mode 100644 plugins/android/testData/lint/convertToDp.xml create mode 100644 plugins/android/testData/lint/convertToDp_after.xml create mode 100644 plugins/android/testData/lint/duplicatedIds.xml create mode 100644 plugins/android/testData/lint/editText.xml create mode 100644 plugins/android/testData/lint/editText_after.xml create mode 100644 plugins/android/testData/lint/exportedService.xml create mode 100644 plugins/android/testData/lint/exportedService_after.xml create mode 100644 plugins/android/testData/lint/hardcodedQuickfix.xml create mode 100644 plugins/android/testData/lint/hardcodedQuickfix1.xml create mode 100644 plugins/android/testData/lint/hardcodedQuickfix1_after.xml create mode 100644 plugins/android/testData/lint/hardcodedQuickfix_after.xml create mode 100644 plugins/android/testData/lint/inefficientWeight.xml create mode 100644 plugins/android/testData/lint/inefficientWeight_after.xml create mode 100644 plugins/android/testData/lint/missingPrefix.xml create mode 100644 plugins/android/testData/lint/missingPrefix1.xml create mode 100644 plugins/android/testData/lint/missingPrefix1_after.xml create mode 100644 plugins/android/testData/lint/missingPrefix_after.xml create mode 100644 plugins/android/testData/lint/obsoleteLayoutParams.xml create mode 100644 plugins/android/testData/lint/obsoleteLayoutParams_after.xml create mode 100644 plugins/android/testData/lint/scrollViewChildren.xml create mode 100644 plugins/android/testData/lint/scrollViewSize.xml create mode 100644 plugins/android/testData/lint/scrollViewSize_after.xml create mode 100644 plugins/android/testData/lint/typographyDashes.xml create mode 100644 plugins/android/testData/lint/typographyDashes_after.xml create mode 100644 plugins/android/testData/lint/typographyQuotes.xml create mode 100644 plugins/android/testData/lint/typographyQuotes_after.xml create mode 100644 plugins/android/testData/lint/uselessLeaf.xml create mode 100644 plugins/android/testData/lint/uselessLeaf_after.xml create mode 100644 plugins/android/testData/lint/uselessParent.xml create mode 100644 plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 2b6ad57b277f..4ed608cd7172 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -307,4 +307,19 @@ android.export.package.run.proguard.label=Run &ProGuard android.export.package.proguad.config.label=C&onfig file path\: android.extract.package.specify.proguard.cfg.path.error=Please specify ProGuard config file path android.inspections.lint.name=Android Lint Validation -android.lint.quickfixes.family=Android Lint Quick Fixes \ No newline at end of file +android.lint.quickfixes.family=Android Lint Quick Fixes +android.lint.inspections.add.content.description=Add 'contentDescription' attribute +android.lint.inspections.scroll.view.children=ScrollView element can have only one child +android.lint.inspections.deprecated=Deprecated XML elements +android.lint.inspections.missing.prefix=Missing android XML namespace +android.lint.inspections.adapter.view.children=AdapterView element cannot have children +android.lint.inspections.add.android.prefix=Add android prefix +android.lint.inspections.replace.with.zero.dp=Replace size attribute with 0dp +android.lint.inspections.set.baseline.attribute=Set 'baselineAligned' attribute +android.lint.inspections.remove.attribute=Remove attribute +android.lint.inspections.convert.to.dp=Convert to \\"dp\\"... +android.lint.inspections.set.to.wrap.content=Replace size attribute with 'wrap_content' +android.lint.inspections.add.permission.attribute=Add 'permission' attribute +android.lint.inspections.add.input.type.attribute=Add 'inputType' attribute +android.lint.inspections.remove.unnecessary.view=Remove unnecessary view +android.lint.inspections.replace.with.suggested.characters=Replace with suggested characters \ No newline at end of file diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java new file mode 100644 index 000000000000..67b4c390ad08 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AddMissingPrefixQuickFix.java @@ -0,0 +1,72 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.sdklib.SdkConstants; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlFile; +import com.intellij.psi.xml.XmlTag; +import com.intellij.xml.XmlExtension; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; + +/** + * @author Eugene.Kudelevsky + */ +class AddMissingPrefixQuickFix implements AndroidLintQuickFix { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.AddMissingPrefixQuickFix"); + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlAttribute attribute = PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class, false); + if (attribute == null) { + return; + } + + final XmlTag tag = attribute.getParent(); + if (tag == null) { + LOG.debug("tag is null"); + return; + } + + String androidNsPrefix = tag.getPrefixByNamespace(SdkConstants.NS_RESOURCES); + + if (androidNsPrefix == null) { + final PsiFile file = tag.getContainingFile(); + final XmlExtension extension = XmlExtension.getExtension(file); + + if (extension == null) { + LOG.debug("Cannot get XmlExtension for file + " + file); + return; + } + + if (!(file instanceof XmlFile)) { + LOG.debug(file + " is not XmlFile"); + return; + } + + final XmlFile xmlFile = (XmlFile)file; + final String defaultPrefix = "android"; + extension.insertNamespaceDeclaration(xmlFile, null, Collections.singleton(SdkConstants.NS_RESOURCES), defaultPrefix, null); + androidNsPrefix = defaultPrefix; + } + attribute.setName(androidNsPrefix + ':' + attribute.getLocalName()); + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + return PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class, false) != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.add.android.prefix"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidAddStringResourceQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidAddStringResourceQuickFix.java new file mode 100644 index 000000000000..0a614f88a0d4 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidAddStringResourceQuickFix.java @@ -0,0 +1,47 @@ +package org.jetbrains.android.inspections.lint; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.android.intentions.AndroidAddStringResourceAction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidAddStringResourceQuickFix extends AndroidAddStringResourceAction { + private final PsiElement myStartElement; + + public AndroidAddStringResourceQuickFix(@NotNull PsiElement startElement) { + myStartElement = startElement; + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + return getAttributeValue(myStartElement) != null; + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + invokeIntention(project, editor, file, null); + } + + public void invokeIntention(Project project, Editor editor, PsiFile file, String resName) { + final XmlAttributeValue attributeValue = getAttributeValue(myStartElement); + if (attributeValue != null) { + doInvoke(project, editor, file, resName, attributeValue); + } + } + + @Nullable + private static XmlAttributeValue getAttributeValue(@NotNull PsiElement element) { + final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class); + return attribute != null ? attribute.getValueElement() : null; + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java index 8e49234ba547..b2a909b18df7 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintExternalAnnotator.java @@ -7,11 +7,11 @@ import com.android.tools.lint.client.api.Lint; import com.android.tools.lint.detector.api.Issue; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionProfile; -import com.intellij.codeInspection.ex.CustomEditInspectionToolsSettingsAction; import com.intellij.codeInspection.ex.DisableInspectionToolAction; -import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.codeInspection.ex.EditInspectionToolsSettingsAction; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.ExternalAnnotator; @@ -22,7 +22,10 @@ import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.PsiElement; @@ -30,6 +33,7 @@ import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidRootUtil; +import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -62,7 +66,7 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator pair = getHighlighLevelAndInspection(issue, file); + final Pair pair = AndroidLintUtil.getHighlighLevelAndInspection(issue, file); if (pair == null) { continue; } final AndroidLintInspectionBase inspection = pair.getFirst(); final HighlightDisplayLevel displayLevel = pair.getSecond(); - + final Annotation annotation = createAnnotation(holder, message, range, displayLevel); if (inspection != null) { final HighlightDisplayKey key = HighlightDisplayKey.find(inspection.getShortName()); - + if (key != null) { - annotation.registerFix(new MyDisableInspectionFix(key)); - annotation.registerFix(new CustomEditInspectionToolsSettingsAction(key, new Computable() { - @Override - public String compute() { - return "Edit '" + inspection.getDisplayName() + "' inspection settings"; + final PsiElement startElement = file.findElementAt(range.getStartOffset()); + final PsiElement endElement = file.findElementAt(range.getEndOffset() - 1); + + if (startElement != null && endElement != null) { + for (AndroidLintQuickFix fix : inspection.getQuickFixes(message)) { + if (fix.isApplicable(startElement, endElement, false)) { + annotation.registerFix(new MyFixingIntention(fix, startElement, endElement)); + } } - })); + + for (IntentionAction intention : inspection.getIntentions(startElement, endElement)) { + annotation.registerFix(intention); + } + } + + annotation.registerFix(new MyDisableInspectionFix(key)); + annotation.registerFix(new MyEditInspectionToolsSettingsAction(key, inspection)); } } } @@ -189,36 +203,6 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator getHighlighLevelAndInspection(@NotNull Issue issue, - @NotNull PsiElement context) { - final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(issue); - if (inspectionShortName == null) { - return null; - } - - final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName); - if (key == null) { - return null; - } - - final InspectionProfile profile = InspectionProjectProfileManager.getInstance(context.getProject()).getInspectionProfile(); - if (!profile.isToolEnabled(key, context)) { - return null; - } - - final InspectionToolWrapper toolWrapper = - (InspectionToolWrapper)profile.getInspectionTool(inspectionShortName, context); - if (toolWrapper == null) { - return null; - } - - final AndroidLintInspectionBase inspection = (AndroidLintInspectionBase)toolWrapper.getTool(); - final HighlightDisplayLevel errorLevel = profile.getErrorLevel(key, context); - return new Pair(inspection, - errorLevel != null ? errorLevel : HighlightDisplayLevel.WARNING); - } - private static class MyDisableInspectionFix implements IntentionAction, Iconable { private final DisableInspectionToolAction myDisableInspectionToolAction; @@ -258,4 +242,90 @@ public class AndroidLintExternalAnnotator extends ExternalAnnotator getIssues() { @@ -128,13 +125,21 @@ class AndroidLintGlobalInspectionContext implements GlobalInspectionContextExten private final Project myProject; private final Map>> myProblemMap; private final AnalysisScope myScope; + private final Collection myIssues; private MyLintClient(@NotNull Project project, @NotNull Map>> problemMap, - @NotNull AnalysisScope scope) { + @NotNull AnalysisScope scope, + @NotNull Collection issues) { myProject = project; myProblemMap = problemMap; myScope = scope; + myIssues = issues; + } + + @Override + public Configuration getConfiguration(com.android.tools.lint.detector.api.Project project) { + return new IntellijLintConfiguration(myIssues); } @Override @@ -248,6 +253,9 @@ class AndroidLintGlobalInspectionContext implements GlobalInspectionContextExten @Override public List getJavaSourceFolders(com.android.tools.lint.detector.api.Project project) { final Module module = findModuleForLintProject(myProject, project); + if (module == null) { + return Collections.emptyList(); + } final VirtualFile[] sourceRoots = ModuleRootManager.getInstance(module).getSourceRoots(false); final List result = new ArrayList(sourceRoots.length); diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java index 5cc3fe5fa98d..dfec9b262f16 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionBase.java @@ -5,11 +5,13 @@ import com.android.tools.lint.detector.api.Issue; import com.android.tools.lint.detector.api.Severity; import com.intellij.analysis.AnalysisScope; import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -34,12 +36,12 @@ import java.util.Map; /** * @author Eugene.Kudelevsky */ -abstract class AndroidLintInspectionBase extends GlobalInspectionTool { +public abstract class AndroidLintInspectionBase extends GlobalInspectionTool { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.AndroidLintInspectionBase"); private static final Map ourIssue2InspectionShortName = new HashMap(); - private final Issue myIssue; + protected final Issue myIssue; private final String[] myGroupPath; private final String myDisplayName; @@ -58,6 +60,29 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { addIssue(issue, getShortName()); } + @NotNull + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return AndroidLintQuickFix.EMPTY_ARRAY; + } + + @NotNull + protected IntentionAction[] getIntentions(@NotNull PsiElement startElement, @NotNull PsiElement endElement) { + return IntentionAction.EMPTY_ARRAY; + } + + @NotNull + private LocalQuickFix[] getLocalQuickFixes(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull String message) { + final AndroidLintQuickFix[] fixes = getQuickFixes(message); + final LocalQuickFix[] result = new LocalQuickFix[fixes.length]; + + for (int i = 0; i < fixes.length; i++) { + if (fixes[i].isApplicable(startElement, endElement, true)) { + result[i] = new MyLocalQuickFix(fixes[i]); + } + } + return result; + } + @Override public void runInspection(AnalysisScope scope, final InspectionManager manager, @@ -81,7 +106,7 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { for (final Map.Entry> entry : file2ProblemList.entrySet()) { final File file = entry.getKey(); final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); - + if (vFile == null) { continue; } @@ -104,9 +129,9 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { } @NotNull - private static ProblemDescriptor[] computeProblemDescriptors(@NotNull PsiFile psiFile, - @NotNull InspectionManager manager, - @NotNull List problems) { + private ProblemDescriptor[] computeProblemDescriptors(@NotNull PsiFile psiFile, + @NotNull InspectionManager manager, + @NotNull List problems) { final List result = new ArrayList(); for (ProblemData problemData : problems) { @@ -128,9 +153,9 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { } } } - + if (f != null) { - result.add(manager.createProblemDescriptor(f, message, false, LocalQuickFix.EMPTY_ARRAY, + result.add(manager.createProblemDescriptor(f, message, false, getLocalQuickFixes(f, f, message), ProblemHighlightType.GENERIC_ERROR_OR_WARNING)); } } @@ -140,7 +165,8 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { if (startElement != null && endElement != null) { result.add(manager.createProblemDescriptor(startElement, endElement, message + "#loc", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)); + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false, + getLocalQuickFixes(startElement, endElement, message))); } } } @@ -218,7 +244,7 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { @Override public boolean isEnabledByDefault() { - return true; + return myIssue.isEnabledByDefault(); } @NotNull @@ -254,4 +280,29 @@ abstract class AndroidLintInspectionBase extends GlobalInspectionTool { return null; } } + + static class MyLocalQuickFix implements LocalQuickFix { + private final AndroidLintQuickFix myLintQuickFix; + + MyLocalQuickFix(@NotNull AndroidLintQuickFix lintQuickFix) { + myLintQuickFix = lintQuickFix; + } + + @NotNull + @Override + public String getName() { + return myLintQuickFix.getName(); + } + + @NotNull + @Override + public String getFamilyName() { + return AndroidBundle.message("android.lint.quickfixes.family"); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + myLintQuickFix.apply(descriptor.getStartElement(), descriptor.getEndElement(), null); + } + } } diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java index 2c44d975a613..8beeef803494 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintInspectionToolProvider.java @@ -1,7 +1,13 @@ package org.jetbrains.android.inspections.lint; import com.android.tools.lint.checks.*; +import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.LintConstants; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.InspectionToolProvider; +import com.intellij.psi.PsiElement; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; /** * @author Eugene.Kudelevsky @@ -9,11 +15,11 @@ import com.intellij.codeInspection.InspectionToolProvider; public class AndroidLintInspectionToolProvider implements InspectionToolProvider { @Override public Class[] getInspectionClasses() { - return new Class[] { + return new Class[]{ AndroidLintContentDescriptionInspection.class, AndroidLintAdapterViewChildrenInspection.class, AndroidLintScrollViewCountInspection.class, - AndroidLintDeprecatedInspection.class, + //AndroidLintDeprecatedInspection.class, AndroidLintMissingPrefixInspection.class, AndroidLintDuplicateIdsInspection.class, AndroidLintGridLayoutInspection.class, @@ -169,29 +175,44 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintContentDescriptionInspection() { super("Missing content description", AccessibilityDetector.ISSUE); } + + @NotNull + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{ + new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.content.description"), + LintConstants.ATTR_CONTENT_DESCRIPTION, null) + }; + } } public static class AndroidLintAdapterViewChildrenInspection extends AndroidLintInspectionBase { public AndroidLintAdapterViewChildrenInspection() { - super("AdapterView element cannot have children", ChildCountDetector.ADAPTERVIEW_ISSUE); + super(AndroidBundle.message("android.lint.inspections.adapter.view.children"), ChildCountDetector.ADAPTERVIEW_ISSUE); } } public static class AndroidLintScrollViewCountInspection extends AndroidLintInspectionBase { public AndroidLintScrollViewCountInspection() { - super("ScrollView element can have only one child", ChildCountDetector.SCROLLVIEW_ISSUE); + super(AndroidBundle.message("android.lint.inspections.scroll.view.children"), ChildCountDetector.SCROLLVIEW_ISSUE); } } - public static class AndroidLintDeprecatedInspection extends AndroidLintInspectionBase { + // it seems we don't need it because we have our own 'deprecated api' inspection + /*public static class AndroidLintDeprecatedInspection extends AndroidLintInspectionBase { public AndroidLintDeprecatedInspection() { - super("Deprecated XML elements", DeprecationDetector.ISSUE); + super(AndroidBundle.message("android.lint.inspections.deprecated"), DeprecationDetector.ISSUE); } - } + }*/ public static class AndroidLintMissingPrefixInspection extends AndroidLintInspectionBase { public AndroidLintMissingPrefixInspection() { - super("Missing android XML namespace", DetectMissingPrefix.MISSING_NAMESPACE); + super(AndroidBundle.message("android.lint.inspections.missing.prefix"), DetectMissingPrefix.MISSING_NAMESPACE); + } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{new AddMissingPrefixQuickFix()}; } } @@ -211,12 +232,26 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintHardcodedTextInspection() { super("Hardcoded text", HardcodedValuesDetector.ISSUE); } + + @NotNull + @Override + protected IntentionAction[] getIntentions(@NotNull final PsiElement startElement, @NotNull PsiElement endElement) { + return new IntentionAction[]{new AndroidAddStringResourceQuickFix(startElement)}; + } } public static class AndroidLintInefficientWeightInspection extends AndroidLintInspectionBase { public AndroidLintInefficientWeightInspection() { super("Inefficient layout weight", InefficientWeightDetector.INEFFICIENT_WEIGHT); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{ + new InefficientWeightQuickFix() + }; + } } public static class AndroidLintNestedWeightsInspection extends AndroidLintInspectionBase { @@ -229,6 +264,15 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintDisableBaselineAlignmentInspection() { super("Missing baselineAligned attribute", InefficientWeightDetector.BASELINE_WEIGHTS); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{ + new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.set.baseline.attribute"), + LintConstants.ATTR_BASELINE_ALIGNED, "false") + }; + } } public static class AndroidLintManifestOrderInspection extends AndroidLintInspectionBase { @@ -253,6 +297,12 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintObsoleteLayoutParamInspection() { super("Obsolete layout params", ObsoleteLayoutParamsDetector.ISSUE); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{new RemoveAttributeQuickFix()}; + } } public static class AndroidLintProguardInspection extends AndroidLintInspectionBase { @@ -265,18 +315,39 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintPxUsageInspection() { super("Using 'px' dimension", PxUsageDetector.ISSUE); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{new ConvertToDpQuickFix()}; + } } public static class AndroidLintScrollViewSizeInspection extends AndroidLintInspectionBase { public AndroidLintScrollViewSizeInspection() { super("ScrollView size validation", ScrollViewChildDetector.ISSUE); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{new SetScrollViewSizeQuickFix()}; + } } public static class AndroidLintExportedServiceInspection extends AndroidLintInspectionBase { public AndroidLintExportedServiceInspection() { super("Exported service does not require permission", SecurityDetector.EXPORTED_SERVICE); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{ + new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.permission.attribute"), + LintConstants.ATTR_PERMISSION, null) + }; + } } public static class AndroidLintGrantAllUrisInspection extends AndroidLintInspectionBase { @@ -295,6 +366,15 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintTextFieldsInspection() { super("Text field missing inputType or hint settings", TextFieldDetector.ISSUE); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{ + new SetAttributeQuickFix(AndroidBundle.message("android.lint.inspections.add.input.type.attribute"), + LintConstants.ATTR_INPUT_TYPE, null) + }; + } } public static class AndroidLintTooManyViewsInspection extends AndroidLintInspectionBase { @@ -309,31 +389,31 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider } } - public static class AndroidLintTypographyDashesInspection extends AndroidLintInspectionBase { + public static class AndroidLintTypographyDashesInspection extends AndroidLintTypographyInspectionBase { public AndroidLintTypographyDashesInspection() { super("Hyphen can be replaced by dash", TypographyDetector.DASHES); } } - public static class AndroidLintTypographyQuotesInspection extends AndroidLintInspectionBase { + public static class AndroidLintTypographyQuotesInspection extends AndroidLintTypographyInspectionBase { public AndroidLintTypographyQuotesInspection() { super("Straight quotes can be replaced by curvy quotes", TypographyDetector.QUOTES); } } - public static class AndroidLintTypographyFractionsInspection extends AndroidLintInspectionBase { + public static class AndroidLintTypographyFractionsInspection extends AndroidLintTypographyInspectionBase { public AndroidLintTypographyFractionsInspection() { super("Fraction string can be replaced with fraction character", TypographyDetector.FRACTIONS); } } - public static class AndroidLintTypographyEllipsisInspection extends AndroidLintInspectionBase { + public static class AndroidLintTypographyEllipsisInspection extends AndroidLintTypographyInspectionBase { public AndroidLintTypographyEllipsisInspection() { super("Ellipsis string can be replaced with ellipsis character", TypographyDetector.ELLIPSIS); } } - public static class AndroidLintTypographyOtherInspection extends AndroidLintInspectionBase { + public static class AndroidLintTypographyOtherInspection extends AndroidLintTypographyInspectionBase { public AndroidLintTypographyOtherInspection() { super("Other typographical problems", TypographyDetector.OTHER); } @@ -355,5 +435,23 @@ public class AndroidLintInspectionToolProvider implements InspectionToolProvider public AndroidLintUselessLeafInspection() { super("Useless leaf layout", UselessViewDetector.USELESS_LEAF); } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[]{new RemoveUselessViewQuickFix(myIssue)}; + } + } + + private static class AndroidLintTypographyInspectionBase extends AndroidLintInspectionBase { + public AndroidLintTypographyInspectionBase(String displayName, Issue issue) { + super(displayName, issue); + } + + @NotNull + @Override + protected AndroidLintQuickFix[] getQuickFixes(@NotNull String message) { + return new AndroidLintQuickFix[] {new TypographyQuickFix(myIssue, message)}; + } } } diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintQuickFix.java new file mode 100644 index 000000000000..f029cb923057 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintQuickFix.java @@ -0,0 +1,20 @@ +package org.jetbrains.android.inspections.lint; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +interface AndroidLintQuickFix { + AndroidLintQuickFix[] EMPTY_ARRAY = new AndroidLintQuickFix[0]; + + void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor); + + boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode); + + @NotNull + String getName(); +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintUtil.java b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintUtil.java new file mode 100644 index 000000000000..95767ccf261b --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/AndroidLintUtil.java @@ -0,0 +1,57 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.tools.lint.detector.api.Issue; +import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.ex.InspectionToolWrapper; +import com.intellij.openapi.util.Pair; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +class AndroidLintUtil { + @NonNls static final String ATTR_VALUE_VERTICAL = "vertical"; + @NonNls static final String ATTR_VALUE_WRAP_CONTENT = "wrap_content"; + @NonNls static final String ATTR_LAYOUT_HEIGHT = "layout_height"; + @NonNls static final String ATTR_LAYOUT_WIDTH = "layout_width"; + @NonNls static final String ATTR_ORIENTATION = "orientation"; + + private AndroidLintUtil() { + } + + @Nullable + static Pair getHighlighLevelAndInspection(@NotNull Issue issue, + @NotNull PsiElement context) { + final String inspectionShortName = AndroidLintInspectionBase.getInspectionShortNameByIssue(issue); + if (inspectionShortName == null) { + return null; + } + + final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionShortName); + if (key == null) { + return null; + } + + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(context.getProject()).getInspectionProfile(); + if (!profile.isToolEnabled(key, context)) { + return null; + } + + final InspectionToolWrapper toolWrapper = + (InspectionToolWrapper)profile.getInspectionTool(inspectionShortName, context); + if (toolWrapper == null) { + return null; + } + + final AndroidLintInspectionBase inspection = (AndroidLintInspectionBase)toolWrapper.getTool(); + final HighlightDisplayLevel errorLevel = profile.getErrorLevel(key, context); + return new Pair(inspection, + errorLevel != null ? errorLevel : HighlightDisplayLevel.WARNING); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/ConvertToDpQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/ConvertToDpQuickFix.java new file mode 100644 index 000000000000..e0190e1bc360 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/ConvertToDpQuickFix.java @@ -0,0 +1,127 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.resources.Density; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.ui.Messages; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author Eugene.Kudelevsky + */ +class ConvertToDpQuickFix implements AndroidLintQuickFix { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.inspections.lint.ConvertToDpQuickFix"); + private static final Pattern PX_ATTR_VALUE_PATTERN = Pattern.compile("(\\d+)px"); + + private static int ourPrevDpi = Density.DEFAULT_DENSITY; + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + if (editor == null) { + return; + } + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + final List densities = new ArrayList(); + + for (Density density : Density.values()) { + if (density.getDpiValue() > 0) { + densities.add(density); + } + } + + final String[] densityPresentableNames = new String[densities.size()]; + + String defaultValue = null; + String initialValue = null; + + for (int i = 0; i < densities.size(); i++) { + final Density density = densities.get(i); + densityPresentableNames[i] = getLabelForDensity(density); + + final int dpi = density.getDpiValue(); + if (dpi == 0) { + continue; + } + + if (dpi == ourPrevDpi) { + initialValue = densityPresentableNames[i]; + } + else if (dpi == Density.DEFAULT_DENSITY) { + defaultValue = densityPresentableNames[i]; + } + } + + if (initialValue == null) { + initialValue = defaultValue; + } + if (initialValue == null) { + return; + } + + final int dpi; + + if (ApplicationManager.getApplication().isUnitTestMode()) { + dpi = Density.DEFAULT_DENSITY; + } + else { + final int selectedIndex = Messages + .showChooseDialog("What is the screen density the current px value works with?", "Choose density", densityPresentableNames, + initialValue, null); + if (selectedIndex < 0) { + return; + } + dpi = densities.get(selectedIndex).getDpiValue(); + } + + //noinspection AssignmentToStaticFieldFromInstanceMethod + ourPrevDpi = dpi; + + for (XmlAttribute attribute : tag.getAttributes()) { + final String value = attribute.getValue(); + + if (value.endsWith("px")) { + final Matcher matcher = PX_ATTR_VALUE_PATTERN.matcher(value); + + if (matcher.matches()) { + final String numberString = matcher.group(1); + try { + final int px = Integer.parseInt(numberString); + final int dp = px * 160 / dpi; + attribute.setValue(Integer.toString(dp) + "dp"); + } + catch (NumberFormatException nufe) { + LOG.error(nufe); + } + } + } + } + } + + @NotNull + private static String getLabelForDensity(@NotNull Density density) { + return String.format("%1$s (%2$d)", density.getShortDisplayValue(), density.getDpiValue()); + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + return !inBatchMode && PsiTreeUtil.getParentOfType(startElement, XmlTag.class) != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.convert.to.dp"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/FakeNode.java b/plugins/android/src/org/jetbrains/android/inspections/lint/FakeNode.java new file mode 100644 index 000000000000..8504add151a7 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/FakeNode.java @@ -0,0 +1,200 @@ +package org.jetbrains.android.inspections.lint; + +import org.jetbrains.annotations.NotNull; +import org.w3c.dom.*; + +/** + * @author Eugene.Kudelevsky + */ +class FakeNode implements Node { + private final String myText; + + FakeNode(@NotNull String text) { + myText = text; + } + + @Override + public String getNodeName() { + throw new UnsupportedOperationException(); + } + + @Override + public String getNodeValue() throws DOMException { + return myText; + } + + @Override + public void setNodeValue(String nodeValue) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public short getNodeType() { + throw new UnsupportedOperationException(); + } + + @Override + public Node getParentNode() { + throw new UnsupportedOperationException(); + } + + @Override + public NodeList getChildNodes() { + throw new UnsupportedOperationException(); + } + + @Override + public Node getFirstChild() { + throw new UnsupportedOperationException(); + } + + @Override + public Node getLastChild() { + throw new UnsupportedOperationException(); + } + + @Override + public Node getPreviousSibling() { + throw new UnsupportedOperationException(); + } + + @Override + public Node getNextSibling() { + throw new UnsupportedOperationException(); + } + + @Override + public NamedNodeMap getAttributes() { + throw new UnsupportedOperationException(); + } + + @Override + public Document getOwnerDocument() { + throw new UnsupportedOperationException(); + } + + @Override + public Node insertBefore(Node newChild, Node refChild) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public Node replaceChild(Node newChild, Node oldChild) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public Node removeChild(Node oldChild) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public Node appendChild(Node newChild) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasChildNodes() { + throw new UnsupportedOperationException(); + } + + @Override + public Node cloneNode(boolean deep) { + throw new UnsupportedOperationException(); + } + + @Override + public void normalize() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSupported(String feature, String version) { + throw new UnsupportedOperationException(); + } + + @Override + public String getNamespaceURI() { + throw new UnsupportedOperationException(); + } + + @Override + public String getPrefix() { + throw new UnsupportedOperationException(); + } + + @Override + public void setPrefix(String prefix) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public String getLocalName() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean hasAttributes() { + throw new UnsupportedOperationException(); + } + + @Override + public String getBaseURI() { + throw new UnsupportedOperationException(); + } + + @Override + public short compareDocumentPosition(Node other) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public String getTextContent() throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public void setTextContent(String textContent) throws DOMException { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isSameNode(Node other) { + throw new UnsupportedOperationException(); + } + + @Override + public String lookupPrefix(String namespaceURI) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isDefaultNamespace(String namespaceURI) { + throw new UnsupportedOperationException(); + } + + @Override + public String lookupNamespaceURI(String prefix) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEqualNode(Node arg) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getFeature(String feature, String version) { + throw new UnsupportedOperationException(); + } + + @Override + public Object setUserData(String key, Object data, UserDataHandler handler) { + throw new UnsupportedOperationException(); + } + + @Override + public Object getUserData(String key) { + throw new UnsupportedOperationException(); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/InefficientWeightQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/InefficientWeightQuickFix.java new file mode 100644 index 000000000000..7d2c4e6ee443 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/InefficientWeightQuickFix.java @@ -0,0 +1,54 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.sdklib.SdkConstants; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +class InefficientWeightQuickFix implements AndroidLintQuickFix { + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return; + } + + final XmlTag parentTag = tag.getParentTag(); + if (parentTag == null) { + return; + } + String attrName; + + if (AndroidLintUtil.ATTR_VALUE_VERTICAL + .equals(parentTag.getAttributeValue(AndroidLintUtil.ATTR_ORIENTATION, SdkConstants.NS_RESOURCES))) { + attrName = AndroidLintUtil.ATTR_LAYOUT_HEIGHT; + } + else { + attrName = AndroidLintUtil.ATTR_LAYOUT_WIDTH; + } + tag.setAttribute(attrName, SdkConstants.NS_RESOURCES, "0dp"); + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return false; + } + return tag.getParentTag() != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.replace.with.zero.dp"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintClient.java b/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintClient.java index cab3907e7252..528970c87f64 100644 --- a/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintClient.java +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintClient.java @@ -1,6 +1,7 @@ package org.jetbrains.android.inspections.lint; import com.android.tools.lint.PositionXmlParser; +import com.android.tools.lint.client.api.Configuration; import com.android.tools.lint.client.api.IDomParser; import com.android.tools.lint.client.api.LintClient; import com.android.tools.lint.detector.api.Context; @@ -43,6 +44,11 @@ class IntellijLintClient extends LintClient implements Disposable { myState = state; } + @Override + public Configuration getConfiguration(com.android.tools.lint.detector.api.Project project) { + return new IntellijLintConfiguration(myState.getIssues()); + } + @Override public void report(Context context, Issue issue, Location location, String message, Object data) { if (location != null) { diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintConfiguration.java b/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintConfiguration.java new file mode 100644 index 000000000000..d24cede931b2 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/IntellijLintConfiguration.java @@ -0,0 +1,43 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.tools.lint.client.api.Configuration; +import com.android.tools.lint.detector.api.Context; +import com.android.tools.lint.detector.api.Issue; +import com.android.tools.lint.detector.api.Location; +import com.android.tools.lint.detector.api.Severity; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.Set; + +/** + * @author Eugene.Kudelevsky + */ +class IntellijLintConfiguration extends Configuration { + private final Set myIssueSet; + + IntellijLintConfiguration(@NotNull Collection issueSet) { + myIssueSet = new HashSet(issueSet); + } + + @Override + public void ignore(Context context, Issue issue, Location location, String message, Object data) { + throw new UnsupportedOperationException(); + } + + @Override + public void setSeverity(Issue issue, Severity severity) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isEnabled(Issue issue) { + return myIssueSet.contains(issue); + } + + @Override + public Severity getSeverity(Issue issue) { + return Severity.WARNING; + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveAttributeQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveAttributeQuickFix.java new file mode 100644 index 000000000000..b9d01eaba5e9 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveAttributeQuickFix.java @@ -0,0 +1,33 @@ +package org.jetbrains.android.inspections.lint; + +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +class RemoveAttributeQuickFix implements AndroidLintQuickFix { + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlAttribute attribute = PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class); + if (attribute != null) { + attribute.getParent().setAttribute(attribute.getName(), null); + } + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + return PsiTreeUtil.getParentOfType(startElement, XmlAttribute.class) != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.remove.attribute"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveUselessViewQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveUselessViewQuickFix.java new file mode 100644 index 000000000000..3c429b7fe435 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/RemoveUselessViewQuickFix.java @@ -0,0 +1,58 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.tools.lint.checks.UselessViewDetector; +import com.android.tools.lint.detector.api.Issue; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +public class RemoveUselessViewQuickFix implements AndroidLintQuickFix { + private final Issue myIssue; + + public RemoveUselessViewQuickFix(@NotNull Issue issue) { + myIssue = issue; + } + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return; + } + + final XmlTag parentTag = tag.getParentTag(); + if (parentTag == null) { + return; + } + + if (myIssue.getId().equals(UselessViewDetector.USELESS_LEAF.getId())) { + tag.delete(); + } + else { + assert false; + // todo: implement + } + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return false; + } + return tag.getParentTag() != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.remove.unnecessary.view"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java new file mode 100644 index 000000000000..4143549ef208 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/SetAttributeQuickFix.java @@ -0,0 +1,74 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.sdklib.SdkConstants; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlAttribute; +import com.intellij.psi.xml.XmlAttributeValue; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +class SetAttributeQuickFix implements AndroidLintQuickFix { + + private final String myName; + private final String myAttributeName; + private final String myValue; + + SetAttributeQuickFix(@NotNull String name, @NotNull String attributeName, @Nullable String value) { + super(); + myName = name; + myAttributeName = attributeName; + myValue = value; + } + + @NotNull + @Override + public String getName() { + return myName; + } + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class, false); + + if (tag == null) { + return; + } + final XmlAttribute attribute = tag.setAttribute(myAttributeName, SdkConstants.NS_RESOURCES, ""); + + if (attribute != null) { + if (myValue != null) { + attribute.setValue(myValue); + } + if (editor != null) { + final XmlAttributeValue valueElement = attribute.getValueElement(); + final TextRange valueTextRange = attribute.getValueTextRange(); + + if (valueElement != null && valueTextRange != null) { + final int valueElementStart = valueElement.getTextRange().getStartOffset(); + editor.getCaretModel().moveToOffset(valueElementStart + valueTextRange.getStartOffset()); + + if (valueTextRange.getStartOffset() < valueTextRange.getEndOffset()) { + editor.getSelectionModel().setSelection(valueElementStart + valueTextRange.getStartOffset(), + valueElementStart + valueTextRange.getEndOffset()); + } + } + } + } + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class, false); + if (tag == null) { + return false; + } + return tag.getAttribute(myAttributeName, SdkConstants.NS_RESOURCES) == null; + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java new file mode 100644 index 000000000000..336bb9a11f61 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/SetScrollViewSizeQuickFix.java @@ -0,0 +1,50 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.sdklib.SdkConstants; +import com.android.tools.lint.detector.api.LintConstants; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlTag; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Eugene.Kudelevsky + */ +class SetScrollViewSizeQuickFix implements AndroidLintQuickFix { + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return; + } + + final XmlTag parentTag = tag.getParentTag(); + if (parentTag == null) { + return; + } + + final boolean isHorizontal = LintConstants.HORIZONTAL_SCROLL_VIEW.equals(parentTag.getName()); + final String attributeName = isHorizontal + ? AndroidLintUtil.ATTR_LAYOUT_WIDTH + : AndroidLintUtil.ATTR_LAYOUT_HEIGHT; + tag.setAttribute(attributeName, SdkConstants.NS_RESOURCES, AndroidLintUtil.ATTR_VALUE_WRAP_CONTENT); + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return false; + } + return tag.getParentTag() != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.set.to.wrap.content"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java b/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java new file mode 100644 index 000000000000..74e7e737cdc8 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/inspections/lint/TypographyQuickFix.java @@ -0,0 +1,67 @@ +package org.jetbrains.android.inspections.lint; + +import com.android.tools.lint.checks.TypographyDetector; +import com.android.tools.lint.detector.api.Issue; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlText; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Eugene.Kudelevsky + */ +class TypographyQuickFix implements AndroidLintQuickFix { + private final Issue myIssue; + private final String myMessage; + + public TypographyQuickFix(@NotNull Issue issue, @NotNull String message) { + myIssue = issue; + myMessage = message; + } + + @Override + public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @Nullable Editor editor) { + final XmlTag tag = PsiTreeUtil.getParentOfType(startElement, XmlTag.class); + if (tag == null) { + return; + } + + for (PsiElement child : tag.getChildren()) { + if (child instanceof XmlText) { + final XmlText xmlText = (XmlText)child; + final String value = xmlText.getValue(); + + if (value != null) { + final List edits = TypographyDetector.getEdits(myIssue.getId(), myMessage, new FakeNode(value)); + final StringBuilder builder = new StringBuilder(value); + + for (TypographyDetector.ReplaceEdit edit : edits) { + builder.replace(edit.offset, edit.offset + edit.length, edit.replaceWith); + } + + final String newValue = builder.toString(); + if (!newValue.equals(value)) { + xmlText.setValue(newValue); + } + } + } + } + } + + @Override + public boolean isApplicable(@NotNull PsiElement startElement, @NotNull PsiElement endElement, boolean inBatchMode) { + return PsiTreeUtil.getParentOfType(startElement, XmlTag.class) != null; + } + + @NotNull + @Override + public String getName() { + return AndroidBundle.message("android.lint.inspections.replace.with.suggested.characters"); + } +} diff --git a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java index d22ddd0c21c2..08e641d87637 100644 --- a/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java +++ b/plugins/android/src/org/jetbrains/android/intentions/AndroidAddStringResourceAction.java @@ -19,6 +19,7 @@ package org.jetbrains.android.intentions; import com.android.resources.ResourceType; import com.intellij.CommonBundle; import com.intellij.codeInsight.intention.AbstractIntentionAction; +import com.intellij.codeInsight.intention.HighPriorityAction; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.template.*; @@ -75,7 +76,7 @@ import static org.jetbrains.android.util.AndroidUtils.VIEW_CLASS_NAME; * Time: 5:02:31 PM * To change this template use File | Settings | File Templates. */ -public class AndroidAddStringResourceAction extends AbstractIntentionAction { +public class AndroidAddStringResourceAction extends AbstractIntentionAction implements HighPriorityAction { private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.intentions.AndroidAddStringResourceAction"); private static final String CONTEXT = AndroidUtils.ANDROID_PACKAGE + ".content.Context"; @@ -165,14 +166,19 @@ public class AndroidAddStringResourceAction extends AbstractIntentionAction { } static void doInvoke(Project project, Editor editor, PsiFile file, @Nullable String resName) { - final AndroidFacet facet = AndroidFacet.getInstance(file); - assert facet != null; - final PsiElement element = getPsiElement(file, editor); assert element != null; + doInvoke(project, editor, file, resName, element); + } + + protected static void doInvoke(Project project, Editor editor, PsiFile file, @Nullable String resName, PsiElement element) { String value = getStringLiteralValue(element, file); assert value != null; + + final AndroidFacet facet = AndroidFacet.getInstance(file); + assert facet != null; + value = value.replace("'", "\\'").replace("\"", "\\\""); final String aPackage = getPackage(facet); diff --git a/plugins/android/testData/lint/adapterViewChildren.xml b/plugins/android/testData/lint/adapterViewChildren.xml new file mode 100644 index 000000000000..9f92c86e6ecf --- /dev/null +++ b/plugins/android/testData/lint/adapterViewChildren.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/baselineWeights.xml b/plugins/android/testData/lint/baselineWeights.xml new file mode 100644 index 000000000000..a9bb155680e6 --- /dev/null +++ b/plugins/android/testData/lint/baselineWeights.xml @@ -0,0 +1,7 @@ + + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + + diff --git a/plugins/android/testData/lint/baselineWeights_after.xml b/plugins/android/testData/lint/baselineWeights_after.xml new file mode 100644 index 000000000000..65a523c3c9a8 --- /dev/null +++ b/plugins/android/testData/lint/baselineWeights_after.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/plugins/android/testData/lint/contentDescription.xml b/plugins/android/testData/lint/contentDescription.xml new file mode 100644 index 000000000000..f99ee50e6262 --- /dev/null +++ b/plugins/android/testData/lint/contentDescription.xml @@ -0,0 +1,11 @@ + + +geView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + /> + + diff --git a/plugins/android/testData/lint/contentDescription1.xml b/plugins/android/testData/lint/contentDescription1.xml new file mode 100644 index 000000000000..3966e0b9e16a --- /dev/null +++ b/plugins/android/testData/lint/contentDescription1.xml @@ -0,0 +1,11 @@ + + +android:contentDescription=""/> + + diff --git a/plugins/android/testData/lint/contentDescription_after.xml b/plugins/android/testData/lint/contentDescription_after.xml new file mode 100644 index 000000000000..f64caa929953 --- /dev/null +++ b/plugins/android/testData/lint/contentDescription_after.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/plugins/android/testData/lint/convertToDp.xml b/plugins/android/testData/lint/convertToDp.xml new file mode 100644 index 000000000000..6bc4c0dc8d8e --- /dev/null +++ b/plugins/android/testData/lint/convertToDp.xml @@ -0,0 +1,6 @@ + + + android:width="100px"/> + \ No newline at end of file diff --git a/plugins/android/testData/lint/convertToDp_after.xml b/plugins/android/testData/lint/convertToDp_after.xml new file mode 100644 index 000000000000..17c930637291 --- /dev/null +++ b/plugins/android/testData/lint/convertToDp_after.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/duplicatedIds.xml b/plugins/android/testData/lint/duplicatedIds.xml new file mode 100644 index 000000000000..3f200a1b60bf --- /dev/null +++ b/plugins/android/testData/lint/duplicatedIds.xml @@ -0,0 +1,17 @@ + + + + android:id="@+id/id123" + /> + + diff --git a/plugins/android/testData/lint/editText.xml b/plugins/android/testData/lint/editText.xml new file mode 100644 index 000000000000..afd1ab54fc0d --- /dev/null +++ b/plugins/android/testData/lint/editText.xml @@ -0,0 +1,6 @@ + + + ayout_height="wrap_content"/> + \ No newline at end of file diff --git a/plugins/android/testData/lint/editText_after.xml b/plugins/android/testData/lint/editText_after.xml new file mode 100644 index 000000000000..f2c4ad49423f --- /dev/null +++ b/plugins/android/testData/lint/editText_after.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/exportedService.xml b/plugins/android/testData/lint/exportedService.xml new file mode 100644 index 000000000000..b62fd1fc5b0a --- /dev/null +++ b/plugins/android/testData/lint/exportedService.xml @@ -0,0 +1,9 @@ + + + + android:exported="true"/> + + diff --git a/plugins/android/testData/lint/exportedService_after.xml b/plugins/android/testData/lint/exportedService_after.xml new file mode 100644 index 000000000000..014758a117f9 --- /dev/null +++ b/plugins/android/testData/lint/exportedService_after.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/plugins/android/testData/lint/hardcodedQuickfix.xml b/plugins/android/testData/lint/hardcodedQuickfix.xml new file mode 100644 index 000000000000..85cc775f1f5a --- /dev/null +++ b/plugins/android/testData/lint/hardcodedQuickfix.xml @@ -0,0 +1,12 @@ + + +android:text="Hello World, MyActivity" + /> + + diff --git a/plugins/android/testData/lint/hardcodedQuickfix1.xml b/plugins/android/testData/lint/hardcodedQuickfix1.xml new file mode 100644 index 000000000000..dc34d4a6e764 --- /dev/null +++ b/plugins/android/testData/lint/hardcodedQuickfix1.xml @@ -0,0 +1,12 @@ + + +android:text="Hello World, MyActivity" + /> + + diff --git a/plugins/android/testData/lint/hardcodedQuickfix1_after.xml b/plugins/android/testData/lint/hardcodedQuickfix1_after.xml new file mode 100644 index 000000000000..97da65a0b131 --- /dev/null +++ b/plugins/android/testData/lint/hardcodedQuickfix1_after.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/android/testData/lint/hardcodedQuickfix_after.xml b/plugins/android/testData/lint/hardcodedQuickfix_after.xml new file mode 100644 index 000000000000..97da65a0b131 --- /dev/null +++ b/plugins/android/testData/lint/hardcodedQuickfix_after.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/android/testData/lint/inefficientWeight.xml b/plugins/android/testData/lint/inefficientWeight.xml new file mode 100644 index 000000000000..65ebfc8958cf --- /dev/null +++ b/plugins/android/testData/lint/inefficientWeight.xml @@ -0,0 +1,12 @@ + + + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="10" + /> + + diff --git a/plugins/android/testData/lint/inefficientWeight_after.xml b/plugins/android/testData/lint/inefficientWeight_after.xml new file mode 100644 index 000000000000..ae8f06788487 --- /dev/null +++ b/plugins/android/testData/lint/inefficientWeight_after.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/android/testData/lint/missingPrefix.xml b/plugins/android/testData/lint/missingPrefix.xml new file mode 100644 index 000000000000..6934bcbf6f10 --- /dev/null +++ b/plugins/android/testData/lint/missingPrefix.xml @@ -0,0 +1,12 @@ + + + id="@+id/id123" + /> + + diff --git a/plugins/android/testData/lint/missingPrefix1.xml b/plugins/android/testData/lint/missingPrefix1.xml new file mode 100644 index 000000000000..3db882a6da7b --- /dev/null +++ b/plugins/android/testData/lint/missingPrefix1.xml @@ -0,0 +1,12 @@ + + + id="@+id/id123" + /> + + diff --git a/plugins/android/testData/lint/missingPrefix1_after.xml b/plugins/android/testData/lint/missingPrefix1_after.xml new file mode 100644 index 000000000000..6c736a2de094 --- /dev/null +++ b/plugins/android/testData/lint/missingPrefix1_after.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/android/testData/lint/missingPrefix_after.xml b/plugins/android/testData/lint/missingPrefix_after.xml new file mode 100644 index 000000000000..e007df753563 --- /dev/null +++ b/plugins/android/testData/lint/missingPrefix_after.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/plugins/android/testData/lint/obsoleteLayoutParams.xml b/plugins/android/testData/lint/obsoleteLayoutParams.xml new file mode 100644 index 000000000000..4c57fe6e7006 --- /dev/null +++ b/plugins/android/testData/lint/obsoleteLayoutParams.xml @@ -0,0 +1,6 @@ + + + android:layout_row="10"/> + \ No newline at end of file diff --git a/plugins/android/testData/lint/obsoleteLayoutParams_after.xml b/plugins/android/testData/lint/obsoleteLayoutParams_after.xml new file mode 100644 index 000000000000..1f0a1aed7c07 --- /dev/null +++ b/plugins/android/testData/lint/obsoleteLayoutParams_after.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/scrollViewChildren.xml b/plugins/android/testData/lint/scrollViewChildren.xml new file mode 100644 index 000000000000..55660b7e40b5 --- /dev/null +++ b/plugins/android/testData/lint/scrollViewChildren.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/scrollViewSize.xml b/plugins/android/testData/lint/scrollViewSize.xml new file mode 100644 index 000000000000..a5ee7b2c3647 --- /dev/null +++ b/plugins/android/testData/lint/scrollViewSize.xml @@ -0,0 +1,8 @@ + + + + android:layout_height="fill_parent"/> + + \ No newline at end of file diff --git a/plugins/android/testData/lint/scrollViewSize_after.xml b/plugins/android/testData/lint/scrollViewSize_after.xml new file mode 100644 index 000000000000..eb95fc26ed31 --- /dev/null +++ b/plugins/android/testData/lint/scrollViewSize_after.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/typographyDashes.xml b/plugins/android/testData/lint/typographyDashes.xml new file mode 100644 index 000000000000..7b68d3f92e0e --- /dev/null +++ b/plugins/android/testData/lint/typographyDashes.xml @@ -0,0 +1,4 @@ + + + 10-20 + \ No newline at end of file diff --git a/plugins/android/testData/lint/typographyDashes_after.xml b/plugins/android/testData/lint/typographyDashes_after.xml new file mode 100644 index 000000000000..35404e3362b2 --- /dev/null +++ b/plugins/android/testData/lint/typographyDashes_after.xml @@ -0,0 +1,4 @@ + + + 10–20 + \ No newline at end of file diff --git a/plugins/android/testData/lint/typographyQuotes.xml b/plugins/android/testData/lint/typographyQuotes.xml new file mode 100644 index 000000000000..cfe2294a0685 --- /dev/null +++ b/plugins/android/testData/lint/typographyQuotes.xml @@ -0,0 +1,5 @@ + + + untitled303 + aba 'aba' + diff --git a/plugins/android/testData/lint/typographyQuotes_after.xml b/plugins/android/testData/lint/typographyQuotes_after.xml new file mode 100644 index 000000000000..f0539ff7ece6 --- /dev/null +++ b/plugins/android/testData/lint/typographyQuotes_after.xml @@ -0,0 +1,5 @@ + + + untitled303 + aba ‘aba’ + diff --git a/plugins/android/testData/lint/uselessLeaf.xml b/plugins/android/testData/lint/uselessLeaf.xml new file mode 100644 index 000000000000..ae483929b35d --- /dev/null +++ b/plugins/android/testData/lint/uselessLeaf.xml @@ -0,0 +1,6 @@ + + + h="wrap_content" android:layout_height="wrap_content"/> + \ No newline at end of file diff --git a/plugins/android/testData/lint/uselessLeaf_after.xml b/plugins/android/testData/lint/uselessLeaf_after.xml new file mode 100644 index 000000000000..68d85c5e154b --- /dev/null +++ b/plugins/android/testData/lint/uselessLeaf_after.xml @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/plugins/android/testData/lint/uselessParent.xml b/plugins/android/testData/lint/uselessParent.xml new file mode 100644 index 000000000000..54a49cc510f5 --- /dev/null +++ b/plugins/android/testData/lint/uselessParent.xml @@ -0,0 +1,8 @@ + + + r android:layout_width="wrap_content" android:layout_height="wrap_content"> + + + \ No newline at end of file diff --git a/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java b/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java new file mode 100644 index 000000000000..186b291dd2b4 --- /dev/null +++ b/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java @@ -0,0 +1,217 @@ +package org.jetbrains.android; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.android.inspections.lint.*; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidLintTest extends AndroidTestCase { + @NonNls private static final String BASE_PATH = "/lint/"; + + public AndroidLintTest() { + super(false); + } + + public void testHardcodedQuickfix() throws Exception { + doTestHardcodedQuickfix(); + } + + public void testHardcodedQuickfix1() throws Exception { + doTestHardcodedQuickfix(); + } + + private void doTestHardcodedQuickfix() throws IOException { + final IntentionAction action = doTestHighlightingAndGetQuickfix( + new AndroidLintInspectionToolProvider.AndroidLintHardcodedTextInspection(), + AndroidBundle.message("add.string.resource.intention.text"), false ? "AndroidManifest.xml" : "/res/layout/layout.xml", "xml"); + assertNotNull(action); + assertTrue(action.isAvailable(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())); + + new WriteCommandAction(myFixture.getProject(), "") { + @Override + protected void run(Result result) throws Throwable { + ((AndroidAddStringResourceQuickFix)action) + .invokeIntention(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), "hello"); + } + }.execute(); + + myFixture.checkResultByFile(BASE_PATH + getTestName(true) + "_after.xml"); + } + + public void testContentDescription() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintContentDescriptionInspection(), + AndroidBundle.message("android.lint.inspections.add.content.description"), + "/res/layout/layout.xml", "xml"); + } + + public void testContentDescription1() throws Exception { + doTestNoFix(new AndroidLintInspectionToolProvider.AndroidLintContentDescriptionInspection(), + "/res/layout/layout.xml", "xml"); + } + + public void testAdapterViewChildren() throws Exception { + doTestNoFix(new AndroidLintInspectionToolProvider.AndroidLintAdapterViewChildrenInspection(), + "/res/layout/layout.xml", "xml"); + } + + public void testScrollViewChildren() throws Exception { + doTestNoFix(new AndroidLintInspectionToolProvider.AndroidLintScrollViewCountInspection(), + "/res/layout/layout.xml", "xml"); + } + + public void testMissingPrefix() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintMissingPrefixInspection(), + AndroidBundle.message("android.lint.inspections.add.android.prefix"), + "/res/layout/layout.xml", "xml"); + } + + public void testMissingPrefix1() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintMissingPrefixInspection(), + AndroidBundle.message("android.lint.inspections.add.android.prefix"), + "/res/layout/layout.xml", "xml"); + } + + public void testDuplicatedIds() throws Exception { + doTestNoFix(new AndroidLintInspectionToolProvider.AndroidLintDuplicateIdsInspection(), + "/res/layout/layout.xml", "xml"); + } + + public void testInefficientWeight() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintInefficientWeightInspection(), + AndroidBundle.message("android.lint.inspections.replace.with.zero.dp"), + "/res/layout/layout.xml", "xml"); + } + + public void testBaselineWeights() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintDisableBaselineAlignmentInspection(), + AndroidBundle.message("android.lint.inspections.set.baseline.attribute"), + "/res/layout/layout.xml", "xml"); + } + + public void testObsoleteLayoutParams() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintObsoleteLayoutParamInspection(), + AndroidBundle.message("android.lint.inspections.remove.attribute"), + "/res/layout/layout.xml", "xml"); + } + + public void testConvertToDp() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintPxUsageInspection(), + AndroidBundle.message("android.lint.inspections.convert.to.dp"), + "/res/layout/layout.xml", "xml"); + } + + public void testScrollViewSize() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintScrollViewSizeInspection(), + AndroidBundle.message("android.lint.inspections.set.to.wrap.content"), + "/res/layout/layout.xml", "xml"); + } + + public void testExportedService() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintExportedServiceInspection(), + AndroidBundle.message("android.lint.inspections.add.permission.attribute"), + "AndroidManifest.xml", "xml"); + } + + public void testEditText() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintTextFieldsInspection(), + AndroidBundle.message("android.lint.inspections.add.input.type.attribute"), + "/res/layout/layout.xml", "xml"); + } + + public void testUselessLeaf() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintUselessLeafInspection(), + AndroidBundle.message("android.lint.inspections.remove.unnecessary.view"), + "/res/layout/layout.xml", "xml"); + } + + public void testUselessParent() throws Exception { + doTestNoFix(new AndroidLintInspectionToolProvider.AndroidLintUselessParentInspection(), + "/res/layout/layout.xml", "xml"); + } + + public void testTypographyDashes() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintTypographyDashesInspection(), + AndroidBundle.message("android.lint.inspections.replace.with.suggested.characters"), + "/res/values/typography.xml", "xml"); + } + + public void testTypographyQuotes() throws Exception { + doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintTypographyQuotesInspection(), + AndroidBundle.message("android.lint.inspections.replace.with.suggested.characters"), + "/res/values/typography.xml", "xml"); + } + + private void doTestNoFix(@NotNull AndroidLintInspectionBase inspection, @NotNull String copyTo, @NotNull String extension) + throws IOException { + doTestHighlighting(inspection, copyTo, extension); + + IntentionAction action = null; + + for (IntentionAction a : myFixture.getAvailableIntentions()) { + if (a instanceof AndroidLintExternalAnnotator.MyFixingIntention) { + action = a; + } + } + assertNull(action); + } + + private void doTestWithFix(@NotNull AndroidLintInspectionBase inspection, + @NotNull String message, + @NotNull String copyTo, + @NotNull String extension) + throws IOException { + final IntentionAction action = doTestHighlightingAndGetQuickfix(inspection, message, copyTo, extension); + assertNotNull(action); + assertTrue(action.isAvailable(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile())); + + new WriteCommandAction(myFixture.getProject(), "") { + @Override + protected void run(Result result) throws Throwable { + action.invoke(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile()); + } + }.execute(); + + myFixture.checkResultByFile(BASE_PATH + getTestName(true) + "_after." + extension); + } + + @Nullable + private IntentionAction doTestHighlightingAndGetQuickfix(@NotNull AndroidLintInspectionBase inspection, + @NotNull String message, + @NotNull String copyTo, + @NotNull String extension) throws IOException { + doTestHighlighting(inspection, copyTo, extension); + + IntentionAction action = null; + + for (IntentionAction a : myFixture.getAvailableIntentions()) { + if (message.equals(a.getText())) { + action = a; + } + } + return action; + } + + private void doTestHighlighting(@NotNull AndroidLintInspectionBase inspection, @NotNull String copyTo, @NotNull String extension) + throws IOException { + if (!"AndroidManifest.xml".equals(copyTo)) { + createManifest(); + } + + myFixture.enableInspections(new GlobalInspectionToolWrapper(inspection)); + final VirtualFile file = myFixture.copyFileToProject(BASE_PATH + getTestName(true) + "." + extension, copyTo); + myFixture.configureFromExistingVirtualFile(file); + myFixture.doHighlighting(); + myFixture.checkHighlighting(true, false, false); + } +} From 8c9d0f03c84a8fed44b8ac5360a8ef191d727793 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 16:34:03 +0400 Subject: [PATCH 008/100] todo navigation: respect order (IDEA-51997) --- .../lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java | 2 ++ .../src/com/intellij/ide/util/treeView/AbstractTreeUi.java | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java index a0c783cfaf65..156ee77bd161 100644 --- a/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java +++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoTreeBuilder.java @@ -539,6 +539,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder { return null; } Object[] children = getTreeStructure().getChildElements(parent); + Arrays.sort(children, getUi().getNodeDescriptorComparator()); int idx = -1; for (int i = 0; i < children.length; i++) { if (obj.equals(children[i])) { @@ -584,6 +585,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder { return null; } Object[] children = getTreeStructure().getChildElements(parent); + Arrays.sort(children, getUi().getNodeDescriptorComparator()); int idx = -1; for (int i = 0; i < children.length; i++) { if (obj.equals(children[i])) { diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java index 6997d30dbed7..ced3ab62d05d 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java @@ -3570,6 +3570,10 @@ public class AbstractTreeUi { } } + public Comparator getNodeDescriptorComparator() { + return myNodeDescriptorComparator; + } + private void disposeNode(DefaultMutableTreeNode node) { TreeNode parent = node.getParent(); if (parent instanceof DefaultMutableTreeNode) { From 35daf8f2916ae7f506bf81861879620fd829e990 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 11:54:30 +0100 Subject: [PATCH 009/100] workaround action update after project closing --- .../platform-impl/src/com/intellij/notification/EventLog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 24552d8947ce..e9bd51dfb527 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -329,6 +329,7 @@ public class EventLog implements Notifications { group.add(new DumbAwareAction("Mark all as read", "Mark all unread notifications as read", IconLoader.getIcon("/general/reset.png")) { @Override public void update(AnActionEvent e) { + if (project.isDisposed()) return; e.getPresentation().setEnabled(!getProjectComponent(project).myProjectModel.getNotifications().isEmpty()); } From fa6b7b350b123658377c211479e48e68f1f3fa5e Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 12:05:01 +0100 Subject: [PATCH 010/100] IDEA-80378 Event Log:   is not replaced in text --- .../com/intellij/notification/EventLog.java | 1 + .../intellij/notification/EventLogTest.groovy | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 platform/platform-tests/testSrc/com/intellij/notification/EventLogTest.groovy diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index e9bd51dfb527..2d1e660c2c6d 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -133,6 +133,7 @@ public class EventLog implements Notifications { mainText += content; } + mainText = StringUtil.replace(mainText, " ", " "); int nlIndex = eolIndex(mainText); if (nlIndex >= 0) { mainText = mainText.substring(0, nlIndex); diff --git a/platform/platform-tests/testSrc/com/intellij/notification/EventLogTest.groovy b/platform/platform-tests/testSrc/com/intellij/notification/EventLogTest.groovy new file mode 100644 index 000000000000..f0ac1b26be4c --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/notification/EventLogTest.groovy @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2012 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.notification; + +import com.intellij.testFramework.UsefulTestCase; + +/** + * @author peter + */ +class EventLogTest extends UsefulTestCase { + + public void testNbsp() { + def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello world", NotificationType.ERROR)) + assert entry.message == 'Title: Hello world' + } + +} From d7dadda142d260e6ec65bc2f39ceba6031fb0152 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 13:43:05 +0100 Subject: [PATCH 011/100] IDEA-80379 Perforce: UOE at com.intellij.openapi.vcs.rollback.DefaultRollbackEnvironment.rollbackModifiedWithoutCheckout --- .../src/com/intellij/openapi/vcs/VcsVFSListener.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java index dbf307d0134e..9c2c9a0d03b1 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsVFSListener.java @@ -223,7 +223,7 @@ public abstract class VcsVFSListener implements Disposable { getSingleFileDeletePromptTemplate(), myRemoveOption); } - protected void beforeContentsChange(VirtualFile file) { + protected void beforeContentsChange(VirtualFileEvent event, VirtualFile file) { } private void addFileToMove(final VirtualFile file, final String newParentPath, final String newName) { @@ -378,10 +378,8 @@ public abstract class VcsVFSListener implements Disposable { @Override public void beforeContentsChange(VirtualFileEvent event) { - if (!isEventIgnored(event, false)) { - assert !event.getFile().isDirectory(); - VcsVFSListener.this.beforeContentsChange(event.getFile()); - } + assert !event.getFile().isDirectory(); + VcsVFSListener.this.beforeContentsChange(event, event.getFile()); } } From 0c3ac45cc2bbd50d185d4f1043aecceef7fde83e Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 13:44:51 +0100 Subject: [PATCH 012/100] IDEA-80382 Notifications: when balloon is shown in Event Log and after clicking a link it expires, it should be hidden --- .../src/com/intellij/notification/Notification.java | 6 +++++- .../src/com/intellij/notification/EventLog.java | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java index 91c23432ba70..b264b20d1c3c 100644 --- a/platform/platform-api/src/com/intellij/notification/Notification.java +++ b/platform/platform-api/src/com/intellij/notification/Notification.java @@ -97,6 +97,11 @@ public class Notification { public void expire() { NotificationsManager.getNotificationsManager().expire(this); + hideBalloon(); + myExpired = true; + } + + public void hideBalloon() { if (myBalloonRef != null) { final Balloon balloon = myBalloonRef.get(); if (balloon != null) { @@ -104,7 +109,6 @@ public class Notification { } myBalloonRef = null; } - myExpired = true; } public void setBalloon(@Nullable final Balloon balloon) { diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 2d1e660c2c6d..79d6ad266bea 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -415,6 +415,8 @@ public class EventLog implements Notifications { Balloon balloon = NotificationsManagerImpl.createBalloon(myNotification, true, true); Disposer.register(project, balloon); balloon.show(target, Balloon.Position.above); + myNotification.hideBalloon(); + myNotification.setBalloon(balloon); } } From 713c8e25e280cd3940630d37fc15ab2af56aab14 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 26 Jan 2012 16:48:07 +0400 Subject: [PATCH 013/100] Correct permissions for copies of executable files --- .../util/src/com/intellij/openapi/util/io/FileUtil.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index a47df50805c8..3ed50898fc01 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -678,9 +678,10 @@ public class FileUtil { } if (SystemInfo.isUnix && fromFile.canExecute()) { - final int permissions = FileSystemUtil.getPermissions(fromFile); - if (permissions != -1) { - FileSystemUtil.setPermissions(toFile, permissions); + final int oldPermissions = FileSystemUtil.getPermissions(fromFile); + final int newPermissions = FileSystemUtil.getPermissions(toFile); + if (oldPermissions != -1 && newPermissions != -1) { + FileSystemUtil.setPermissions(toFile, (oldPermissions | newPermissions)); } } } From 97cdf4ce8eede2d26de00b1be437c79ad8ed8aa1 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 26 Jan 2012 16:55:57 +0400 Subject: [PATCH 014/100] moved tests to community --- .../FileDocumentManagerImplTest.java | 580 +++++++++++++++ .../fileEditor/IdeDocumentHistoryTest.java | 210 ++++++ .../openapi/fileEditor/LoadTextUtilTest.java | 37 + .../src/com/intellij/mock/Mock.java | 681 ++++++++++++++++++ .../intellij/mock/MockCommandProcessor.java | 104 +++ .../com/intellij/mock/MockVirtualFile.java | 70 +- 6 files changed, 1671 insertions(+), 11 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java create mode 100644 platform/testFramework/src/com/intellij/mock/Mock.java create mode 100644 platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java new file mode 100644 index 000000000000..baed1c53c602 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java @@ -0,0 +1,580 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.codeStyle.CodeStyleFacade; +import com.intellij.codeStyle.DefaultCodeStyleFacade; +import com.intellij.mock.MockCommandProcessor; +import com.intellij.mock.MockEditorFactory; +import com.intellij.mock.MockVirtualFile; +import com.intellij.mock.MockVirtualFileManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; +import com.intellij.openapi.fileTypes.*; +import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl; +import com.intellij.openapi.fileTypes.impl.InternalFileTypeFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectLocator; +import com.intellij.openapi.project.impl.DefaultProjectLocator; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileEvent; +import com.intellij.testFramework.MockSchemesManagerFactory; +import com.intellij.testFramework.PlatformLiteFixture; +import com.intellij.util.LocalTimeCounter; +import org.jetbrains.annotations.NotNull; + +import java.io.CharArrayWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import java.util.Arrays; + +public class FileDocumentManagerImplTest extends PlatformLiteFixture { + private MyFileDocumentManagerImpl myDocumentManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initApplication(); + registerExtension(FileTypeFactory.FILE_TYPE_FACTORY_EP, new InternalFileTypeFactory()); + registerExtensionPoint(FileDocumentSynchronizationVetoer.EP_NAME, FileDocumentSynchronizationVetoer.class); + getApplication().registerService(CommandProcessor.class, new MyMockCommandProcessor()); + getApplication().registerService(CodeStyleFacade.class, new DefaultCodeStyleFacade()); + getApplication().registerService(ProjectLocator.class, new DefaultProjectLocator()); + + MockEditorFactory editorFactory = new MockEditorFactory(); + getApplication().registerService(EditorFactory.class, editorFactory); + final LanguageFileType[] fileType = {null}; + getApplication().addComponent(FileTypeManager.class, new FileTypeManagerImpl(null, new MockSchemesManagerFactory()){ + @NotNull + @Override + public FileType getFileTypeByFileName(@NotNull String fileName) { + return fileType[0]; + } + + @NotNull + @Override + public FileType getFileTypeByFile(@NotNull VirtualFile file) { + return fileType[0]; + } + + @NotNull + @Override + public FileType getFileTypeByExtension(@NotNull String extension) { + return fileType[0]; + } + }); + + fileType[0] = StdFileTypes.JAVA; + + getApplication().getComponent(FileTypeManager.class); + myDocumentManager = new MyFileDocumentManagerImpl(); + getApplication().registerService(FileDocumentManager.class, myDocumentManager); + } + + public void testGetCachedDocument_Cached() throws Exception { + final Document cachedDocument = myDocumentManager.getCachedDocument(new MockVirtualFile("test.txt")); + assertNull(cachedDocument); + } + + public void testGetCachedDocument_NotCached() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + + assertSame(myDocumentManager.getCachedDocument(file), document); + } + + public void testGetDocument_CreateNew() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.isWritable(), document.isWritable()); + } + + public void testGetDocument_CreateNew_ReadOnly() throws Exception { + final MockVirtualFile file = newTextFile(); + file.setWritable(false); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.isWritable(), document.isWritable()); + } + + public void testGetDocument_ReturnCachedValueTwice() throws Exception { + final VirtualFile file = newTextFile(); + final Document document = myDocumentManager.getDocument(file); + assertNotNull(document); + assertEquals("test", document.getText()); + + final Document document2 = myDocumentManager.getDocument(file); + assertSame(document2, document); + } + + public void testGetDocument_CreatesNewAfterGced() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertTrue(idCode != System.identityHashCode(document)); + } + + public void testGetUnsavedDocuments_NoDocuments() throws Exception { + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_CreatedDocument() throws Exception { + final VirtualFile file = newTextFile(); + myDocumentManager.getDocument(file); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_ModifiedDocument() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(1, unsavedDocuments.length); + assertSame(document, unsavedDocuments[0]); + assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray())); + } + + public void testGetUnsavedDocuments_afterSaveAllDocuments() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveAllDocuments(); + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + public void testGetUnsavedDocuments_afterSaveDocuments() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(0, unsavedDocuments.length); + } + + private static MockVirtualFile newTextFile() { + return new MockVirtualFile("test.txt", "test"); + } + + public void testGetUnsavedDocuments_afterSaveDocumentWithProblems() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @Override + @NotNull + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + throw new IOException(""); + } + }; + + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + + assertNotNull(myDocumentManager.myExceptionOnSave); + + final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments(); + assertEquals(1, unsavedDocuments.length); + assertSame(document, unsavedDocuments[0]); + assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray())); + } + + public void testUnsavedDocument_DontGc() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertEquals(idCode, System.identityHashCode(document)); + } + + public void testUnsavedDocument_GcAfterSave() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + int idCode = System.identityHashCode(document); + //noinspection UnusedAssignment + document = null; + + myDocumentManager.saveAllDocuments(); + + System.gc(); + System.gc(); + + document = myDocumentManager.getDocument(file); + assertTrue(idCode != System.identityHashCode(document)); + } + + public void testSaveDocument_DocumentWasntChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + myDocumentManager.saveDocument(document); + assertEquals(stamp, file.getModificationStamp()); + } + + public void testSaveDocument_DocumentWasChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveDocument(document); + assertTrue(stamp != file.getModificationStamp()); + assertEquals(document.getModificationStamp(), file.getModificationStamp()); + assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray())); + } + + public void testSaveAllDocuments_DocumentWasChanged() throws Exception { + final VirtualFile file = newTextFile(); + final long stamp = file.getModificationStamp(); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + + myDocumentManager.saveAllDocuments(); + assertTrue(stamp != file.getModificationStamp()); + assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray())); + } + + public void testGetFile() throws Exception { + final VirtualFile file = newTextFile(); + Document document = myDocumentManager.getDocument(file); + assertSame(file, myDocumentManager.getFile(document)); + } + + public void testConvertSeparators() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + Document document = myDocumentManager.getDocument(file); + assertEquals("test\ntest", document.getText()); + } + + public void testRememberSeparators() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + myDocumentManager.saveAllDocuments(); + assertTrue(Arrays.equals("xxxtest\rtest".getBytes(), file.contentsToByteArray())); + } + + public void testContentChanged_noDocument() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + file.setContent(null, "xxx", true); + assertNull(myDocumentManager.getCachedDocument(file)); + } + + public void testContentChanged_documentPresent() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + file.setContent(null, "xxx", true); + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + } + + public void testContentChanged_ignoreEventsFromSelf() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + file.setContent(myDocumentManager, "xxx", true); + assertEquals("test\ntest", document.getText()); + } + + public void testContentChanged_ignoreEventsFromSelfOnSave() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest") { + public Writer getWriter(final Object requestor, final long newModificationStamp) { + final VirtualFile self = this; + return new CharArrayWriter() { + @Override + public void close() { + super.close(); + long oldStamp = getModificationStamp(); + setModificationStamp(newModificationStamp); + setText(toString()); + myDocumentManager.contentsChanged(new VirtualFileEvent(requestor, self, null, oldStamp, getModificationStamp())); + } + }; + } + }; + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "xxx"); + final long stamp = document.getModificationStamp(); + + myDocumentManager.saveAllDocuments(); + assertEquals(stamp, document.getModificationStamp()); + } + + public void testContentChanged_reloadChangedDocument() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest"); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + + myDocumentManager.myReloadFromDisk = Boolean.TRUE; + try { + file.setContent(null, "xxx", true); + + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(0, myDocumentManager.getUnsavedDocuments().length); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testContentChanged_dontreloadChangedDocument() throws Exception { + final MockVirtualFile file = newTextFile(); + file.setListener(myDocumentManager); + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + + myDocumentManager.myReloadFromDisk = Boolean.FALSE; + try { + long oldDocumentStamp = document.getModificationStamp(); + + file.setContent(null, "xxx", true); + + assertEquals("zzztest", document.getText()); + assertEquals(oldDocumentStamp, document.getModificationStamp()); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testSaveDocument_dontSaveIfModStampEqualsToFile() throws Exception { + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + fail(); + throw new IOException(); + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + document.setModificationStamp(file.getModificationStamp()); + + myDocumentManager.saveDocument(document); + } + + // this test requires changes in idea code to support MockFile as local file system file (FileDocumentManager.needsRefresh). + // TODO: think how to test this functionality without hacking production code + public void atestContentChanged_reloadChangedDocumentOnSave() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest") { + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + long oldStamp = getModificationStamp(); + setModificationStamp(LocalTimeCounter.currentTime()); + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp())); + } + }; + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + file.setContent(null, "xxx", false); + + myDocumentManager.myReloadFromDisk = Boolean.TRUE; + try { + file.setActualTimeStamp(file.getTimeStamp() + 1); + myDocumentManager.saveAllDocuments(); + long fileStamp = file.getModificationStamp(); + + assertEquals("xxx", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertEquals(file.getModificationStamp(), fileStamp); + assertEquals(0, myDocumentManager.getUnsavedDocuments().length); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testContentChanged_dontreloadChangedDocumentOnSave() throws Exception { + final MockVirtualFile file = new MockVirtualFile("test.txt", "test") { + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + long oldStamp = getModificationStamp(); + setModificationStamp(LocalTimeCounter.currentTime()); + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp())); + } + }; + + myDocumentManager.myReloadFromDisk = Boolean.FALSE; + try { + Document document = myDocumentManager.getDocument(file); + document.insertString(0, "zzz"); + long documentStamp = document.getModificationStamp(); + + file.setContent(null, "xxx", false); + + file.setActualTimeStamp(file.getTimeStamp() + 1); + myDocumentManager.saveAllDocuments(); + + assertEquals("zzztest", document.getText()); + assertEquals(file.getModificationStamp(), document.getModificationStamp()); + assertTrue(Arrays.equals("zzztest".getBytes(), file.contentsToByteArray())); + assertEquals(documentStamp, document.getModificationStamp()); + } + finally { + myDocumentManager.myReloadFromDisk = null; + } + } + + public void testReplaceDocumentTestWithTheSameTest() throws Exception { + final boolean[] canCallSave = {true}; + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + if (!canCallSave[0]) fail(); + return super.getOutputStream(requestor, newModificationStamp, newTimeStamp); + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + + String newText = "test text"; + document.replaceString(0, document.getTextLength(), newText); + assertTrue(myDocumentManager.isDocumentUnsaved(document)); + myDocumentManager.saveDocument(document); + + canCallSave[0] = false; + + final long modificationStamp = document.getModificationStamp(); + + document.replaceString(0, document.getTextLength(), newText); + + if (myDocumentManager.isDocumentUnsaved(document)) { + assertTrue(document.getModificationStamp() > modificationStamp); + } + else { + assertEquals(modificationStamp, document.getModificationStamp()); + } + } + + + public void testExternalReplaceWithTheSameText() throws Exception{ + final long[] modificationStamp = new long[1]; + + modificationStamp[0] = 1; + + final VirtualFile file = new MockVirtualFile("test.txt", "test") { + @NotNull + @Override + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + fail(); + throw new IOException(); + } + + @Override + public long getModificationStamp() { + return modificationStamp[0]; + } + + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, 1, 2)); + + } + }; + DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file); + + + modificationStamp[0] = 2; + + file.refresh(false, false); + + assertEquals(2, document.getModificationStamp()); + } + + public static class MyFileDocumentManagerImpl extends FileDocumentManagerImpl { + + public static final FileDocumentManagerListener[] LISTENERS = new FileDocumentManagerListener[0]; + + public IOException myExceptionOnSave; + public Boolean myReloadFromDisk = null; + + public MyFileDocumentManagerImpl() { + super(new MockVirtualFileManager()); + } + + @Override + protected void reportErrorOnSave(IOException e) { + myExceptionOnSave = e; + } + + @Override + protected boolean askReloadFromDisk(VirtualFile file, Document document) { + if (myReloadFromDisk == null){ + fail(); + return false; + } + else{ + return myReloadFromDisk.booleanValue(); + } + } + + @NotNull + @Override + protected FileDocumentManagerListener[] getListeners() { + return LISTENERS; + } + } + + private static class MyMockCommandProcessor extends MockCommandProcessor { + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) { + runnable.run(); + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy, + Document document) { + runnable.run(); + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy) { + runnable.run(); + } + + @Override + public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) { + runnable.run(); + } + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java new file mode 100644 index 000000000000..04264ccb9df3 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/IdeDocumentHistoryTest.java @@ -0,0 +1,210 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.mock.Mock; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.fileEditor.impl.IdeDocumentHistoryImpl; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.testFramework.PlatformTestCase; +import org.jetbrains.annotations.NotNull; + +public class IdeDocumentHistoryTest extends PlatformTestCase { + private IdeDocumentHistoryImpl myHistory; + + private Mock.MyFileEditor mySelectedEditor; + private Mock.MyVirtualFile mySelectedFile; + private FileEditorState myEditorState; + private FileEditorProvider myProvider; + + private MyState myState1; + private MyState myState2; + private MyState myState3; + + @Override + protected void setUp() throws Exception { + super.setUp(); + myHistory = new IdeDocumentHistoryImpl(getProject(), EditorFactory.getInstance(), new EditorManager(), VirtualFileManager.getInstance(), CommandProcessor.getInstance(), new Mock.MyToolWindowManager()) { + @Override + protected Pair getSelectedEditor() { + return Pair.create ((FileEditor)mySelectedEditor, myProvider); + } + + @Override + protected void executeCommand(Runnable runnable, String name, Object groupId) { + myHistory.onCommandStarted(); + runnable.run(); + myHistory.onSelectionChanged(); + myHistory.onCommandFinished(groupId); + } + }; + + mySelectedEditor = new Mock.MyFileEditor() { + @Override + @NotNull + public FileEditorState getState(@NotNull FileEditorStateLevel level) { + return myEditorState; + } + + @Override + public void setState(@NotNull FileEditorState state) { + myEditorState = state; + } + }; + mySelectedFile = new Mock.MyVirtualFile(); + myEditorState = new MyState(false, "start"); + myProvider = new Mock.MyFileEditorProvider() { + @Override + @NotNull + public String getEditorTypeId() { + return "EditorType"; + } + }; + } + public void testNoHistoryRecording() throws Throwable { + myHistory.onCommandStarted(); + myHistory.onCommandFinished(null); + + assertFalse(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + } + + public void testNavigationRecording() throws Throwable { + makeNavigationChange(myState2); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + assertEquals(1, myHistory.getBackPlaces().size()); + } + + public void testMergingForwardPlaces() throws Throwable { + myEditorState = new MyState(true, "state1"); + makeNavigationChange(new MyState(true, "state2")); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + assertEquals(1, myHistory.getBackPlaces().size()); + } + + public void testSimpleNavigation() throws Throwable { + pushTwoStates(); + + assertFalse(myHistory.isForwardAvailable()); + assertTrue(myHistory.isBackAvailable()); + + myHistory.back(); + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState2, myEditorState); + + myHistory.back(); + assertFalse(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState1, myEditorState); + + myHistory.forward(); + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + assertSame(myState2, myEditorState); + + myHistory.forward(); + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + assertSame(myState3, myEditorState); + } + + public void testQueueCutOff() throws Throwable { + pushTwoStates(); + myHistory.back(); + + assertTrue(myHistory.isBackAvailable()); + assertTrue(myHistory.isForwardAvailable()); + + MyState newState = new MyState(false, "newState"); + makeNavigationChange(newState); + + assertTrue(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + + myHistory.back(); + assertSame(myState2, myEditorState); + myHistory.back(); + assertSame(myState1, myEditorState); + assertFalse(myHistory.isBackAvailable()); + } + + public void testRemoveInvalid() throws Throwable { + pushTwoStates(); + assertTrue(myHistory.isBackAvailable()); + + mySelectedFile.myValid = false; + + myHistory.onFileDeleted(); + + assertFalse(myHistory.isBackAvailable()); + assertFalse(myHistory.isForwardAvailable()); + } + + + private void pushTwoStates() { + myState1 = new MyState(false, "state1"); + myState2 = new MyState(false, "state2"); + myState3 = new MyState(false, "state3"); + + myEditorState = myState1; + makeNavigationChange(myState2); + makeNavigationChange(myState3); + } + + private void makeNavigationChange(MyState newState) { + myHistory.onCommandStarted(); + myHistory.onSelectionChanged(); + myHistory.onCommandFinished(null); + myEditorState = newState; + } + + private class EditorManager extends Mock.MyFileEditorManager { + + @Override + public VirtualFile getFile(@NotNull FileEditor editor) { + return mySelectedFile; + } + + @Override + @NotNull + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + boolean searchForSplitter) { + return Pair.create (new FileEditor[] {mySelectedEditor}, new FileEditorProvider[] {myProvider}); + } + + @Override + public FileEditorProvider getProvider(FileEditor editor) { + return myProvider; + } + } + + private static class MyState implements FileEditorState { + + private final boolean myCanBeMerged; + private final String myName; + + public MyState(boolean canBeMerged, String name) { + myCanBeMerged = canBeMerged; + myName = name; + } + + @Override + public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) { + return myCanBeMerged; + } + + public String toString() { + return myName; + } + } + +} diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java new file mode 100644 index 000000000000..74ead6c532b8 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/LoadTextUtilTest.java @@ -0,0 +1,37 @@ +package com.intellij.openapi.fileEditor; + +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; +import com.intellij.openapi.util.Comparing; +import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.LightVirtualFile; + +public class LoadTextUtilTest extends LightPlatformTestCase { + private static void doTest(String source, String expected, String expectedSeparator) { + final LightVirtualFile vFile = new LightVirtualFile("test.txt"); + final CharSequence real = LoadTextUtil.getTextByBinaryPresentation(source.getBytes(), vFile); + assertTrue("content", Comparing.equal(expected, real)); + if (expectedSeparator != null) { + assertEquals("detected line separator", expectedSeparator, FileDocumentManager.getInstance().getLineSeparator(vFile, null)); + } + } + + public void testSimpleLoad() { + doTest("test", "test", null); + } + + public void testConvert_SlashR() { + doTest("test\rtest\rtest", "test\ntest\ntest", "\r"); + } + + public void testConvert_SlashN() { + doTest("test\ntest\ntest", "test\ntest\ntest", "\n"); + } + + public void testConvert_SlashR_SlashN() { + doTest("test\r\ntest\r\ntest", "test\ntest\ntest", "\r\n"); + } + + public void testConvertMostCommon() { + doTest("test\r\ntest\r\ntest\ntest", "test\ntest\ntest\ntest", "\r\n"); + } +} diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java new file mode 100644 index 000000000000..74c68d273eb0 --- /dev/null +++ b/platform/testFramework/src/com/intellij/mock/Mock.java @@ -0,0 +1,681 @@ +package com.intellij.mock; + +import com.intellij.codeHighlighting.BackgroundEditorHighlighter; +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileEditor.impl.EditorComposite; +import com.intellij.openapi.fileEditor.impl.EditorWindow; +import com.intellij.openapi.fileEditor.impl.EditorsSplitters; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.util.*; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowAnchor; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.impl.IdeFocusManagerHeadless; +import com.intellij.util.ArrayUtil; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.HyperlinkListener; +import java.awt.*; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Collections; +import java.util.List; + +//[kirillk] - this class looks to be an overkill but IdeDocumentHistory is highly coupled +// with all of that stuff below, so it's not possible to test it's back/forward capabilities +// w/o making mocks for all of them. perhaps later we will decouple those things +public class Mock { + + public static class MyFileEditor extends UserDataHolderBase implements DocumentsEditor { + public Document[] DOCUMENTS; + + @Override + public Document[] getDocuments() { + return DOCUMENTS; + } + + @Override + @NotNull + public JComponent getComponent() { + throw new UnsupportedOperationException(); + } + + @Override + public JComponent getPreferredFocusedComponent() { + return null; + } + + @Override + @NotNull + public String getName() { + return ""; + } + + @Override + public void dispose() { + } + + @Override + public StructureViewBuilder getStructureViewBuilder() { + return null; + } + + @Override + @NotNull + public FileEditorState getState(@NotNull FileEditorStateLevel level) { + return new FileEditorState() { + @Override + public boolean canBeMergedWith(FileEditorState fileEditorState, FileEditorStateLevel fileEditorStateLevel) { + return false; + } + }; + } + + @Override + public void setState(@NotNull FileEditorState state) { + } + + @Override + public boolean isModified() { + return false; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public void selectNotify() { + } + + @Override + public void deselectNotify() { + } + + @Override + public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) { + } + + @Override + public BackgroundEditorHighlighter getBackgroundHighlighter() { + return null; + } + + @Override + public FileEditorLocation getCurrentLocation() { + return null; + } + } + + public static class MyFileEditorManager extends FileEditorManagerEx { + @Override + public JComponent getComponent() { + return null; + } + + @Override + public ActionCallback notifyPublisher(Runnable runnable) { + runnable.run(); + return new ActionCallback.Done(); + } + + @Override + public ActionCallback getReady(@NotNull Object requestor) { + return new ActionCallback.Done(); + } + + @NotNull + @Override + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + @NotNull EditorWindow window) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isInsideChange() { + return false; + } + + @Override + public boolean hasSplitOrUndockedWindows() { + return false; + } + + @Override + public EditorsSplitters getSplittersFor(Component c) { + return null; + } + + @Override + public EditorsSplitters getSplitters() { + return null; + } + + @Override + public AsyncResult getActiveWindow() { + return null; + } + + @Override + public void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void removeTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void addBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public void removeBottomComponent(@NotNull final FileEditor editor, @NotNull final JComponent component) { + } + + @Override + public JComponent getPreferredFocusedComponent() { + return null; + } + + @Override + @NotNull + public Pair getEditorsWithProviders(@NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + public FileEditorProvider getProvider(FileEditor editor) { + return null; + } + + @Override + public EditorWindow getCurrentWindow() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void setCurrentWindow(EditorWindow window) { + } + + @Override + public VirtualFile getFile(@NotNull FileEditor editor) { + return null; + } + + @Override + public void updateFilePresentation(VirtualFile file) { + } + + @Override + public void unsplitWindow() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void unsplitAllWindow() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + @NotNull + public EditorWindow[] getWindows() { + return new EditorWindow[0]; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + @NotNull + public VirtualFile[] getSiblings(VirtualFile file) { + return new VirtualFile[0]; + } + + @Override + public void createSplitter(int orientation, @Nullable EditorWindow window) { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void changeSplitterOrientation() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public void flipTabs() { + //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean tabsMode() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isInSplitter() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean hasOpenedFile() { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public VirtualFile getCurrentFile() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Pair getSelectedEditorWithProvider(@NotNull VirtualFile file) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public boolean isChanged(@NotNull EditorComposite editor) { + return false; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public EditorWindow getNextWindow(@NotNull EditorWindow window) { + return null; + } + + @Override + public EditorWindow getPrevWindow(@NotNull EditorWindow window) { + return null; + } + + @Override + public void closeAllFiles() { + } + + public Editor openTextEditorEnsureNoFocus(@NotNull OpenFileDescriptor descriptor) { + return null; + } + + @Override + @NotNull + public Pair openFileWithProviders(@NotNull VirtualFile file, + boolean focusEditor, + boolean searchForSplitter) { + return Pair.create (new FileEditor[0], new FileEditorProvider [0]); + } + + @Override + public void closeFile(@NotNull VirtualFile file) { + } + + @Override + public void closeFile(@NotNull VirtualFile file, @NotNull EditorWindow window) { + } + + @Override + public Editor openTextEditor(OpenFileDescriptor descriptor, boolean focusEditor) { + return null; + } + + @Override + public Editor getSelectedTextEditor() { + return null; + } + + @Override + public boolean isFileOpen(@NotNull VirtualFile file) { + return false; + } + + @Override + @NotNull + public VirtualFile[] getOpenFiles() { + return new VirtualFile[0]; + } + + @Override + @NotNull + public VirtualFile[] getSelectedFiles() { + return new VirtualFile[0]; + } + + @Override + @NotNull + public FileEditor[] getSelectedEditors() { + return new FileEditor[0]; + } + + @Override + public FileEditor getSelectedEditor(@NotNull VirtualFile file) { + return null; + } + + @Override + @NotNull + public FileEditor[] getEditors(@NotNull VirtualFile file) { + return new FileEditor[0]; + } + + @NotNull + @Override + public FileEditor[] getAllEditors(@NotNull VirtualFile file) { + return new FileEditor[0]; + } + + @Override + @NotNull + public FileEditor[] getAllEditors() { + return new FileEditor[0]; + } + + @Override + public void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent) { + } + + @Override + public void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent) { + } + + @Override + public void addFileEditorManagerListener(@NotNull FileEditorManagerListener listener) { + } + + @Override + public void addFileEditorManagerListener(@NotNull FileEditorManagerListener listener, Disposable parentDisposable) { + } + + @Override + public void removeFileEditorManagerListener(@NotNull FileEditorManagerListener listener) { + } + + @Override + @NotNull + public List openEditor(@NotNull OpenFileDescriptor descriptor, boolean focusEditor) { + return Collections.emptyList(); + } + + @Override + @NotNull + public Project getProject() { + throw new UnsupportedOperationException(); + } + + @Override + public void registerExtraEditorDataProvider(@NotNull EditorDataProvider provider, Disposable parentDisposable) { + } + + @Override + public int getWindowSplitCount() { + return 0; + } + } + + public static class MyVirtualFile extends VirtualFile { + + public boolean myValid = true; + + @Override + @NotNull + public VirtualFileSystem getFileSystem() { + throw new UnsupportedOperationException(); + } + + @Override + public String getPath() { + return null; + } + + @Override + @NotNull + public String getName() { + throw new UnsupportedOperationException(); + } + + @Override + public void rename(Object requestor, @NotNull String newName) throws IOException { + } + + @Override + public boolean isWritable() { + return false; + } + + @Override + public boolean isDirectory() { + return false; + } + + @Override + public boolean isValid() { + return myValid; + } + + @Override + public VirtualFile getParent() { + return null; + } + + @Override + public VirtualFile[] getChildren() { + return new VirtualFile[0]; + } + + @Override + public VirtualFile createChildDirectory(Object requestor, String name) throws IOException { + return null; + } + + @Override + public VirtualFile createChildData(Object requestor, @NotNull String name) throws IOException { + return null; + } + + @Override + public void delete(Object requestor) throws IOException { + } + + @Override + public void move(Object requestor, @NotNull VirtualFile newParent) throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + return null; + } + + @Override + @NotNull + public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public byte[] contentsToByteArray() throws IOException { + return ArrayUtil.EMPTY_BYTE_ARRAY; + } + + @Override + public long getModificationStamp() { + return 0; + } + + @Override + public long getTimeStamp() { + return 0; + } + + @Override + public long getLength() { + return 0; + } + + @Override + public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { + } + } + + public static class MyToolWindowManager extends ToolWindowManager { + @Override + public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, + @NotNull JComponent component, + @NotNull ToolWindowAnchor anchor, + Disposable parentDisposable, + boolean canWorkInDumbMode, boolean canCloseContents) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, + @NotNull JComponent component, + @NotNull ToolWindowAnchor anchor, + Disposable parentDisposable, + boolean canWorkInDumbMode) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, + final Disposable parentDisposable, final boolean dumbAware) { + return null; + } + + @Override + public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, final boolean sideTool) { + return null; + } + + public JComponent getFocusTargetFor(final JComponent comp) { + return null; + } + + @Override + public void unregisterToolWindow(@NotNull String id) { + } + + @Override + public void activateEditorComponent() { + } + + public ActionCallback requestFocus(final Component c, final boolean forced) { + return new ActionCallback.Done(); + } + + public ActionCallback requestFocus(final ActiveRunnable command, final boolean forced) { + return new ActionCallback.Done(); + } + + @Override + public boolean isEditorComponentActive() { + return false; + } + + @Override + public String[] getToolWindowIds() { + return ArrayUtil.EMPTY_STRING_ARRAY; + } + + @Override + public String getActiveToolWindowId() { + return null; + } + + @Override + public ToolWindow getToolWindow(String id) { + return null; + } + + @Override + public void invokeLater(Runnable runnable) { + } + + @Override + public IdeFocusManager getFocusManager() { + return IdeFocusManagerHeadless.INSTANCE; + } + + @Override + public void notifyByBalloon(@NotNull final String toolWindowId, final MessageType type, @NotNull final String text, @Nullable final Icon icon, + @Nullable final HyperlinkListener listener) { + } + + @Override + public Balloon getToolWindowBalloon(String id) { + return null; + } + + @Override + public void notifyByBalloon(@NotNull final String toolWindowId, @NotNull final MessageType type, @NotNull final String htmlBody) { + } + } + + + public static class MyFileEditorProvider implements FileEditorProvider { + @Override + public boolean accept(@NotNull Project project, @NotNull VirtualFile file) { + return false; + } + + @Override + @NotNull + public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + @Override + public void disposeEditor(@NotNull FileEditor editor) { + } + + @Override + @NotNull + public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) { + throw new UnsupportedOperationException(); + } + + @Override + public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) { + } + + @Override + @NotNull + public String getEditorTypeId() { + throw new UnsupportedOperationException(); + } + + @Override + @NotNull + public FileEditorPolicy getPolicy() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java b/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java new file mode 100644 index 000000000000..981b97fc25df --- /dev/null +++ b/platform/testFramework/src/com/intellij/mock/MockCommandProcessor.java @@ -0,0 +1,104 @@ +package com.intellij.mock; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.command.CommandListener; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.command.UndoConfirmationPolicy; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MockCommandProcessor extends CommandProcessor { + @Override + public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) { + } + + @Override + public void executeCommand(Project project, + @NotNull Runnable runnable, + String name, + Object groupId, + @NotNull UndoConfirmationPolicy confirmationPolicy) { + + } + + @Override + public void setCurrentCommandName(String name) { + } + + @Override + public void setCurrentCommandGroupId(Object groupId) { + } + + @Override + public Runnable getCurrentCommand() { + return null; + } + + @Override + public String getCurrentCommandName() { + return null; + } + + @Override + @Nullable + public Object getCurrentCommandGroupId() { + return null; + } + + @Override + public Project getCurrentCommandProject() { + return null; + } + + @Override + public void addCommandListener(@NotNull CommandListener listener) { + } + + @Override + public void addCommandListener(@NotNull CommandListener listener, @NotNull Disposable parentDisposable) { + } + + @Override + public void removeCommandListener(@NotNull CommandListener listener) { + } + + @Override + public boolean isUndoTransparentActionInProgress() { + return false; + } + + @Override + public void markCurrentCommandAsGlobal(Project project) { + + } + + @Override + public void runUndoTransparentAction(@NotNull Runnable action) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable command, String name, Object groupId, @NotNull UndoConfirmationPolicy confirmationPolicy, + Document document) { + } + + @Override + public void executeCommand(Project project, @NotNull Runnable runnable, @Nls String name, Object groupId, @Nullable Document document) { + + } + + @Override + public void addAffectedDocuments(Project project, @NotNull Document... docs) { + } + + @Override + public void addAffectedFiles(Project project, @NotNull VirtualFile... files) { + } +} diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java index 5478d0b84890..4a8ac05d43ff 100644 --- a/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java +++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFile.java @@ -3,15 +3,14 @@ */ package com.intellij.mock; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.openapi.vfs.*; +import com.intellij.util.LocalTimeCounter; import com.intellij.util.SmartList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -26,8 +25,8 @@ public class MockVirtualFile extends VirtualFile { private final boolean myDirectory; private final List myChildren = new SmartList(); private String myText; - private FileType myFileType; private final MockVirtualFileSystem myFileSystem = new MockVirtualFileSystem(); + private long myModStamp = LocalTimeCounter.currentTime(); public MockVirtualFile(final String name) { this(false, name); @@ -38,6 +37,12 @@ public class MockVirtualFile extends VirtualFile { myName = name; } + public MockVirtualFile(String name, String text) { + myName = name; + myText = text; + myDirectory = false; + } + public void setText(final String text) { myText = text; } @@ -73,9 +78,13 @@ public class MockVirtualFile extends VirtualFile { return prefix + "/" + myName; } + private boolean myIsWritable = true; @Override public boolean isWritable() { - throw new UnsupportedOperationException("Method isWritable is not yet implemented in " + getClass().getName()); + return myIsWritable; + } + public void setWritable(boolean b) { + myIsWritable = b; } @Override @@ -96,13 +105,28 @@ public class MockVirtualFile extends VirtualFile { @Override public VirtualFile[] getChildren() { - return (VirtualFile[])VfsUtil.toVirtualFileArray(myChildren); + return VfsUtil.toVirtualFileArray(myChildren); } @Override @NotNull - public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException { - throw new UnsupportedOperationException("Method getOutputStream is not yet implemented in " + getClass().getName()); + public OutputStream getOutputStream(Object requestor, final long newModificationStamp, long newTimeStamp) throws IOException { + return new ByteArrayOutputStream() { + @Override + public void close() { + myModStamp = newModificationStamp; + myText = toString(); + } + }; + } + + @Override + public long getModificationStamp() { + return myModStamp; + } + + public void setModificationStamp(long modStamp) { + myModStamp = modStamp; } @Override @@ -111,9 +135,11 @@ public class MockVirtualFile extends VirtualFile { return myText.getBytes(); } + + private final long myTimeStamp = System.currentTimeMillis(); @Override public long getTimeStamp() { - throw new UnsupportedOperationException("Method getTimeStamp is not yet implemented in " + getClass().getName()); + return myTimeStamp; } @Override @@ -123,7 +149,16 @@ public class MockVirtualFile extends VirtualFile { @Override public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) { - throw new UnsupportedOperationException("Method refresh is not yet implemented in " + getClass().getName()); + + } + + private long myActualTimeStamp = myTimeStamp; + public void setActualTimeStamp(long actualTimeStamp) { + myActualTimeStamp = actualTimeStamp; + } + + public long getActualTimeStamp() { + return myActualTimeStamp; } @Override @@ -131,6 +166,19 @@ public class MockVirtualFile extends VirtualFile { throw new UnsupportedOperationException("Method getInputStream is not yet implemented in " + getClass().getName()); } + private VirtualFileListener myListener = null; + public void setListener(VirtualFileListener listener) { + myListener = listener; + } + + public void setContent(Object requestor, String content, boolean fireEvent) { + long oldStamp = myModStamp; + myText = content; + if (fireEvent) { + myModStamp = LocalTimeCounter.currentTime(); + myListener.contentsChanged(new VirtualFileEvent(requestor, this, null, oldStamp, myModStamp)); + } + } } From 73e303d324b862b1e71982c18f5b2115c7a58ac7 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 26 Jan 2012 14:09:00 +0100 Subject: [PATCH 015/100] test for "Constant StringBuffer may be String" inspection --- ...ngBufferReplaceableByStringInspection.java | 39 +++++++------------ .../StringBufferReplaceableByString.java | 11 ++++++ .../expected.xml | 16 ++++++++ ...fferReplaceableByStringInspectionTest.java | 11 ++++++ 4 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java index 5d6be63483a9..15cb757ba90c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,8 +24,7 @@ import com.siyeh.ig.psiutils.TypeUtils; import com.siyeh.ig.psiutils.VariableAccessUtils; import org.jetbrains.annotations.NotNull; -public class StringBufferReplaceableByStringInspection - extends BaseInspection { +public class StringBufferReplaceableByStringInspection extends BaseInspection { @Override @NotNull @@ -46,21 +45,17 @@ public class StringBufferReplaceableByStringInspection return new StringBufferReplaceableByStringBuilderVisitor(); } - private static class StringBufferReplaceableByStringBuilderVisitor - extends BaseInspectionVisitor { + private static class StringBufferReplaceableByStringBuilderVisitor extends BaseInspectionVisitor { @Override public void visitLocalVariable(@NotNull PsiLocalVariable variable) { super.visitLocalVariable(variable); - - final PsiCodeBlock codeBlock = - PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class); + final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class); if (codeBlock == null) { return; } final PsiType type = variable.getType(); - if (!TypeUtils.typeEquals(CommonClassNames.JAVA_LANG_STRING_BUFFER, - type) && + if (!TypeUtils.typeEquals(CommonClassNames.JAVA_LANG_STRING_BUFFER, type) && !TypeUtils.typeEquals(CommonClassNames.JAVA_LANG_STRING_BUILDER, type)) { return; } @@ -80,8 +75,7 @@ public class StringBufferReplaceableByStringInspection if (VariableAccessUtils.variableIsReturned(variable, codeBlock)) { return; } - if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, - codeBlock)) { + if (VariableAccessUtils.variableIsPassedAsMethodArgument(variable, codeBlock)) { return; } if (variableIsModified(variable, codeBlock)) { @@ -90,16 +84,13 @@ public class StringBufferReplaceableByStringInspection registerVariableError(variable); } - public static boolean variableIsModified(PsiVariable variable, - PsiElement context) { - final VariableIsModifiedVisitor visitor = - new VariableIsModifiedVisitor(variable); + public static boolean variableIsModified(PsiVariable variable, PsiElement context) { + final VariableIsModifiedVisitor visitor = new VariableIsModifiedVisitor(variable); context.accept(visitor); return visitor.isModified(); } - private static boolean isNewStringBufferOrStringBuilder( - PsiExpression expression) { + private static boolean isNewStringBufferOrStringBuilder(PsiExpression expression) { if (expression == null) { return false; } @@ -107,16 +98,12 @@ public class StringBufferReplaceableByStringInspection return true; } else if (expression instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression methodCallExpression = - (PsiMethodCallExpression)expression; - if (!VariableIsModifiedVisitor.isStringBufferUpdate( - methodCallExpression)) { + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression; + if (!VariableIsModifiedVisitor.isStringBufferUpdate(methodCallExpression)) { return false; } - final PsiReferenceExpression methodExpression = - methodCallExpression.getMethodExpression(); - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); return isNewStringBufferOrStringBuilder(qualifier); } return false; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java new file mode 100644 index 000000000000..7f0eb5b6fbfa --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/StringBufferReplaceableByString.java @@ -0,0 +1,11 @@ +package com.siyeh.igtest.performance.constant_string_buffer_may_be_string; + +public class StringBufferReplaceableByString { + + StringBuilder foo() { + StringBuilder builder = new StringBuilder("asdfasdfasdf"); + StringBuffer buffer = new StringBuffer("test"); + StringBuilder result = new StringBuilder("return"); + return result; + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml new file mode 100644 index 000000000000..7ecadfbba1b4 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml @@ -0,0 +1,16 @@ + + + + StringBufferReplaceableByString.java + 6 + Constant StringBuffer may be String + Constant StringBuffer <code>builder</code> may be declared as String #loc + + + + StringBufferReplaceableByString.java + 7 + Constant StringBuffer may be String + Constant StringBuffer <code>buffer</code> may be declared as String #loc + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java new file mode 100644 index 000000000000..7b9a0e928b64 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferReplaceableByStringInspectionTest.java @@ -0,0 +1,11 @@ +package com.siyeh.ig.performance; + +import com.siyeh.ig.IGInspectionTestCase; + +public class StringBufferReplaceableByStringInspectionTest extends IGInspectionTestCase { + + public void test() throws Exception { + doTest("com/siyeh/igtest/performance/constant_string_buffer_may_be_string", + new StringBufferReplaceableByStringInspection()); + } +} \ No newline at end of file From 5613bcf15d5e39ecbcc10976ed4494fbfab80a0a Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 26 Jan 2012 17:09:16 +0300 Subject: [PATCH 016/100] IDEA-80368 (AE at com.intellij.codeInsight.completion.CodeCompletionHandlerBase$1$1.run) --- .../MavenRunnerParametersConfigurable.java | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java index 36a845b23737..60c0e8227f25 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenRunnerParametersConfigurable.java @@ -64,53 +64,55 @@ public abstract class MavenRunnerParametersConfigurable implements Configurable, } }); - MyCompletionProvider profilesCompletionProvider = new MyCompletionProvider(project) { - @Override - protected void addVariants(@NotNull CompletionResultSet result, MavenProjectsManager manager) { - for (String profile : manager.getAvailableProfiles()) { - result.addElement(LookupElementBuilder.create(profile)); + if (!project.isDefault()) { + MyCompletionProvider profilesCompletionProvider = new MyCompletionProvider(project) { + @Override + protected void addVariants(@NotNull CompletionResultSet result, MavenProjectsManager manager) { + for (String profile : manager.getAvailableProfiles()) { + result.addElement(LookupElementBuilder.create(profile)); + } } - } - }; - - profilesComponent.setComponent(profilesCompletionProvider.createEditor(project)); + }; - MyCompletionProvider goalsCompletionProvider = new MyCompletionProvider(project) { - - private volatile List myCachedElements; - - @Override - protected void addVariants(@NotNull CompletionResultSet result, MavenProjectsManager manager) { - List cachedElements = myCachedElements; - if (cachedElements == null) { - Set goals = new HashSet(); - goals.addAll(MavenConstants.PHASES); + profilesComponent.setComponent(profilesCompletionProvider.createEditor(project)); - for (MavenProject mavenProject : manager.getProjects()) { - for (MavenPlugin plugin : mavenProject.getPlugins()) { - MavenPluginInfo pluginInfo = MavenArtifactUtil.readPluginInfo(manager.getLocalRepository(), plugin.getMavenId()); - if (pluginInfo != null) { - for (MavenPluginInfo.Mojo mojo : pluginInfo.getMojos()) { - goals.add(mojo.getDisplayName()); + MyCompletionProvider goalsCompletionProvider = new MyCompletionProvider(project) { + + private volatile List myCachedElements; + + @Override + protected void addVariants(@NotNull CompletionResultSet result, MavenProjectsManager manager) { + List cachedElements = myCachedElements; + if (cachedElements == null) { + Set goals = new HashSet(); + goals.addAll(MavenConstants.PHASES); + + for (MavenProject mavenProject : manager.getProjects()) { + for (MavenPlugin plugin : mavenProject.getPlugins()) { + MavenPluginInfo pluginInfo = MavenArtifactUtil.readPluginInfo(manager.getLocalRepository(), plugin.getMavenId()); + if (pluginInfo != null) { + for (MavenPluginInfo.Mojo mojo : pluginInfo.getMojos()) { + goals.add(mojo.getDisplayName()); + } } } } + + cachedElements = new ArrayList(goals.size()); + for (String goal : goals) { + cachedElements.add(LookupElementBuilder.create(goal).setIcon(MavenIcons.PHASE_ICON)); + } + + myCachedElements = cachedElements; } - cachedElements = new ArrayList(goals.size()); - for (String goal : goals) { - cachedElements.add(LookupElementBuilder.create(goal).setIcon(MavenIcons.PHASE_ICON)); - } - - myCachedElements = cachedElements; + result.addAllElements(cachedElements); } + }; + + goalsComponent.setComponent(goalsCompletionProvider.createEditor(project)); + } - result.addAllElements(cachedElements); - } - }; - - goalsComponent.setComponent(goalsCompletionProvider.createEditor(project)); - setAnchor(profilesComponent.getLabel()); } From e34c877e5359e112ada6580c32760aa675b0882f Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 25 Jan 2012 02:11:11 +0400 Subject: [PATCH 017/100] create static field for comment types set to avoid token set creation on each relevant token during indexing --- .../intellij/plugins/relaxNG/compact/RncParserDefinition.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncParserDefinition.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncParserDefinition.java index ac48d70d1a94..431b40e345b0 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncParserDefinition.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/compact/RncParserDefinition.java @@ -43,6 +43,7 @@ import org.jetbrains.annotations.NotNull; */ public class RncParserDefinition implements ParserDefinition { public static final IFileElementType FILE_ELEMENT_TYPE = new IFileElementType(RngCompactLanguage.INSTANCE); + private static final TokenSet myCommentTypes = TokenSet.orSet(RncTokenTypes.COMMENTS, RncTokenTypes.DOC_TOKENS); @NotNull public Lexer createLexer(Project project) { @@ -64,7 +65,7 @@ public class RncParserDefinition implements ParserDefinition { @NotNull public TokenSet getCommentTokens() { - return TokenSet.orSet(RncTokenTypes.COMMENTS, RncTokenTypes.DOC_TOKENS); + return myCommentTypes; } @NotNull From 08674a48475eef33da3d66619687b26974c88187 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Wed, 25 Jan 2012 20:01:58 +0400 Subject: [PATCH 018/100] do not call bundle.message before actual reporting error --- .../lang/java/parser/DeclarationParser.java | 28 ++++++++++--------- .../lang/java/parser/ExpressionParser.java | 6 ++-- .../lang/java/parser/JavaParserUtil.java | 8 ++++-- .../lang/java/parser/ReferenceParser.java | 2 +- .../lang/java/parser/StatementParser.java | 4 +-- .../src/messages/JavaErrorMessages.properties | 1 + 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index ccb8e83f70e2..510cab79e4de 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -27,6 +27,7 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.PropertyKey; import static com.intellij.lang.PsiBuilderUtil.expect; import static com.intellij.lang.PsiBuilderUtil.nextTokenType; @@ -86,7 +87,7 @@ public class DeclarationParser { } parseClassBodyDeclarations(builderWrapper, isAnnotation); - expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace")); + expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace"); } @Nullable @@ -139,7 +140,7 @@ public class DeclarationParser { } if (declarationsAfterEnd) { - expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace")); + expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace"); } } @@ -426,7 +427,7 @@ public class DeclarationParser { final boolean anno, final boolean constructor) { parseParameterList(builder); - eatBrackets(builder, constructor, JavaErrorMessages.message("expected.semicolon")); + eatBrackets(builder, constructor, "expected.semicolon"); if (areTypeAnnotationsSupported(builder)) { final PsiBuilder.Marker receiver = builder.mark(); @@ -489,8 +490,8 @@ public class DeclarationParser { builder.advanceLexer(); final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA; - final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma"); - final String noElementMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter"); + final String noDelimiterMsg = resources ? "expected.semicolon" : "expected.comma"; + final String noElementMsg = resources ? "expected.resource" : "expected.parameter"; PsiBuilder.Marker invalidElements = null; String errorMessage = null; @@ -548,7 +549,7 @@ public class DeclarationParser { if (invalidElements == null) { if (builder.getTokenType() == delimiter) { - error(builder, noElementMsg); + error(builder, JavaErrorMessages.message(noElementMsg)); builder.advanceLexer(); if (noElements && resources) { noElements = false; @@ -557,7 +558,7 @@ public class DeclarationParser { } else { invalidElements = builder.mark(); - errorMessage = delimiterExpected ? noDelimiterMsg : noElementMsg; + errorMessage = JavaErrorMessages.message(delimiterExpected ? noDelimiterMsg : noElementMsg); } } @@ -613,7 +614,7 @@ public class DeclarationParser { if (expect(builder, JavaTokenType.IDENTIFIER)) { if (!resource) { - eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen")); + eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, "expected.rparen"); done(param, JavaElementType.PARAMETER); return param; } @@ -624,7 +625,7 @@ public class DeclarationParser { return modListInfo.first; } - if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) { + if (expectOrError(builder, JavaTokenType.EQ, "expected.eq")) { if (myExpressionParser.parse(builder) == null) { error(builder, JavaErrorMessages.message("expected.expression")); } @@ -720,7 +721,8 @@ public class DeclarationParser { return declaration; } - private static boolean eatBrackets(final PsiBuilder builder, final boolean isError, @Nullable final String error) { + private static boolean eatBrackets(final PsiBuilder builder, final boolean isError, + @Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) { if (builder.getTokenType() != JavaTokenType.LBRACKET) return true; final PsiBuilder.Marker marker = isError ? builder.mark() : null; @@ -735,7 +737,7 @@ public class DeclarationParser { } if (marker != null) { - marker.error(error); + marker.error(errorKey != null ? JavaErrorMessages.message(errorKey):null); } return result; @@ -840,9 +842,9 @@ public class DeclarationParser { pair = builder.mark(); } - final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier")); + final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier"); - expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq")); + expectOrError(builder, JavaTokenType.EQ, "expected.eq"); parseAnnotationValue(builder); diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index 8424d8defa81..d8ee0e01f8db 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -404,7 +404,7 @@ public class ExpressionParser { final PsiBuilder.Marker refExpr = expr.precede(); myReferenceParser.parseReferenceParameterList(builder, false, false); - if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"))) { + if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier")) { refExpr.done(JavaElementType.REFERENCE_EXPRESSION); startMarker.drop(); return refExpr; @@ -726,7 +726,7 @@ public class ExpressionParser { } bracketCount++; - if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) { + if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) { newExpr.done(JavaElementType.NEW_EXPRESSION); return newExpr; } @@ -812,7 +812,7 @@ public class ExpressionParser { } } - final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen")); + final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, "expected.rparen"); list.done(JavaElementType.EXPRESSION_LIST); if (!closed) { diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index d3fd09cc889f..6af4ce564138 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -39,6 +39,7 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.PropertyKey; import java.util.List; @@ -258,9 +259,10 @@ public class JavaParserUtil { } } - public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, final String errorMessage) { + public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, + @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorMessageKey) { if (!PsiBuilderUtil.expect(builder, expectedType)) { - error(builder, errorMessage); + error(builder, JavaErrorMessages.message(errorMessageKey)); return false; } return true; @@ -275,7 +277,7 @@ public class JavaParserUtil { } public static void semicolon(final PsiBuilder builder) { - expectOrError(builder, JavaTokenType.SEMICOLON, JavaErrorMessages.message("expected.semicolon")); + expectOrError(builder, JavaTokenType.SEMICOLON, "expected.semicolon"); } public static PsiBuilder braceMatchingBuilder(final PsiBuilder builder) { diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index 68fd2ff197e3..9382af0cac6b 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -293,7 +293,7 @@ public class ReferenceParser { if (expect(builder, JavaTokenType.GT)) { break; } - else if (!expectOrError(builder, JavaTokenType.COMMA, JavaErrorMessages.message("expected.gt.or.comma"))) { + else if (!expectOrError(builder, JavaTokenType.COMMA, "expected.gt.or.comma")) { isOk = false; break; } diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java index b4294f6a4cd9..95ad7cfd72a8 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java @@ -131,7 +131,7 @@ public class StatementParser { parseStatements(builder, parseUntilEof ? BraceMode.TILL_LAST : BraceMode.TILL_FIRST); - final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace")); + final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace"); builder.getTokenType(); // eat spaces done(codeBlock, JavaElementType.CODE_BLOCK); @@ -543,7 +543,7 @@ public class StatementParser { } } - expectOrError(builder, JavaTokenType.COLON, JavaErrorMessages.message("expected.colon")); + expectOrError(builder, JavaTokenType.COLON, "expected.colon"); done(statement, JavaElementType.SWITCH_LABEL_STATEMENT); return statement; diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 317aeb1326bb..1c83fe4b3480 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -328,6 +328,7 @@ expected.lparen.or.lbracket='(' or '[' expected expected.array.initializer=Array initializer expected unexpected.tokens=Unexpected tokens expected.gt.or.comma='>' or ',' expected. +string.expected=String literal expected else.without.if='else' without 'if' catch.without.try='catch' without 'try' finally.without.try='finally' without 'try' From 1fd9395de4046946ce1e1e929b57360d80e5083e Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 26 Jan 2012 17:28:13 +0400 Subject: [PATCH 019/100] less garbage and synchronization during building indexed --- .../intellij/images/util/ImageInfoReader.java | 3 +- .../psi/stubs/SerializedStubTree.java | 5 +- .../BufferExposingByteArrayInputStream.java | 7 +- .../BufferExposingByteArrayOutputStream.java | 16 ++- .../com/intellij/util/io/IntToIntBtree.java | 11 +- .../util/io/PersistentBTreeEnumerator.java | 17 +-- .../intellij/util/io/PersistentHashMap.java | 111 +++++++----------- .../io/PersistentHashMapValueStorage.java | 7 +- .../util/io/UnsyncByteArrayInputStream.java | 69 +++++++++++ .../util/io/UnsyncByteArrayOutputStream.java | 77 ++++++++++++ .../util/io/storage/AbstractStorage.java | 3 +- .../properties/xml/XmlPropertiesIndex.java | 7 +- .../com/intellij/util/xml/DomFileIndex.java | 4 +- .../intellij/xml/index/XmlNamespaceIndex.java | 4 +- .../intellij/xml/index/XmlTagNamesIndex.java | 4 +- 15 files changed, 234 insertions(+), 111 deletions(-) create mode 100644 platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java create mode 100644 platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java diff --git a/images/src/org/intellij/images/util/ImageInfoReader.java b/images/src/org/intellij/images/util/ImageInfoReader.java index 1c809bbba28f..7dd764faa328 100644 --- a/images/src/org/intellij/images/util/ImageInfoReader.java +++ b/images/src/org/intellij/images/util/ImageInfoReader.java @@ -16,6 +16,7 @@ package org.intellij.images.util; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -65,7 +66,7 @@ public class ImageInfoReader { @Nullable private static Info read(@NotNull final byte[] data) { - final DataInputStream is = new DataInputStream(new ByteArrayInputStream(data)); + final DataInputStream is = new DataInputStream(new UnsyncByteArrayInputStream(data)); try { return readFileData(is); } diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java index abaf63828b69..d7423c8420b2 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/SerializedStubTree.java @@ -19,7 +19,8 @@ */ package com.intellij.psi.stubs; -import java.io.ByteArrayInputStream; +import com.intellij.util.io.UnsyncByteArrayInputStream; + import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; @@ -45,7 +46,7 @@ public class SerializedStubTree { } public StubElement getStub() { - return SerializationManager.getInstance().deserialize(new ByteArrayInputStream(myBytes)); + return SerializationManager.getInstance().deserialize(new UnsyncByteArrayInputStream(myBytes)); } public boolean equals(final Object that) { diff --git a/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayInputStream.java b/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayInputStream.java index d0c9412efe07..9a2efb3e2ba7 100644 --- a/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayInputStream.java +++ b/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayInputStream.java @@ -15,17 +15,16 @@ */ package com.intellij.openapi.util.io; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NotNull; -import java.io.ByteArrayInputStream; - -public class BufferExposingByteArrayInputStream extends ByteArrayInputStream { +public class BufferExposingByteArrayInputStream extends UnsyncByteArrayInputStream { public BufferExposingByteArrayInputStream(@NotNull byte[] bytes) { super(bytes); } @NotNull public byte[] getInternalBuffer() { - return buf; + return myBuffer; } } diff --git a/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayOutputStream.java b/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayOutputStream.java index 61fe2ea73020..990088c1842f 100644 --- a/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayOutputStream.java +++ b/platform/util/src/com/intellij/openapi/util/io/BufferExposingByteArrayOutputStream.java @@ -15,13 +15,11 @@ */ package com.intellij.openapi.util.io; +import com.intellij.util.io.UnsyncByteArrayOutputStream; import org.jetbrains.annotations.NotNull; -import java.io.ByteArrayOutputStream; - -public class BufferExposingByteArrayOutputStream extends ByteArrayOutputStream { - public BufferExposingByteArrayOutputStream() { - } +public class BufferExposingByteArrayOutputStream extends UnsyncByteArrayOutputStream { + public BufferExposingByteArrayOutputStream() {} public BufferExposingByteArrayOutputStream(int size) { super(size); @@ -29,14 +27,14 @@ public class BufferExposingByteArrayOutputStream extends ByteArrayOutputStream { @NotNull public byte[] getInternalBuffer() { - return buf; + return myBuffer; } // moves back the written bytes pointer by {@link #size}, to "unwrite" last {@link #size} bytes public int backOff(int size) { assert size >= 0 : size; - count -= size; - assert count >= 0 : count; - return count; + myCount -= size; + assert myCount >= 0 : myCount; + return myCount; } } diff --git a/platform/util/src/com/intellij/util/io/IntToIntBtree.java b/platform/util/src/com/intellij/util/io/IntToIntBtree.java index 8df25adaa3b8..5c73f192038d 100644 --- a/platform/util/src/com/intellij/util/io/IntToIntBtree.java +++ b/platform/util/src/com/intellij/util/io/IntToIntBtree.java @@ -2,7 +2,6 @@ package com.intellij.util.io; import com.intellij.openapi.util.io.FileUtil; import gnu.trove.TIntIntHashMap; -import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; @@ -130,10 +129,11 @@ class IntToIntBtree { return pageStart; } - public @Nullable Integer get(int key) { + public boolean get(int key, int[] result) { if (hasCachedMappings) { if (myCachedMappings.containsKey(key)) { - return myCachedMappings.get(key); + result[0] = myCachedMappings.get(key); + return true; } } @@ -141,8 +141,9 @@ class IntToIntBtree { currentIndexNode.setAddress(root.address); int index = currentIndexNode.locate(key, false); - if (index < 0) return null; - return currentIndexNode.addressAt(index); + if (index < 0) return false; + result[0] = currentIndexNode.addressAt(index); + return true; } public void put(int key, int value) { diff --git a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java index f99784a9d79d..5c21065d3a33 100644 --- a/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java +++ b/platform/util/src/com/intellij/util/io/PersistentBTreeEnumerator.java @@ -186,9 +186,11 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase 0) { if (!p.process(record)) return false; } else { @@ -259,22 +261,23 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase 0) { @@ -309,7 +312,7 @@ public class PersistentBTreeEnumerator extends PersistentEnumeratorBase extends PersistentEnumeratorDelegate< super(new BufferExposingByteArrayOutputStream()); } - public int getBufferSize() { - return ((ByteArrayOutputStream)out).size(); + private void reset() { + ((UnsyncByteArrayOutputStream)out).reset(); } - public void writeTo(OutputStream stream) throws IOException { - ((ByteArrayOutputStream)out).writeTo(stream); - } - - public void reset() { - ((ByteArrayOutputStream)out).reset(); - } - - public byte[] toByteArray() { - return ((ByteArrayOutputStream)out).toByteArray(); - } - - public ByteSequence getInternalBuffer() { - final BufferExposingByteArrayOutputStream _out = (BufferExposingByteArrayOutputStream)out; - return new ByteSequence(_out.getInternalBuffer(), 0, _out.size()); + private BufferExposingByteArrayOutputStream getInternalBuffer() { + return (BufferExposingByteArrayOutputStream)out; } } @@ -110,16 +97,14 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< protected void onDropFromCache(final Key key, final AppendStream value) { synchronized (PersistentEnumerator.ourLock) { try { - final ByteSequence bytes = value.getInternalBuffer(); + final BufferExposingByteArrayOutputStream bytes = value.getInternalBuffer(); final int id = enumerate(key); - HeaderRecord oldHeaderRecord = readValueId(id); + long oldHeaderRecord = readValueId(id); - HeaderRecord headerRecord = new HeaderRecord( - myValueStorage.appendBytes(bytes, oldHeaderRecord.address) - ); + long headerRecord = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), oldHeaderRecord); updateValueId(id, headerRecord, oldHeaderRecord, key, 0); - if (oldHeaderRecord == HeaderRecord.EMPTY) { + if (oldHeaderRecord == NULL_ADDR) { myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } @@ -266,18 +251,18 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< final AppendStream record = new AppendStream(); myValueExternalizer.save(record, value); - final ByteSequence bytes = record.getInternalBuffer(); + final BufferExposingByteArrayOutputStream bytes = record.getInternalBuffer(); final int id = enumerate(key); - HeaderRecord oldheader = readValueId(id); - if (oldheader != HeaderRecord.EMPTY) { + long oldheader = readValueId(id); + if (oldheader != NULL_ADDR) { myLiveAndGarbageKeysCounter++; } else { myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } - HeaderRecord header = new HeaderRecord(myValueStorage.appendBytes(bytes, 0)); + long header = myValueStorage.appendBytes(bytes.getInternalBuffer(), 0, bytes.size(), 0); updateValueId(id, header, oldheader, key, 0); } @@ -330,41 +315,39 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< myAppendCache.clear(); return myEnumerator.processAllDataObject(processor, new PersistentEnumerator.DataFilter() { public boolean accept(final int id) { - return readValueId(id).address != NULL_ADDR; + return readValueId(id) != NULL_ADDR; } }); } } - public final Value get(Key key) throws IOException { + public final @Nullable Value get(Key key) throws IOException { synchronized (myEnumerator) { return doGet(key); } } - protected Value doGet(Key key) throws IOException { + protected @Nullable Value doGet(Key key) throws IOException { synchronized (PersistentEnumerator.ourLock) { myAppendCache.remove(key); final int id = tryEnumerate(key); if (id == PersistentEnumerator.NULL_ID) { return null; } - final HeaderRecord oldHeader = readValueId(id); - if (oldHeader.address == PersistentEnumerator.NULL_ID) { + final long oldHeader = readValueId(id); + if (oldHeader == PersistentEnumerator.NULL_ID) { return null; } - Pair readResult = myValueStorage.readBytes(oldHeader.address); - if (readResult.first != null && readResult.first != oldHeader.address) { + Pair readResult = myValueStorage.readBytes(oldHeader); + if (readResult.first != null && readResult.first != oldHeader) { myEnumerator.markDirty(true); - updateValueId(id, new HeaderRecord(readResult.first), oldHeader, key, 0); - if (oldHeader != HeaderRecord.EMPTY) { - myLiveAndGarbageKeysCounter++; - } + updateValueId(id, readResult.first, oldHeader, key, 0); + myLiveAndGarbageKeysCounter++; } - final DataInputStream input = new DataInputStream(new ByteArrayInputStream(readResult.second)); + final DataInputStream input = new DataInputStream(new UnsyncByteArrayInputStream(readResult.second)); try { return myValueExternalizer.read(input); } @@ -387,7 +370,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< if (id == PersistentEnumerator.NULL_ID) { return false; } - return readValueId(id).address != NULL_ADDR; + return readValueId(id) != NULL_ADDR; } } @@ -406,12 +389,12 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } myEnumerator.markDirty(true); - final HeaderRecord record = readValueId(id); - if (record != HeaderRecord.EMPTY) { + final long record = readValueId(id); + if (record != NULL_ADDR) { myLiveAndGarbageKeysCounter++; } - updateValueId(id, HeaderRecord.EMPTY, record, key, 0); + updateValueId(id, NULL_ADDR, record, key, 0); } } @@ -473,10 +456,10 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< traverseAllRecords(new PersistentEnumerator.RecordsProcessor() { public boolean process(final int keyId) throws IOException { - final HeaderRecord record = readValueId(keyId); - if (record.address != NULL_ADDR) { - Pair readResult = myValueStorage.readBytes(record.address); - HeaderRecord value = new HeaderRecord(newStorage.appendBytes(new ByteSequence(readResult.second), 0)); + final long record = readValueId(keyId); + if (record != NULL_ADDR) { + Pair readResult = myValueStorage.readBytes(record); + long value = newStorage.appendBytes(new ByteSequence(readResult.second), 0); updateValueId(keyId, value, record, null, getCurrentKey()); myLiveAndGarbageKeysCounter += LIVE_KEY_MASK; } @@ -496,10 +479,10 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } } - private HeaderRecord readValueId(final int keyId) { + private long readValueId(final int keyId) { long address = myEnumerator.myStorage.getInt(keyId + myParentValueRefOffset); if (address == 0 || address == -POSITIVE_VALUE_SHIFT) { - return HeaderRecord.EMPTY; + return NULL_ADDR; } if (address < 0) { @@ -509,7 +492,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< address = ((address << 32) + value) & ~USED_LONG_VALUE_MASK; } - return new HeaderRecord(address); + return address; } private int smallKeys; @@ -517,19 +500,19 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< private int transformedKeys; private int requests; - private int updateValueId(int keyId, HeaderRecord value, HeaderRecord oldValue, @Nullable Key key, int processingKey) throws IOException { - final boolean newKey = oldValue == null || oldValue.address == NULL_ADDR; + private int updateValueId(int keyId, long value, long oldValue, @Nullable Key key, int processingKey) throws IOException { + final boolean newKey = oldValue == NULL_ADDR; if (newKey) ++requests; boolean defaultSizeInfo = true; if (myCanReEnumerate) { - if (canUseIntAddressForNewRecord(value.address)) { + if (canUseIntAddressForNewRecord(value)) { defaultSizeInfo = false; - myEnumerator.myStorage.putInt(keyId + myParentValueRefOffset, -(int)(value.address + POSITIVE_VALUE_SHIFT)); + myEnumerator.myStorage.putInt(keyId + myParentValueRefOffset, -(int)(value + POSITIVE_VALUE_SHIFT)); if (newKey) ++smallKeys; } else { if (newKey && myWatermarkId == 0) myWatermarkId = keyId; - if (keyId < myWatermarkId && (oldValue == null || canUseIntAddressForNewRecord(oldValue.address))) { + if (keyId < myWatermarkId && (oldValue == NULL_ADDR || canUseIntAddressForNewRecord(oldValue))) { // keyId is result of enumerate, if we do reenumerate then it is no longer accessible unless somebody cached it myIntAddressForNewRecord = false; keyId = myEnumerator.reenumerate(key == null ? myEnumerator.getValue(keyId, processingKey) : key); @@ -539,7 +522,7 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< } if (defaultSizeInfo) { - myEnumerator.myStorage.putLong(keyId + myParentValueRefOffset, value.address | USED_LONG_VALUE_MASK); + myEnumerator.myStorage.putLong(keyId + myParentValueRefOffset, value | USED_LONG_VALUE_MASK); if (newKey) ++largeKeys; } @@ -548,21 +531,11 @@ public class PersistentHashMap extends PersistentEnumeratorDelegate< ",@"+getBaseFile().getPath()); } if (doHardConsistencyChecks) { - HeaderRecord checkRecord = readValueId(keyId); - if (checkRecord.address != value.address) { - assert false:value.address; + long checkRecord = readValueId(keyId); + if (checkRecord != value) { + assert false:value; } } return keyId; } - - private static class HeaderRecord { - final long address; - - HeaderRecord(long address) { - this.address = address; - } - - static final HeaderRecord EMPTY = new HeaderRecord(NULL_ADDR); - } } diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java index 6edddcd02ace..26daa4379a9c 100644 --- a/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java +++ b/platform/util/src/com/intellij/util/io/PersistentHashMapValueStorage.java @@ -79,10 +79,13 @@ public class PersistentHashMapValueStorage { private static final int INT_LENGTH_LONG_ADDRESS = 4 + 8; public long appendBytes(ByteSequence data, long prevChunkAddress) throws IOException { + return appendBytes(data.getBytes(), data.getOffset(), data.getLength(), prevChunkAddress); + } + + public long appendBytes(byte[] data, int offset, int dataLength, long prevChunkAddress) throws IOException { assert !myCompactionMode; long result = mySize; final CacheValue appender = ourAppendersCache.get(myPath); - int dataLength = data.getLength(); int serviceFieldsSizeIncrease; try { @@ -102,7 +105,7 @@ public class PersistentHashMapValueStorage { dataOutputStream.writeLong(prevChunkAddress); serviceFieldsSizeIncrease = INT_LENGTH_LONG_ADDRESS; } - dataOutputStream.write(data.getBytes(), data.getOffset(), dataLength); + dataOutputStream.write(data, offset, dataLength); if (requests % IOStatistics.KEYS_FACTOR == 0 && IOStatistics.DEBUG) { IOStatistics.dump("Small writes:"+smallWritesCount +", bytes:"+smallWrites + ", largeWrites:"+largeWritesCount + ", bytes:"+largeWrites+", total:"+requests + "@"+myFile.getPath()); diff --git a/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java b/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java new file mode 100644 index 000000000000..c22a9ecb0818 --- /dev/null +++ b/platform/util/src/com/intellij/util/io/UnsyncByteArrayInputStream.java @@ -0,0 +1,69 @@ +package com.intellij.util.io; + +import java.io.InputStream; + +public class UnsyncByteArrayInputStream extends InputStream { + protected byte[] myBuffer; + private int myPosition; + private int myCount; + private int myMarkedPosition; + + public UnsyncByteArrayInputStream(byte buf[]) { + this.myBuffer = buf; + this.myPosition = 0; + this.myCount = buf.length; + } + + public int read() { + return (myPosition < myCount) ? (myBuffer[myPosition++] & 0xff) : -1; + } + + public int read(byte b[], int off, int len) { + if (b == null) { + throw new NullPointerException(); + } else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + if (myPosition >= myCount) { + return -1; + } + if (myPosition + len > myCount) { + len = myCount - myPosition; + } + if (len <= 0) { + return 0; + } + System.arraycopy(myBuffer, myPosition, b, off, len); + myPosition += len; + return len; + } + + public long skip(long n) { + if (myPosition + n > myCount) { + n = myCount - myPosition; + } + if (n < 0) { + return 0; + } + myPosition += n; + return n; + } + + public int available() { + return myCount - myPosition; + } + + @Override + public boolean markSupported() { + return true; + } + + @Override + public void mark(int readlimit) { + myMarkedPosition = myPosition; + } + + public void reset() { + myPosition = myMarkedPosition; + } +} diff --git a/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java b/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java new file mode 100644 index 000000000000..3ba1db36b94b --- /dev/null +++ b/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java @@ -0,0 +1,77 @@ +/* + * Copyright 2000-2012 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.util.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Arrays; + +public class UnsyncByteArrayOutputStream extends OutputStream { + protected byte[] myBuffer; + protected int myCount; + + public UnsyncByteArrayOutputStream() { + this(32); + } + + public UnsyncByteArrayOutputStream(int size) { + myBuffer = new byte[size]; + } + + public void write(int b) { + int newcount = myCount + 1; + if (newcount > myBuffer.length) { + myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount)); + } + myBuffer[myCount] = (byte)b; + myCount = newcount; + } + + public void write(byte b[], int off, int len) { + if ((off < 0) || (off > b.length) || (len < 0) || + ((off + len) > b.length) || ((off + len) < 0)) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + int newcount = myCount + len; + if (newcount > myBuffer.length) { + myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount)); + } + System.arraycopy(b, off, myBuffer, myCount, len); + myCount = newcount; + } + + public void writeTo(OutputStream out) throws IOException { + out.write(myBuffer, 0, myCount); + } + + public void reset() { + myCount = 0; + } + + public byte[] toByteArray() { + return Arrays.copyOf(myBuffer, myCount); + } + + public int size() { + return myCount; + } + + public String toString() { + return new String(myBuffer, 0, myCount); + } +} diff --git a/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java b/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java index 8051d48d0b82..e98173172044 100644 --- a/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java +++ b/platform/util/src/com/intellij/util/io/storage/AbstractStorage.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.io.PagePool; import com.intellij.util.io.RecordDataOutput; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NonNls; import java.io.*; @@ -228,7 +229,7 @@ public abstract class AbstractStorage implements Disposable, Forceable { public DataInputStream readStream(int record) throws IOException { final byte[] bytes = readBytes(record); - return new DataInputStream(new ByteArrayInputStream(bytes)); + return new DataInputStream(new UnsyncByteArrayInputStream(bytes)); } protected byte[] readBytes(int record) throws IOException { diff --git a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java index a0473e9fa33b..827c08987a22 100644 --- a/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java +++ b/plugins/properties/src/com/intellij/lang/properties/xml/XmlPropertiesIndex.java @@ -5,10 +5,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.StreamUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.indexing.*; -import com.intellij.util.io.DataExternalizer; -import com.intellij.util.io.EnumeratorStringDescriptor; -import com.intellij.util.io.IOUtil; -import com.intellij.util.io.KeyDescriptor; +import com.intellij.util.io.*; import com.intellij.util.xml.NanoXmlUtil; import net.n3.nanoxml.StdXMLReader; import org.jetbrains.annotations.NotNull; @@ -91,7 +88,7 @@ public class XmlPropertiesIndex extends FileBasedIndexExtension{ @NotNull public Map map(final FileContent inputData) { final Set namespaces = new THashSet(); - final XmlFileHeader header = NanoXmlUtil.parseHeader(new ByteArrayInputStream(inputData.getContent())); + final XmlFileHeader header = NanoXmlUtil.parseHeader(new UnsyncByteArrayInputStream(inputData.getContent())); ContainerUtil.addIfNotNull(header.getPublicId(), namespaces); ContainerUtil.addIfNotNull(header.getSystemId(), namespaces); ContainerUtil.addIfNotNull(header.getRootTagNamespace(), namespaces); diff --git a/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java index 8cd41a372f2e..5af871e438af 100644 --- a/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java +++ b/xml/impl/src/com/intellij/xml/index/XmlNamespaceIndex.java @@ -24,10 +24,10 @@ import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.indexing.FileContent; import com.intellij.util.indexing.ID; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.ByteArrayInputStream; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -67,7 +67,7 @@ public class XmlNamespaceIndex extends XmlIndex { return new DataIndexer() { @NotNull public Map map(final FileContent inputData) { - final String ns = XsdNamespaceBuilder.computeNamespace(new ByteArrayInputStream(inputData.getContent())); + final String ns = XsdNamespaceBuilder.computeNamespace(new UnsyncByteArrayInputStream(inputData.getContent())); final HashMap map = new HashMap(2); if (ns != null) { map.put(ns, ""); diff --git a/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java index b18d184ca698..a8d1901574a3 100644 --- a/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java +++ b/xml/impl/src/com/intellij/xml/index/XmlTagNamesIndex.java @@ -20,9 +20,9 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.HashMap; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; +import com.intellij.util.io.UnsyncByteArrayInputStream; import org.jetbrains.annotations.NotNull; -import java.io.ByteArrayInputStream; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -50,7 +50,7 @@ public class XmlTagNamesIndex extends XmlIndex { return new DataIndexer() { @NotNull public Map map(final FileContent inputData) { - final Collection tags = XsdTagNameBuilder.computeTagNames(new ByteArrayInputStream(inputData.getContent())); + final Collection tags = XsdTagNameBuilder.computeTagNames(new UnsyncByteArrayInputStream(inputData.getContent())); if (tags != null && !tags.isEmpty()) { final HashMap map = new HashMap(tags.size()); for (String tag : tags) { From 37f420c1506207c55639f393bac551ce8aec77c9 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jan 2012 12:22:20 +0400 Subject: [PATCH 020/100] typo --- .../lang/cacheBuilder/DefaultWordsScanner.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java b/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java index 3c87dda6701c..8f777e4864c9 100644 --- a/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java +++ b/platform/lang-api/src/com/intellij/lang/cacheBuilder/DefaultWordsScanner.java @@ -51,29 +51,29 @@ public class DefaultWordsScanner implements WordsScanner { public void processWords(CharSequence fileText, Processor processor) { myLexer.start(fileText); - WordOccurrence occurence = null; // shared occurence + WordOccurrence occurrence = null; // shared occurrence while (myLexer.getTokenType() != null) { final IElementType type = myLexer.getTokenType(); if (myIdentifierTokenSet.contains(type)) { - if (occurence == null) { - occurence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE); + if (occurrence == null) { + occurrence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE); } else { - occurence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE); + occurrence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE); } - if (!processor.process(occurence)) return; + if (!processor.process(occurrence)) return; } else if (myCommentTokenSet.contains(type)) { - if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurence, false)) return; + if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurrence, false)) return; } else if (myLiteralTokenSet.contains(type)) { - if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurence, myMayHaveFileRefsInLiterals)) return; + if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurrence, myMayHaveFileRefsInLiterals)) return; } else { // process all word-like characters as words // Plugin writers may have (Maximka in JavaScript especially) some keyword token types omitted from the identifierTokenSet - if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurence, false)) return; + if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurrence, false)) return; } myLexer.advance(); } From 3455c92bde19fb6387ff9d162b5b299cedc9f55f Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Jan 2012 13:43:35 +0400 Subject: [PATCH 021/100] IDEA-79352: PyCharm 2.0.1 shows nice error box for trac after test button --- .../src/com/intellij/tasks/trac/TracRepository.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java index 5ce6d6c4b299..136ed2161ebd 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java @@ -57,10 +57,8 @@ public class TracRepository extends BaseRepositoryImpl { String search = myDefaultSearch + "&max=" + max; if (myMaxSupported == null) { try { + myMaxSupported = true; result = runQuery(query, transport, client, search); - if (result != null) { - myMaxSupported = true; - } } catch (XmlRpcException e) { if (e.getMessage().contains("t.max")) { From 6774df98e8741d99595acda35e2f030ecf5b976c Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 25 Jan 2012 12:05:25 +0400 Subject: [PATCH 022/100] removed dependency on xml-rpc --- .../tasks/jira-connector/jira-connector.iml | 1 - .../tasks/jira/HttpClientTransport.java | 45 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/HttpClientTransport.java diff --git a/plugins/tasks/jira-connector/jira-connector.iml b/plugins/tasks/jira-connector/jira-connector.iml index e47df2880a1f..8be54150f15d 100644 --- a/plugins/tasks/jira-connector/jira-connector.iml +++ b/plugins/tasks/jira-connector/jira-connector.iml @@ -12,7 +12,6 @@ - diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/HttpClientTransport.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/HttpClientTransport.java deleted file mode 100644 index 669fd13e0bb9..000000000000 --- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/HttpClientTransport.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.intellij.tasks.jira; - -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.xmlrpc.XmlRpc; -import org.apache.xmlrpc.XmlRpcClientException; -import org.apache.xmlrpc.XmlRpcTransport; - -import java.io.IOException; -import java.io.InputStream; - -public class HttpClientTransport implements XmlRpcTransport { - - private final String myUrl; - private final HttpClient myHttpClient; - private final Header myUserAgentHeader = new Header("User-Agent", XmlRpc.version); - private PostMethod myMethod; - - public HttpClientTransport(String url, HttpClient httpClient) { - myUrl = url; - myHttpClient = httpClient; - } - - public InputStream sendXmlRpc(byte[] request) throws IOException, XmlRpcClientException { - myMethod = new PostMethod(myUrl); - myMethod.setRequestHeader(new Header("Content-Type", "text/xml")); - myMethod.setRequestHeader(myUserAgentHeader); - myMethod.setRequestEntity(new ByteArrayRequestEntity(request)); - - configureMethod(myMethod); - - myHttpClient.executeMethod(myMethod); - return myMethod.getResponseBodyAsStream(); - } - - protected void configureMethod(HttpMethod method) { - } - - public void endClientRequest() throws XmlRpcClientException { - myMethod.releaseConnection(); - } -} From 272f420d1f95f3e4dd41201d5df3b46147dc197d Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 26 Jan 2012 14:44:02 +0400 Subject: [PATCH 023/100] setPlatformPrefix() extracted --- .../com/intellij/testFramework/PlatformTestCase.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 8ee4505c515a..d575d7df5019 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -145,10 +145,10 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro if (resource == null) { resource = PlatformTestCase.class.getClassLoader().getResource("idea/IdeaApplicationInfo.xml"); if (resource == null) { - System.setProperty("idea.platform.prefix", "PlatformLangXml"); + setPlatformPrefix("PlatformLangXml"); } else { - System.setProperty("idea.platform.prefix", "Idea"); + setPlatformPrefix("Idea"); } } } @@ -742,11 +742,15 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro isUltimate = false; } if (!isUltimate) { - System.setProperty("idea.platform.prefix", prefix); + setPlatformPrefix(prefix); } } } + public static void setPlatformPrefix(String prefix) { + System.setProperty("idea.platform.prefix", prefix); + } + @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface WrapInCommand {} From d35c11949ec275bceba2e31f551ad3c5bd710ed3 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Thu, 26 Jan 2012 17:48:29 +0400 Subject: [PATCH 024/100] IDEA-75975 Wrong coding in Open Task from --- .../intellij/tasks/trac/TracRepository.java | 11 ++-- plugins/tasks/tasks-tests/tasks-tests.iml | 2 + .../integration/TracIntegrationTest.java | 57 +++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/TracIntegrationTest.java diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java index 136ed2161ebd..a4cb3f78ca89 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trac/TracRepository.java @@ -23,10 +23,7 @@ import com.intellij.tasks.impl.BaseRepositoryImpl; import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; -import org.apache.xmlrpc.CommonsXmlRpcTransport; -import org.apache.xmlrpc.XmlRpcClient; -import org.apache.xmlrpc.XmlRpcException; -import org.apache.xmlrpc.XmlRpcRequest; +import org.apache.xmlrpc.*; import org.jetbrains.annotations.Nullable; import java.io.IOException; @@ -41,6 +38,10 @@ import java.util.*; @SuppressWarnings({"UseOfObsoleteCollectionType", "unchecked"}) public class TracRepository extends BaseRepositoryImpl { + static { + XmlRpc.setDefaultInputEncoding("UTF-8"); + } + private String myDefaultSearch = "status!=closed&owner={username}&summary~={query}"; private Boolean myMaxSupported; @@ -96,7 +97,7 @@ public class TracRepository extends BaseRepositoryImpl { } private XmlRpcClient getRpcClient() throws MalformedURLException { - return new XmlRpcClient(new URL(getUrl())); + return new XmlRpcClient(getUrl()); } @Override diff --git a/plugins/tasks/tasks-tests/tasks-tests.iml b/plugins/tasks/tasks-tests/tasks-tests.iml index f59b8dfccb7e..668e75245368 100644 --- a/plugins/tasks/tasks-tests/tasks-tests.iml +++ b/plugins/tasks/tasks-tests/tasks-tests.iml @@ -14,6 +14,8 @@ + + diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/TracIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/TracIntegrationTest.java new file mode 100644 index 000000000000..61a0b8f76323 --- /dev/null +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/TracIntegrationTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2000-2012 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.tasks.integration; + +import com.intellij.tasks.Task; +import com.intellij.tasks.TaskManagerTestCase; +import com.intellij.tasks.trac.TracRepository; +import org.apache.xmlrpc.CommonsXmlRpcTransport; +import org.apache.xmlrpc.XmlRpc; +import org.apache.xmlrpc.XmlRpcClient; +import org.apache.xmlrpc.XmlRpcRequest; + +import java.net.URL; +import java.util.Arrays; +import java.util.Vector; + +/** + * @author Dmitry Avdeev + * Date: 1/25/12 + */ +public abstract class TracIntegrationTest extends TaskManagerTestCase { + + public void testTracEncoding() throws Exception { + + XmlRpc.setDefaultInputEncoding("UTF-8"); + XmlRpcClient client = new XmlRpcClient("http://trac.shopware.de/trac/login/rpc"); + // client.setBasicAuthentication(); + + CommonsXmlRpcTransport transport = new CommonsXmlRpcTransport(new URL("http://trac.shopware.de/trac/login/rpc")); + transport.setBasicAuthentication("jetbrains", "jetbrains"); + Object o = client.execute(new XmlRpcRequest("ticket.get", new Vector(Arrays.asList("5358"))), + transport); + + System.out.println(o); + + TracRepository repository = new TracRepository(); + repository.setPassword("jetbrains"); + repository.setUsername("jetbrains"); + repository.setUrl("http://trac.shopware.de/trac/login/rpc"); + Task[] issues = repository.getIssues("", 10, 0); + Task task = repository.findTask("5358"); + System.out.println(task.getDescription()); + } +} From 07371921553bd2ad2c757fc15bba9e1d337f2493 Mon Sep 17 00:00:00 2001 From: "Alexander.Podkhalyuzin" Date: Thu, 26 Jan 2012 18:33:34 +0400 Subject: [PATCH 025/100] Additional constructor to RequestHint.SmartStepFilter. --- .../com/intellij/debugger/engine/RequestHint.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/RequestHint.java b/java/debugger/impl/src/com/intellij/debugger/engine/RequestHint.java index 08bafc3e50cd..1a94cbc25ec4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/RequestHint.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/RequestHint.java @@ -61,9 +61,16 @@ public class RequestHint { private boolean myMethodExecuted; public SmartStepFilter(PsiMethod psiMethod) { - myDeclaringClassName = JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass()); - myTargetMethodName = psiMethod.isConstructor()? "" : psiMethod.getName(); - myTargetMethodSignature = JVMNameUtil.getJVMSignature(psiMethod); + this(JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass()), + psiMethod.isConstructor()? "" : psiMethod.getName(), + JVMNameUtil.getJVMSignature(psiMethod)); + } + + public SmartStepFilter(@NotNull JVMName declaringClassName, @NonNls String targetMethodName, + @NotNull JVMName targetMethodSignature) { + myDeclaringClassName = declaringClassName; + myTargetMethodName = targetMethodName; + myTargetMethodSignature = targetMethodSignature; } public String getTargetMethodName() { From 904dc6fa98354446d1c5f41f0372b6e28a3aa744 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 26 Jan 2012 18:36:22 +0400 Subject: [PATCH 026/100] getMessage is not that costly when invoked via e.g. JavaErrorMessages.message(xxx); --- platform/util/src/com/intellij/AbstractBundle.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/AbstractBundle.java b/platform/util/src/com/intellij/AbstractBundle.java index 9230d95e1776..0629b8f0c2f6 100644 --- a/platform/util/src/com/intellij/AbstractBundle.java +++ b/platform/util/src/com/intellij/AbstractBundle.java @@ -21,6 +21,7 @@ import com.intellij.util.containers.FactoryMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.util.Locale; import java.util.ResourceBundle; @@ -43,6 +44,7 @@ import java.util.ResourceBundle; * @since 8/1/11 2:37 PM */ public abstract class AbstractBundle { + private Reference myBundle; @NonNls private final String myPathToBundle; protected AbstractBundle(@NonNls @NotNull String pathToBundle) { @@ -54,7 +56,13 @@ public abstract class AbstractBundle { } private ResourceBundle getBundle() { - return getResourceBundle(myPathToBundle, getClass().getClassLoader()); + ResourceBundle bundle = null; + if (myBundle != null) bundle = myBundle.get(); + if (bundle == null) { + bundle = getResourceBundle(myPathToBundle, getClass().getClassLoader()); + myBundle = new SoftReference(bundle); + } + return bundle; } @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") From b9e202f42b7f7b4c1b343de67dcc28ad5ba0d368 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Thu, 26 Jan 2012 19:04:39 +0400 Subject: [PATCH 027/100] Implementing incrementalization log (compiler server). --- .../jetbrains/jps/incremental/Builder.java | 22 ++++ .../dependencyView/DependencyContext.java | 4 +- .../ether/dependencyView/Logger.java | 2 +- .../ether/dependencyView/Mappings.java | 124 +++++++++++++----- 4 files changed, 114 insertions(+), 38 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java index 2c642f0df771..f7c24ef8c73b 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/Builder.java @@ -1,11 +1,13 @@ package org.jetbrains.jps.incremental; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.io.FileUtil; import org.jetbrains.ether.dependencyView.Mappings; import org.jetbrains.jps.Module; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.incremental.storage.SourceToOutputMapping; +import sun.util.LocaleServiceProviderPool; import java.io.File; import java.io.IOException; @@ -16,6 +18,8 @@ import java.util.*; * Date: 9/17/11 */ public abstract class Builder { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder"); + private static final Key> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_"); private static final Key> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_"); @@ -70,6 +74,24 @@ public abstract class Builder { delta, removedPaths, successfullyCompiled, allCompiledFiles, allAffectedFiles ); + if (LOG.isDebugEnabled()) { + LOG.debug("Differentiate Results:"); + + LOG.debug(" Compiled Files:"); + + for (final File c : allCompiledFiles) { + LOG.debug(" " + c.getAbsolutePath()); + } + + LOG.debug(" Affected Files:"); + + for (final File c : allAffectedFiles) { + LOG.debug(" " + c.getAbsolutePath()); + } + + LOG.debug("End Of Differentiate Results."); + } + if (incremental) { final Set newlyAffectedFiles = new HashSet(allAffectedFiles); newlyAffectedFiles.removeAll(affectedBeforeDif); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java index c3c796f349de..d8af32122f35 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java @@ -172,9 +172,9 @@ class DependencyContext { public Logger getLogger(final com.intellij.openapi.diagnostic.Logger log) { return new Logger() { @Override - public void debug(S s) { + public void debug(String comment, S s) { if (log.isDebugEnabled()) { - log.debug(getValue(s)); + log.debug(comment + getValue(s)); } } }; diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java index 20ffdf19d8f4..dbd95bb3a256 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java @@ -23,5 +23,5 @@ package org.jetbrains.ether.dependencyView; * To change this template use File | Settings | File Templates. */ public interface Logger { - void debug(T t); + void debug(String comment, T t); } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 43bde0ea86f3..3b7c6fe7fa5a 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -42,8 +42,8 @@ public class Mappings { LOG.debug(s); } - private void debug(final DependencyContext.S s) { - myDebugS.debug(s); + private void debug(final String comment, final DependencyContext.S s) { + myDebugS.debug(comment, s); } private MultiMaplet myClassToSubclasses; @@ -534,16 +534,25 @@ public class Mappings { final Collection affectedUsages, final Collection dependants, final boolean usages) { + debug("Affecting subclasses of class: ", className); + final DependencyContext.S fileName = myClassToSourceFile.get(className); if (fileName == null) { + debug("No source file detected for class ", className); + debug("End of affectSubclasses"); return; } + debug("Source file name: ", fileName); + if (usages) { + debug("Class usages affection requested"); + final ClassRepr classRepr = reprByName(className); if (classRepr != null) { + debug("Added class usage for ", classRepr.name); affectedUsages.add(classRepr.createUsage()); } } @@ -730,32 +739,38 @@ public class Mappings { // Public branch --- hopeless if ((member.access & Opcodes.ACC_PUBLIC) > 0) { - debug("Switched to non-incremental mode"); + debug("Public access, switching to a non-incremental mode"); return false; } // Protected branch if ((member.access & Opcodes.ACC_PROTECTED) > 0) { - debug("Softening non-incremental decision: adding all relevant subclasses for a recompilation"); + debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation"); + debug("Root class: ", owner); final Collection propagated = self.propagateFieldAccess(isField ? member.name : myContext.get(""), owner); for (DependencyContext.S className : propagated) { - affectedFiles.add(new File(myContext.getValue(myClassToSourceFile.get(className)))); + final String fileName = myContext.getValue(myClassToSourceFile.get(className)); + debug("Adding " + fileName); + affectedFiles.add(new File(fileName)); } } - debug("Softening non-incremental decision: adding all package classes for a recompilation"); - final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name)); - + + debug("Softening non-incremental decision: adding all package classes for a recompilation"); + debug("Package name: " + packageName); + // Package-local branch for (Map.Entry e : myClassToSourceFile.entrySet()) { final DependencyContext.S className = e.getKey(); final DependencyContext.S fileName = e.getValue(); if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) { - affectedFiles.add(new File(myContext.getValue(fileName))); + final String f = myContext.getValue(fileName); + debug("Adding: " + f); + affectedFiles.add(new File(f)); } } @@ -767,6 +782,8 @@ public class Mappings { final Collection filesToCompile, final Collection compiledFiles, final Collection affectedFiles) { + debug("Begin of Differentiate:"); + delta.compensateRemovedContent(filesToCompile); final Util u = new Util(delta); @@ -798,14 +815,12 @@ public class Mappings { final Difference.Specifier classDiff = Difference.make(pastClasses, classes); - debug("Processing changed classes"); - + debug("Processing changed classes:"); for (Pair changed : classDiff.changed()) { final ClassRepr it = changed.first; final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second; - debug("Changed: "); - debug(it.name); + debug("Changed: ", it.name); final int addedModifiers = diff.addedModifiers(); final int removedModifiers = diff.removedModifiers(); @@ -815,24 +830,34 @@ public class Mappings { final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0; if (superClassChanged || interfacesChanged || signatureChanged) { + debug("Superclass changed: " + superClassChanged); + debug("Interfaces changed: " + interfacesChanged); + debug("Signature changed " + signatureChanged); + final boolean extendsChanged = superClassChanged && !diff.extendsAdded(); final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty(); + debug("Extends changed: " + extendsChanged); + debug("Interfaces removed: " + interfacesRemoved); + u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged); } if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) { + debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages"); affectedUsages.add(it.createUsage()); } if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) { debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested"); if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { + debug("End of Differentiate, returning false"); return false; } } if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) { + debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages"); final UsageRepr.Usage usage = it.createUsage(); affectedUsages.add(usage); @@ -840,6 +865,7 @@ public class Mappings { } if (diff.packageLocalOn()) { + debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages"); final UsageRepr.Usage usage = it.createUsage(); affectedUsages.add(usage); @@ -847,46 +873,52 @@ public class Mappings { } if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) { + debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages"); affectedUsages.add(it.createUsage()); } - if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0) { - affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name)); - } - - if ((addedModifiers & Opcodes.ACC_STATIC) > 0 || - (removedModifiers & Opcodes.ACC_STATIC) > 0 || - (addedModifiers & Opcodes.ACC_ABSTRACT) > 0) { + if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) { + debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages"); affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name)); } if (it.isAnnotation()) { + debug("Class is annotation, performing annotation-specific analysis"); + if (diff.retentionChanged()) { + debug("Retention policy change detected, adding class usage to affected usages"); affectedUsages.add(it.createUsage()); } else { final Collection removedtargets = diff.targets().removed(); if (removedtargets.contains(ElementType.LOCAL_VARIABLE)) { - debug("Annotation, removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested"); + debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested"); if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { + debug("End of Differentiate, returning false"); return false; } } if (!removedtargets.isEmpty()) { + debug("Removed some annotation targets, adding annotation query"); annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr .createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), null, removedtargets)); } for (MethodRepr m : diff.methods().added()) { if (!m.hasValue()) { + debug("Added method with no default value: " + m.name); + debug("Adding class usage to affected usages"); affectedUsages.add(it.createUsage()); } } } + + debug("End of annotation-specific analysis"); } + debug("Processing added methods: "); for (MethodRepr m : diff.methods().added()) { if (it.isAnnotation()) { continue; @@ -984,7 +1016,9 @@ public class Mappings { } } } - + debug("End of added methods processing"); + + debug("Processing removed methods:"); for (MethodRepr m : diff.methods().removed()) { final Collection> overridenMethods = u.findOverridenMethods(m, it); final Collection propagated = u.propagateMethodAccess(m.name, it.name); @@ -1053,7 +1087,9 @@ public class Mappings { } } } - + debug("End of removed methods processing"); + + debug("Processing changed methods:"); for (Pair mr : diff.methods().changed()) { final MethodRepr m = mr.first; final MethodRepr.Diff d = (MethodRepr.Diff)mr.second; @@ -1129,9 +1165,11 @@ public class Mappings { } } } - + debug("End of changed methods processing"); + final int mask = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; + debug("Processing added fields"); for (FieldRepr f : diff.fields().added()) { final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0; final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0; @@ -1214,16 +1252,16 @@ public class Mappings { } } } - - debug("Processing removed fields"); - + debug("End of added fields processing"); + + debug("Processing removed fields:"); for (FieldRepr f : diff.fields().removed()) { - debug("Field "); - debug(f.name); + debug("Field: ", it.name); if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) { debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested"); if (!incrementalDecision(it.name, f, affectedFiles)) { + debug("End of Differentiate, returning false"); return false; } } @@ -1231,20 +1269,20 @@ public class Mappings { final Collection propagated = u.propagateFieldAccess(f.name, it.name); u.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), affectedUsages, dependants); } + debug("End of removed fields processing"); - debug("Processing changed fields"); - + debug("Processing changed fields:"); for (Pair f : diff.fields().changed()) { final Difference d = f.second; final FieldRepr field = f.first; - debug("Field "); - debug(field.name); + debug("Field: ", it.name); if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) { if ((d.base() & Difference.ACCESS) > 0 || (d.base() & Difference.VALUE) > 0) { debug("Inline field changed it's access or value => a switch to non-incremental mode requested"); if (!incrementalDecision(it.name, field, affectedFiles)){ + debug("End of Differentiate, returning false"); return false; } } @@ -1293,12 +1331,18 @@ public class Mappings { } } } + debug("End of changed fields processing"); } - + debug("End of changed classes processing"); + + debug("Processing removed classes:"); for (ClassRepr c : classDiff.removed()) { + debug("Adding usages of class ", c.name); affectedUsages.add(c.createUsage()); } + debug("End of removed classes processing."); + debug("Processing added classes:"); for (ClassRepr c : classDiff.added()) { final Collection depClasses = myClassToClassDependency.get(c.name); @@ -1307,12 +1351,16 @@ public class Mappings { final DependencyContext.S fName = myClassToSourceFile.get(depClass); if (fName != null) { - affectedFiles.add(new File(myContext.getValue(fName))); + final String f = myContext.getValue(fName); + debug("Adding dependent file " + f); + affectedFiles.add(new File(f)); } } } } + debug("End of added classes processing."); + debug("Checking dependent files:"); if (dependants != null) { final Set dependentFiles = new HashSet(); @@ -1332,6 +1380,8 @@ public class Mappings { continue filewise; } + debug("Dependent file: " + theFile.getAbsolutePath()); + final Collection depClusters = mySourceFileToUsages.get(depFile); for (UsageRepr.Cluster depCluster : depClusters) { @@ -1347,6 +1397,7 @@ public class Mappings { final Util.UsageConstraint constraint = usageConstraints.get(usage); if (constraint == null) { + debug("Added file with no constraints"); affectedFiles.add(theFile); continue filewise; } @@ -1354,6 +1405,7 @@ public class Mappings { final Set residenceClasses = depCluster.getResidence(usage); for (DependencyContext.S residentName : residenceClasses) { if (constraint.checkResidence(residentName)) { + debug("Added file with satisfied constraint"); affectedFiles.add(theFile); continue filewise; } @@ -1369,6 +1421,7 @@ public class Mappings { for (UsageRepr.Usage usage : annotationUsages) { for (UsageRepr.AnnotationUsage query : annotationQuery) { if (query.satisfies(usage)) { + debug("Added file due to annotation query"); affectedFiles.add(theFile); continue filewise; } @@ -1381,6 +1434,7 @@ public class Mappings { } } + debug("End of Differentiate, returning true"); return true; } From 13ce2b999a423d3b32fe7cafdab763884f323bbe Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 26 Jan 2012 16:08:44 +0100 Subject: [PATCH 028/100] when closing floating editor, close all copies of all open files (IDEA-80361) --- .../impl/DockableEditorTabbedContainer.java | 2 +- .../fileEditor/impl/EditorsSplitters.java | 25 +++++++++++++++++ .../impl/FileEditorManagerImpl.java | 27 +++---------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java index 2eacfab54920..f2c24a9de973 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java @@ -196,7 +196,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent { } public void close(VirtualFile file) { - mySplitters.getCurrentWindow().closeFile(file); + mySplitters.closeFile(file, false); } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index 776e61846800..d64dd34acb6c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -586,6 +586,31 @@ public class EditorsSplitters extends JPanel { return null; } + void closeFile(VirtualFile file, boolean moveFocus) { + final List windows = findWindows(file); + if (!windows.isEmpty()) { + final VirtualFile nextFile = findNextFile(file); + for (final EditorWindow window : windows) { + LOG.assertTrue(window.getSelectedEditor() != null); + window.closeFile(file, false, moveFocus); + if (window.getTabCount() == 0 && nextFile != null) { + EditorWithProviderComposite newComposite = myManager.newEditorComposite(nextFile); + window.setEditor(newComposite, moveFocus); // newComposite can be null + } + } + // cleanup windows with no tabs + for (final EditorWindow window : windows) { + if (window.isDisposed()) { + // call to window.unsplit() which might make its sibling disposed + continue; + } + if (window.getTabCount() == 0) { + window.unsplit(false); + } + } + } + } + private final class MyFocusTraversalPolicy extends IdeFocusTraversalPolicy { public final Component getDefaultComponentImpl(final Container focusCycleRoot) { if (myCurrentWindow != null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 582716f561ed..f1881c6cb742 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -556,33 +556,12 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec assertDispatchThread(); runChange(new FileEditorManagerChange() { public void run(EditorsSplitters splitters) { - final List windows = splitters.findWindows(file); - if (!windows.isEmpty()) { - final VirtualFile nextFile = splitters.findNextFile(file); - for (final EditorWindow window : windows) { - LOG.assertTrue(window.getSelectedEditor() != null); - window.closeFile(file, false, moveFocus); - if (window.getTabCount() == 0 && nextFile != null) { - EditorWithProviderComposite newComposite = newEditorComposite(nextFile); - window.setEditor(newComposite, moveFocus); // newComposite can be null - } - } - // cleanup windows with no tabs - for (final EditorWindow window : windows) { - if (window.isDisposed()) { - // call to window.unsplit() which might make its sibling disposed - continue; - } - if (window.getTabCount() == 0) { - window.unsplit(false); - } - } - } + splitters.closeFile(file, moveFocus); } }, closeAllCopies ? null : getActiveSplitters(true).getResult()); } -//-------------------------------------- Open File ---------------------------------------- + //-------------------------------------- Open File ---------------------------------------- @NotNull public Pair openFileWithProviders(@NotNull final VirtualFile file, @@ -865,7 +844,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec @Nullable - private EditorWithProviderComposite newEditorComposite(final VirtualFile file) { + EditorWithProviderComposite newEditorComposite(final VirtualFile file) { if (file == null) { return null; } From 270e4e598336b3f53d1aa922b7dc9719d76fe1db Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 26 Jan 2012 16:18:06 +0100 Subject: [PATCH 029/100] mnemonic (IDEA-79780) --- .../platform-resources-en/src/messages/ActionsBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 4b218b9198be..24451d203f3e 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -1147,7 +1147,7 @@ group.EditSelectGroup.text=Editor Select Actions group.EditCreateDeleteGroup.text=Editor Create/Delete Actions group.CutCopyPasteGroup.text=Cut/Copy/Paste Actions group.EditSelectWordGroup.text=Select Word Actions -group.EditBookmarksGroup.text=Bookmarks +group.EditBookmarksGroup.text=Boo_kmarks group.OpenProjectGroup.text=Open Project Actions group.EditSmartGroup.text=Edit Code Actions group.ProjectViewGroup.text=Project View Actions From d08398955cde09748ac7e928beee734da786df1c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 17:10:46 +0400 Subject: [PATCH 030/100] margins --- .../src/com/intellij/unscramble/UnscrambleDialog.form | 4 +++- .../vcs/configurable/VcsContentAnnotationConfigurable.java | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form index b0ee1e42eb87..96720321c9fe 100644 --- a/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form +++ b/java/java-impl/src/com/intellij/unscramble/UnscrambleDialog.form @@ -71,6 +71,7 @@ + @@ -81,11 +82,12 @@ + - + diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsContentAnnotationConfigurable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsContentAnnotationConfigurable.java index 4463eef17b8e..bb1eb46a9e1c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsContentAnnotationConfigurable.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsContentAnnotationConfigurable.java @@ -60,11 +60,13 @@ public class VcsContentAnnotationConfigurable implements Configurable { public JComponent createComponent() { JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); myHighlightRecentlyChanged = new JCheckBox("Show changed in last"); - myHighlightRecentlyChanged.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + myHighlightRecentlyChanged.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 1)); myHighlightInterval = new JSpinner(new SpinnerNumberModel(1, 1, VcsContentAnnotationSettings.ourMaxDays, 1)); wrapper.add(myHighlightRecentlyChanged); wrapper.add(myHighlightInterval); - wrapper.add(new JLabel("days")); + final JLabel days = new JLabel("days"); + days.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 1)); + wrapper.add(days); myHighlightRecentlyChanged.addActionListener(new ActionListener() { @Override From 95c07df29bfe352b1bed9f4fa8d678f4404c4995 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 18:22:55 +0400 Subject: [PATCH 031/100] do not switch view during package navigation --- .../psi/impl/file/PsiPackageImplementationHelperImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java index 0c0abdce08d1..46812a81f005 100644 --- a/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/file/PsiPackageImplementationHelperImpl.java @@ -16,7 +16,6 @@ package com.intellij.psi.impl.file; import com.intellij.ide.projectView.ProjectView; -import com.intellij.ide.projectView.impl.ProjectViewPane; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.undo.GlobalUndoableAction; import com.intellij.openapi.command.undo.UndoManager; @@ -139,7 +138,7 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation final ProjectView projectView = ProjectView.getInstance(project); PsiDirectory[] directories = suggestMostAppropriateDirectories(psiPackage); if (directories.length == 0) return; - projectView.getProjectViewPaneById(ProjectViewPane.ID).select(directories[0], directories[0].getVirtualFile(), requestFocus); + projectView.select(directories[0], directories[0].getVirtualFile(), requestFocus); } }); } From e7b0f0ddcce9412b407a9dcce287bdbbfe8938b4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 18:42:09 +0400 Subject: [PATCH 032/100] fix jvm class names --- .../openapi/src/com/intellij/execution/JavaExecutionUtil.java | 3 +-- .../src/com/intellij/execution/junit/JUnitConfiguration.java | 2 +- .../testng/configuration/TestNGConfiguration.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java index 5097256ac559..987a6c8a62b5 100644 --- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java +++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java @@ -110,8 +110,7 @@ public class JavaExecutionUtil { if (containingClass != null) { final String parentName = getRuntimeQualifiedName(containingClass); return parentName + "$" + aClass.getName(); - } - else { + } else { return aClass.getQualifiedName(); } } diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java index 082bc604d7d7..469d4b64ed03 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfiguration.java @@ -365,7 +365,7 @@ public class JUnitConfiguration extends ModuleBasedConfiguration classes, PsiMethod method) { Set patterns = new HashSet(); for (PsiClass pattern : classes) { - patterns.add(pattern.getQualifiedName()); + patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern)); } myData.setPatterns(patterns); myData.METHOD_NAME = method.getName(); diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java index 4564aa0b66a3..9021ecea90b2 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfiguration.java @@ -261,7 +261,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration classes, PsiMethod method) { Set patterns = new HashSet(); for (PsiClass pattern : classes) { - patterns.add(pattern.getQualifiedName()); + patterns.add(JavaExecutionUtil.getRuntimeQualifiedName(pattern)); } data.setPatterns(patterns); data.METHOD_NAME = method.getName(); From dcbedf2152151110c01f99e82e653b4817b7fbed Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 19:22:17 +0400 Subject: [PATCH 033/100] run abstract tests: ask about target class each time [peter] --- .../com/intellij/execution/junit/TestMethod.java | 13 +++++++++---- .../com/intellij/execution/junit/TestsPattern.java | 5 ++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java index ab93fa1232b9..e84c0ff0bc7a 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java @@ -21,7 +21,10 @@ import com.intellij.execution.*; import com.intellij.execution.configurations.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiPackage; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.refactoring.listeners.RefactoringElementAdapter; import com.intellij.refactoring.listeners.RefactoringElementListener; @@ -106,12 +109,14 @@ class TestMethod extends TestObject { PsiMethod testMethod, PsiPackage testPackage) { if (testMethod == null) return false; - final PsiClass containingClass = testMethod.getContainingClass(); - if (testClass == null && (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.ABSTRACT))) return false; + if (testClass == null) return false; final JUnitConfiguration.Data data = configuration.getPersistentData(); + /*final PsiClass containingClass = testMethod.getContainingClass(); + if (testClass == null && (containingClass == null || !containingClass.hasModifierProperty(PsiModifier.ABSTRACT))) return false; + if (containingClass != null && containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) { return Comparing.equal(testMethod.getName(), data.getMethodName()); - } + }*/ return Comparing.equal(JavaExecutionUtil.getRuntimeQualifiedName(testClass), data.getMainClassName()) && Comparing.equal(testMethod.getName(), data.getMethodName()); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java index df090c198bf0..01527b71fde3 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestsPattern.java @@ -27,7 +27,6 @@ import com.intellij.execution.util.JavaParametersUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; @@ -108,9 +107,9 @@ public class TestsPattern extends TestObject { PsiClass testClass, PsiMethod testMethod, PsiPackage testPackage) { - if (testMethod != null && Comparing.strEqual(testMethod.getName(), configuration.getPersistentData().METHOD_NAME)) { + /*if (testMethod != null && Comparing.strEqual(testMethod.getName(), configuration.getPersistentData().METHOD_NAME)) { return true; - } + }*/ return false; } From 9b6198c08bfbd53912d2ebabed6c9cc6e9824b0e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 26 Jan 2012 16:37:49 +0100 Subject: [PATCH 034/100] restore correct logic for existing instance activation (IDEA-79952) --- .../src/com/intellij/idea/SocketLock.java | 2 +- .../src/com/intellij/idea/StartupUtil.java | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/idea/SocketLock.java b/platform/platform-impl/src/com/intellij/idea/SocketLock.java index d8ab49cb1712..ca9ebb6a06a2 100644 --- a/platform/platform-impl/src/com/intellij/idea/SocketLock.java +++ b/platform/platform-impl/src/com/intellij/idea/SocketLock.java @@ -162,13 +162,13 @@ public class SocketLock { try { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.writeUTF(ACTIVATE_COMMAND + StringUtil.join(args, "\0")); + out.flush(); String response = in.readUTF(); if (response.equals("ok")) { return ActivateStatus.ACTIVATED; } } catch(IOException e) { - } return ActivateStatus.CANNOT_ACTIVATE; } diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index 81e873ae3041..e30f09e9611a 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -111,7 +111,17 @@ public class StartupUtil { } if (activateStatus != SocketLock.ActivateStatus.NO_INSTANCE) { - showError("Error", "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time."); + if (isHeadless()) { //team server inspections + System.out.println("Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time."); + return false; + } + if (activateStatus == SocketLock.ActivateStatus.CANNOT_ACTIVATE) { + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), + "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + + " can be run at a time.", + "Error", + JOptionPane.INFORMATION_MESSAGE); + } return false; } From ec7b60c455a327fa77a42bf38ddf4eda2a27930c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 26 Jan 2012 16:49:53 +0100 Subject: [PATCH 035/100] quickfix for "Constant StringBuffer may be String" --- .../siyeh/InspectionGadgetsBundle.properties | 14 ++- ...ngBufferReplaceableByStringInspection.java | 117 ++++++++++++++++-- .../VariableIsModifiedVisitor.java | 23 ++-- 3 files changed, 126 insertions(+), 28 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index 5586e14f0484..1e9817d92927 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -764,7 +764,7 @@ for.loop.with.missing.component.collection.loop.option=Ignore collection iterati double.checked.locking.display.name=Double-checked locking double.checked.locking.problem.descriptor=Double-checked locking #loc double.checked.locking.ignore.on.volatiles.option=Ignore double-checked locking on volatile fields -string.buffer.replaceable.by.string.display.name=Constant StringBuffer may be String +string.buffer.replaceable.by.string.display.name=Constant 'StringBuffer' may be 'String' boolean.method.name.must.start.with.question.display.name=Boolean method name must start with question word class.name.same.as.ancestor.name.display.name=Class name same as ancestor name error.rethrown.display.name='java.lang.Error' not rethrown @@ -1043,9 +1043,9 @@ map.replaceable.by.enum.map.problem.descriptor=#ref replaceable wit set.replaceable.by.enum.set.problem.descriptor=#ref replaceable with EnumSet #loc inner.class.may.be.static.problem.descriptor=Inner class #ref may be 'static' #loc string.buffer.must.have.initial.capacity.problem.descriptor=#ref without initial capacity #loc -string.buffer.replaceable.by.string.builder.problem.descriptor=StringBuffer #ref may be declared as StringBuilder #loc -string.buffer.replaceable.by.string.problem.descriptor=Constant StringBuffer #ref may be declared as String #loc -string.replaceable.by.string.buffer.problem.descriptor=Non-constant String #ref should probably be declared as StringBuilder #loc +string.buffer.replaceable.by.string.builder.problem.descriptor=StringBuffer #ref may be declared as ''StringBuilder'' #loc +string.buffer.replaceable.by.string.problem.descriptor=Constant {0} #ref may be declared as ''String'' #loc +string.replaceable.by.string.buffer.problem.descriptor=Non-constant String #ref should probably be declared as ''StringBuilder'' #loc collections.must.have.initial.capacity.problem.descriptor=#ref without initial capacity #loc string.concatenation.in.loops.problem.descriptor=String concatenation #ref in loop #loc string.concatenation.inside.string.buffer.append.problem.descriptor=String concatenation as argument to {0}.#ref() call #loc @@ -1303,7 +1303,7 @@ manual.array.to.collection.copy.replace.quickfix=Replace with 'Collections.addAl method.may.be.static.only.option=Only check private or final methods method.may.be.static.empty.option=Ignore empty methods random.double.for.random.integer.replace.quickfix=Replace with 'nextInt()' -string.buffer.replaceable.by.string.builder.replace.quickfix=Replace with StringBuilder +string.buffer.replaceable.by.string.builder.replace.quickfix=Replace with 'StringBuilder' string.buffer.to.string.in.concatenation.remove.quickfix=Remove 'toString()' string.concatenation.in.loops.only.option=Only warn if string is repeatedly appended string.concatenation.inside.string.buffer.append.replace.quickfix=Replace with chained 'append()' calls @@ -1967,4 +1967,6 @@ ambiguous.field.access.display.name=Inherited field accessed while local variabl ambiguous.field.access.hides.local.variable.problem.descriptor=Field #ref from super class ''{0}'' accessed, while local variable access might be expected #loc ambiguous.field.access.hides.parameter.problem.descriptor=Field #ref from super class ''{0}'' accessed, while parameter access might be expected #loc ambiguous.field.access.hides.field.problem.descriptor=Field #ref from super class ''{0}'' accessed, while field access from surrounding class might be expected #loc -ambiguous.field.access.quickfix=Qualify field access with 'super.' \ No newline at end of file +ambiguous.field.access.quickfix=Qualify field access with 'super.' +string.builder.replaceable.by.string.quickfix=Replace 'StringBuilder' with 'String' +string.buffer.replaceable.by.string.quickfix=Replace 'StringBuffer' with 'String' \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java index 15cb757ba90c..a77d0cc4161c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/StringBufferReplaceableByStringInspection.java @@ -15,11 +15,15 @@ */ package com.siyeh.ig.performance; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.TypeUtils; import com.siyeh.ig.psiutils.VariableAccessUtils; import org.jetbrains.annotations.NotNull; @@ -29,23 +33,114 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "string.buffer.replaceable.by.string.display.name"); + return InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.display.name"); } @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "string.buffer.replaceable.by.string.problem.descriptor"); + final String typeText = ((PsiType)infos[0]).getPresentableText(); + return InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.problem.descriptor", typeText); + } + + @Override + protected InspectionGadgetsFix buildFix(Object... infos) { + final String typeText = ((PsiType)infos[0]).getCanonicalText(); + return new StringBufferReplaceableByStringFix(CommonClassNames.JAVA_LANG_STRING_BUILDER.equals(typeText)); + } + + private static class StringBufferReplaceableByStringFix extends InspectionGadgetsFix { + + private final boolean isStringBuilder; + + private StringBufferReplaceableByStringFix(boolean isStringBuilder) { + this.isStringBuilder = isStringBuilder; + } + + @NotNull + @Override + public String getName() { + if (isStringBuilder) { + return InspectionGadgetsBundle.message("string.builder.replaceable.by.string.quickfix"); + } else { + return InspectionGadgetsBundle.message("string.buffer.replaceable.by.string.quickfix"); + } + } + + @Override + protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (!(parent instanceof PsiVariable)) { + return; + } + final PsiVariable variable = (PsiVariable)parent; + final PsiTypeElement originalTypeElement = variable.getTypeElement(); + if (originalTypeElement == null) { + return; + } + final PsiExpression initializer = variable.getInitializer(); + if (initializer == null) { + return; + } + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); + final PsiClassType javaLangString = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, variable.getResolveScope()); + final PsiTypeElement typeElement = factory.createTypeElement(javaLangString); + final StringBuilder newInitializer = buildReplacementInitializer(initializer, new StringBuilder()); + if (newInitializer == null) { + return; + } + originalTypeElement.replace(typeElement); + replaceExpression(initializer, newInitializer.toString()); + } + + private static StringBuilder buildReplacementInitializer(PsiExpression initializer, StringBuilder result) { + if (initializer instanceof PsiNewExpression) { + final PsiNewExpression newExpression = (PsiNewExpression)initializer; + final PsiExpressionList argumentList = newExpression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + if (arguments.length == 0) { + result.append("\"\""); + } else if (arguments.length == 1) { + final PsiExpression argument = arguments[0]; + final PsiType type = argument.getType(); + if (PsiType.INT.equals(type)) { + result.append("\"\""); + } else { + result.append(argument.getText()); + } + } else { + return null; + } + } else if (initializer instanceof PsiMethodCallExpression) { + final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)initializer; + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); + result = buildReplacementInitializer(qualifier, result); + if (result == null) { + return null; + } + final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); + final PsiExpression[] arguments = argumentList.getExpressions(); + if (arguments.length != 1) { + return null; + } + final PsiExpression argument = arguments[0]; + result.append('+'); + result.append(argument.getText()); + } else { + return null; + } + return result; + } } @Override public BaseInspectionVisitor buildVisitor() { - return new StringBufferReplaceableByStringBuilderVisitor(); + return new StringBufferReplaceableByStringVisitor(); } - private static class StringBufferReplaceableByStringBuilderVisitor extends BaseInspectionVisitor { + private static class StringBufferReplaceableByStringVisitor extends BaseInspectionVisitor { @Override public void visitLocalVariable(@NotNull PsiLocalVariable variable) { @@ -81,7 +176,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { if (variableIsModified(variable, codeBlock)) { return; } - registerVariableError(variable); + registerVariableError(variable, type); } public static boolean variableIsModified(PsiVariable variable, PsiElement context) { @@ -99,7 +194,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { } else if (expression instanceof PsiMethodCallExpression) { final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression; - if (!VariableIsModifiedVisitor.isStringBufferUpdate(methodCallExpression)) { + if (!isAppend(methodCallExpression)) { return false; } final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); @@ -108,5 +203,11 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { } return false; } + + public static boolean isAppend(PsiMethodCallExpression methodCallExpression) { + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); + final String methodName = methodExpression.getReferenceName(); + return "append".equals(methodName); + } } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java index 0a5651be08ea..fcccb5a96a46 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/VariableIsModifiedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Dave Griffith + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,14 +25,15 @@ import java.util.Set; class VariableIsModifiedVisitor extends JavaRecursiveElementVisitor { - @NonNls private static final Set updateNames = - new HashSet(9); + @NonNls private static final Set updateNames = new HashSet(9); static { updateNames.add("append"); updateNames.add("appendCodePoint"); + updateNames.add("capacity"); // does not strictly modify, but is not a String method updateNames.add("delete"); updateNames.add("deleteCharAt"); + updateNames.add("ensureCapacity"); // does not strictly modify, but is not a String method updateNames.add("insert"); updateNames.add("replace"); updateNames.add("reverse"); @@ -44,7 +45,6 @@ class VariableIsModifiedVisitor extends JavaRecursiveElementVisitor { private final PsiVariable variable; VariableIsModifiedVisitor(PsiVariable variable) { - super(); this.variable = variable; } @@ -65,28 +65,23 @@ class VariableIsModifiedVisitor extends JavaRecursiveElementVisitor { if (!isStringBufferUpdate(call)) { return; } - final PsiReferenceExpression methodExpression = - call.getMethodExpression(); - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (!(qualifier instanceof PsiReferenceExpression)) { return; } - final PsiReferenceExpression reference = - (PsiReferenceExpression)qualifier; + final PsiReferenceExpression reference = (PsiReferenceExpression)qualifier; final PsiElement referent = reference.resolve(); if (variable.equals(referent)) { modified = true; } } - public static boolean isStringBufferUpdate( - @Nullable PsiMethodCallExpression methodCallExpression) { + public static boolean isStringBufferUpdate(@Nullable PsiMethodCallExpression methodCallExpression) { if (methodCallExpression == null) { return false; } - final PsiReferenceExpression methodExpression = - methodCallExpression.getMethodExpression(); + final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); return updateNames.contains(methodName); } From f214f993375851dad6c0b17cfc917fef0de3f084 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 26 Jan 2012 19:53:05 +0400 Subject: [PATCH 036/100] [ann] IDEA-80335 (more precise check for exceptions from AutoClosable types) --- .../intellij/codeInsight/ExceptionUtil.java | 32 ++++++++++++------- .../advHighlighting7/TryWithResources.java | 19 +++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java index 22e98032eb8a..c9f49dbf0d19 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -16,15 +16,15 @@ package com.intellij.codeInsight; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.NullableComputable; import com.intellij.psi.*; import com.intellij.psi.controlFlow.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.psi.search.ProjectScope; +import com.intellij.psi.util.*; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; @@ -347,18 +347,26 @@ public class ExceptionUtil { @NotNull public static List getUnhandledCloserExceptions(final PsiResourceVariable resource, @Nullable final PsiElement topElement) { - final PsiType resourceType = resource.getType(); - if (resourceType instanceof PsiClassType) { - final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); - if (resourceClass != null) { - final PsiMethod[] closers = resourceClass.findMethodsByName("close", false); - for (final PsiMethod method : closers) { - if (method.getParameterList().getParametersCount() == 0) { - return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY); + final Project project = resource.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project)); + if (autoCloseable != null) { + final PsiMethod[] methods = autoCloseable.findMethodsByName("close", false); + if (methods.length == 1) { + final MethodSignature signature = methods[0].getSignature(PsiSubstitutor.EMPTY); + final PsiType resourceType = resource.getType(); + if (resourceType instanceof PsiClassType) { + final PsiClass resourceClass = ((PsiClassType)resourceType).resolve(); + if (resourceClass != null) { + final PsiMethod method = MethodSignatureUtil.findMethodBySignature(resourceClass, signature, true); + if (method != null) { + return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY); + } } } } } + return Collections.emptyList(); } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java index e8df782c83ac..c0f8eb7cc342 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/TryWithResources.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 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. + */ class C { static class E extends Exception { } static class E1 extends E { } @@ -10,6 +25,8 @@ class C { @Override public void close() throws E3 { } } + static interface I extends AutoCloseable { } + void m1() { try (MyResource r = new MyResource()) { r.doSomething(); } catch (E1 | E2 | E3 ignore) { } @@ -24,6 +41,8 @@ class C { catch (E3 e) { } try (MyResource r = new MyResource()) { } + + try (I r = null) { System.out.println(r); } } void m2() throws Exception { From 1dd84fdf6bd51ee085d6d4aaa97d9aa4cafe85b8 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Thu, 26 Jan 2012 17:49:37 +0100 Subject: [PATCH 037/100] CommandProcessor: assertion improved --- .../openapi/command/impl/CommandProcessorImpl.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java index 71494e542fac..33596a4f619d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/CommandProcessorImpl.java @@ -57,6 +57,11 @@ public class CommandProcessorImpl extends CommandProcessorEx { myUndoConfirmationPolicy = undoConfirmationPolicy; myDocument = document; } + + @Override + public String toString() { + return "'" + myName + "', group: '" + myGroupId + "'"; + } } private CommandDescriptor myCurrentCommand = null; @@ -219,7 +224,8 @@ public class CommandProcessorImpl extends CommandProcessorEx { } public void leaveModal() { - CommandLog.LOG.assertTrue(myCurrentCommand == null); + CommandLog.LOG.assertTrue(myCurrentCommand == null, "Command must not run: " + String.valueOf(myCurrentCommand)); + myCurrentCommand = myInterruptedCommands.pop(); if (myCurrentCommand != null) { fireCommandStarted(); From e5befcba13f454c2f0b01f729abfef94d2beafb9 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 26 Jan 2012 20:48:21 +0400 Subject: [PATCH 038/100] Less warnings on missing files --- .../util/src/com/intellij/openapi/util/io/FileSystemUtil.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java index 337395d0b9bd..d46a663babf1 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileSystemUtil.java @@ -22,11 +22,14 @@ import com.sun.jna.Library; import com.sun.jna.Memory; import com.sun.jna.Native; import com.sun.jna.Pointer; +import com.sun.org.apache.bcel.internal.generic.NEW; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; @@ -188,6 +191,7 @@ public class FileSystemUtil { @Override public String resolveSymLink(@NotNull final String path) throws Exception { + if (!new File(path).exists()) return null; final Object pathObj = myGetPath.invoke(myDefaultFileSystem, path, ArrayUtil.EMPTY_STRING_ARRAY); final Method toRealPath = pathObj.getClass().getMethod("toRealPath", myLinkOptions.getClass()); toRealPath.setAccessible(true); From 8b70c85a5a63c5a4b4d2d2bb84f671abecc34294 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 26 Jan 2012 17:54:46 +0100 Subject: [PATCH 039/100] CCE fix EA-33249 --- .../intellij/ide/util/FileStructurePopup.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java index 822ec3a804dc..2285504fe806 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java +++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java @@ -228,18 +228,20 @@ public class FileStructurePopup implements Disposable { for (ObjectWithWeight p : paths) { final Object last = ((TreePath)p.node).getLastPathComponent(); final List elements = new ArrayList(); - FilteringTreeStructure.FilteringNode node = - (FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)last).getUserObject(); - while (node != null) { - elements.add(getPsi(node)); - node = node.getParentNode(); - } - final int size = ContainerUtil.intersection(parents, elements).size(); - if (size > max) { - max = size; - cur = p.node; - } else if (size == max && size == parents.size()) { - cur = p.node; + final Object object = ((DefaultMutableTreeNode)last).getUserObject(); + if (object instanceof FilteringTreeStructure.FilteringNode) { + FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object; + while (node != null) { + elements.add(getPsi(node)); + node = node.getParentNode(); + } + final int size = ContainerUtil.intersection(parents, elements).size(); + if (size > max) { + max = size; + cur = p.node; + } else if (size == max && size == parents.size()) { + cur = p.node; + } } } From 4d40b23d28dd36333bcbe83944e70d17ddd7ac32 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 26 Jan 2012 19:55:46 +0300 Subject: [PATCH 040/100] IDEA-80105 (Grails: IDEA doesn't update list of artifacts on file rename.) --- .../mvc/MvcModuleStructureSynchronizer.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java index f4e2b1452ea0..c93b5fe07aaf 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java @@ -33,10 +33,7 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Trinity; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileAdapter; -import com.intellij.openapi.vfs.VirtualFileEvent; -import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; @@ -196,6 +193,18 @@ public class MvcModuleStructureSynchronizer extends AbstractProjectComponent { queue(SyncAction.UpdateProjectStructure, event.getFile()); } } + + @Override + public void fileMoved(VirtualFileMoveEvent event) { + myModificationCount++; + } + + @Override + public void propertyChanged(VirtualFilePropertyEvent event) { + if (VirtualFile.PROP_NAME.equals(event.getPropertyName())) { + myModificationCount++; + } + } })); } From ac49354dbf06c6d4ec4a85b60d4449a1a50d0e8a Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 26 Jan 2012 18:02:38 +0100 Subject: [PATCH 041/100] NPE EA-33272 --- .../intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index c9f1f5c6ef0e..b5eca8b1f0e4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -220,11 +220,11 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc } public boolean isVisible() { - return myDialog.isVisible(); + return myDialog != null && myDialog.isVisible(); } public boolean isShowing() { - return myDialog.isShowing(); + return myDialog != null && myDialog.isShowing(); } public void setSize(final int width, final int height) { From 6bab1d7005ebbe79c5fddfebcdf8401ba12649a4 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 16:39:42 +0100 Subject: [PATCH 042/100] make ClassUtil.getJvmClassName work correctly for groovy classes --- .../intellij/execution/JavaExecutionUtil.java | 9 ++----- .../src/com/intellij/psi/util/ClassUtil.java | 27 +++++++------------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java index 987a6c8a62b5..89cc65ebeeaf 100644 --- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java +++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java @@ -30,6 +30,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.ClassUtil; import com.intellij.psi.util.PsiClassUtil; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; @@ -106,13 +107,7 @@ public class JavaExecutionUtil { @Nullable public static String getRuntimeQualifiedName(final PsiClass aClass) { - final PsiClass containingClass = aClass.getContainingClass(); - if (containingClass != null) { - final String parentName = getRuntimeQualifiedName(containingClass); - return parentName + "$" + aClass.getName(); - } else { - return aClass.getQualifiedName(); - } + return ClassUtil.getJVMClassName(aClass); } @Nullable diff --git a/java/openapi/src/com/intellij/psi/util/ClassUtil.java b/java/openapi/src/com/intellij/psi/util/ClassUtil.java index 18038c40c13d..d7f8aa2a27c2 100644 --- a/java/openapi/src/com/intellij/psi/util/ClassUtil.java +++ b/java/openapi/src/com/intellij/psi/util/ClassUtil.java @@ -245,26 +245,19 @@ public class ClassUtil { @Nullable public static String getJVMClassName(PsiClass aClass) { - final String qName = aClass.getQualifiedName(); - if (qName == null) return null; - return replaceDotsWithDollars(qName, aClass); - } - - private static String replaceDotsWithDollars(final String qName, PsiClass aClass) { - StringBuilder qNameBuffer = new StringBuilder(qName); - - int fromIndex = qNameBuffer.length(); - PsiElement parent = aClass.getParent(); - while (parent instanceof PsiClass) { - final int dotIndex = qNameBuffer.lastIndexOf(".", fromIndex); - if (dotIndex < 0) break; - qNameBuffer.replace(dotIndex, dotIndex + 1, "$"); - fromIndex = dotIndex - 1; - parent = parent.getParent(); + final PsiClass containingClass = aClass.getContainingClass(); + if (containingClass != null) { + String parentName = getJVMClassName(containingClass); + if (parentName == null) { + return null; + } + + return parentName + "$" + aClass.getName(); } - return qNameBuffer.toString(); + return aClass.getQualifiedName(); } + @Nullable public static PsiClass findPsiClassByJVMName(final PsiManager manager, final String jvmClassName) { return findPsiClass(manager, jvmClassName.replace('/', '.'), null, true); From e7eb75ebc159e976c193f9e457288048a2b1699e Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 18:29:37 +0100 Subject: [PATCH 043/100] a failing test for compiling 'jps' module issues --- .../jps/incremental/groovy/GroovyBuilder.java | 3 +- .../groovy/compiler/GroovyCompilerTest.groovy | 43 ++++++++++++++----- .../compiler/GroovyCompilerTestCase.java | 30 ++++++++++++- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 2bb3e3c411ab..30635be989f8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -104,12 +104,13 @@ public class GroovyBuilder extends Builder { // todo CompilerUtil.addLocaleOptions() //todo different outputs in a chunk + //todo xmx //todo module jdk path final List cmd = ExternalProcessUtil.buildJavaCommandLine( SystemProperties.getJavaHome() + "/bin/java", "org.jetbrains.groovy.compiler.rt.GroovycRunner", Collections.emptyList(), new ArrayList(cp), - Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5858"*/), + Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239"*/), Arrays.asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath()) ); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index 17df5b873993..4aab9d2fc036 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -65,6 +65,14 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase { assertOutput("Foo", "239"); setFileText(file, "class Bar {}"); + makeShouldFail() + + setFileText(file, barText); + make(); + assertOutput("Foo", "239"); + } + + private void makeShouldFail() { try { make(); fail("Make should fail"); @@ -74,10 +82,6 @@ public abstract class GroovyCompilerTest extends GroovyCompilerTestCase { throw e; } } - - setFileText(file, barText); - make(); - assertOutput("Foo", "239"); } public void testRenameToJava() throws Throwable { @@ -475,9 +479,9 @@ class Indirect { } public void testDontRecompileUnneeded() { - myFixture.addFileToProject('Base.groovy', 'class Base { }').virtualFile + myFixture.addFileToProject('Base.groovy', 'class Base { }') def foo = myFixture.addFileToProject('Foo.groovy', 'class Foo extends Base { }').virtualFile - myFixture.addFileToProject('Bar.groovy', 'class Bar extends Foo { }').virtualFile + myFixture.addFileToProject('Bar.groovy', 'class Bar extends Foo { }') def main = myFixture.addFileToProject('Main.groovy', 'class Main extends Bar { }').virtualFile assertEmpty make() long oldBaseStamp = findClassFile("Base").modificationStamp @@ -490,17 +494,34 @@ class Indirect { assert oldBaseStamp == findClassFile("Base").modificationStamp } + public void _testPartialCrossRecompile() { + def used = myFixture.addFileToProject('Used.groovy', 'class Used { }') + def java = myFixture.addFileToProject('Java.java', 'class Java { void foo(Used used) {} }') + def main = myFixture.addFileToProject('Main.groovy', 'class Main extends Java { }').virtualFile + + assertEmpty compileModule(myModule) + assertEmpty compileFiles(used.virtualFile, main) + assertEmpty compileModule(myModule) + assertEmpty compileModule(myModule) + + setFileText(used, 'class Used2 {}') + makeShouldFail() + assert findClassFile('Used') == null + assert findClassFile('Used2') == null + + setFileText(used, 'class Used3 {}') + setFileText(java, 'class Java { void foo(Used3 used) {} }') + assertEmpty make() + + assert findClassFile('Used2') == null + } + public static class IdeaModeTest extends GroovyCompilerTest { @Override protected boolean useJps() { false } } public static class JpsModeTest extends GroovyCompilerTest { @Override protected boolean useJps() { true } - - @Override - void testCorrectFailAndCorrect() { - super.testCorrectFailAndCorrect() - } } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java index 6f910e67db60..5dee59b7d0db 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java @@ -42,6 +42,7 @@ import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.testFramework.fixtures.TempDirTestFixture; import com.intellij.testFramework.fixtures.impl.TempDirTestFixtureImpl; +import com.intellij.util.Consumer; import com.intellij.util.ObjectUtils; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; @@ -243,6 +244,33 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC } protected List make() { + return runCompiler(new Consumer() { + @Override + public void consume(ErrorReportingCallback callback) { + CompilerManager.getInstance(getProject()).make(callback); + } + }); + } + + protected List compileModule(final Module module) { + return runCompiler(new Consumer() { + @Override + public void consume(ErrorReportingCallback callback) { + CompilerManager.getInstance(getProject()).compile(module, callback); + } + }); + } + + protected List compileFiles(final VirtualFile... files) { + return runCompiler(new Consumer() { + @Override + public void consume(ErrorReportingCallback callback) { + CompilerManager.getInstance(getProject()).compile(files, callback); + } + }); + } + + private List runCompiler(final Consumer runnable) { final Semaphore semaphore = new Semaphore(); semaphore.down(); final ErrorReportingCallback callback = new ErrorReportingCallback(semaphore); @@ -258,7 +286,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC assert ioFile.exists(); } } - CompilerManager.getInstance(getProject()).make(callback); + runnable.consume(callback); } catch (Exception e) { throw new RuntimeException(e); From 4f1e8391acf47d51db284a246dd1b27ddeccc23c Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Thu, 26 Jan 2012 21:51:40 +0400 Subject: [PATCH 044/100] comment broken test --- .../testSrc/org/jetbrains/android/AndroidLintTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java b/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java index 186b291dd2b4..dfcd39e34d20 100644 --- a/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java +++ b/plugins/android/testSrc/org/jetbrains/android/AndroidLintTest.java @@ -140,7 +140,7 @@ public class AndroidLintTest extends AndroidTestCase { "/res/layout/layout.xml", "xml"); } - public void testTypographyDashes() throws Exception { + /*public void testTypographyDashes() throws Exception { doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintTypographyDashesInspection(), AndroidBundle.message("android.lint.inspections.replace.with.suggested.characters"), "/res/values/typography.xml", "xml"); @@ -150,7 +150,7 @@ public class AndroidLintTest extends AndroidTestCase { doTestWithFix(new AndroidLintInspectionToolProvider.AndroidLintTypographyQuotesInspection(), AndroidBundle.message("android.lint.inspections.replace.with.suggested.characters"), "/res/values/typography.xml", "xml"); - } + }*/ private void doTestNoFix(@NotNull AndroidLintInspectionBase inspection, @NotNull String copyTo, @NotNull String extension) throws IOException { From 4d381bd888307b74b5fb1822895b0758538ae1a9 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 26 Jan 2012 18:46:46 +0100 Subject: [PATCH 045/100] IDEA-80382 Notifications: when balloon is shown in Event Log and after clicking a link it expires, it should be hidden --- .../intellij/notification/Notification.java | 20 +++++++++++++------ .../com/intellij/notification/EventLog.java | 2 -- .../impl/NotificationsManagerImpl.java | 7 ------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java index b264b20d1c3c..36ad4145c9e7 100644 --- a/platform/platform-api/src/com/intellij/notification/Notification.java +++ b/platform/platform-api/src/com/intellij/notification/Notification.java @@ -18,6 +18,8 @@ package com.intellij.notification; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.Balloon; +import com.intellij.openapi.ui.popup.JBPopupAdapter; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -111,12 +113,18 @@ public class Notification { } } - public void setBalloon(@Nullable final Balloon balloon) { - if (balloon != null) { - myBalloonRef = new WeakReference(balloon); - } else { - myBalloonRef = null; - } + public void setBalloon(@NotNull final Balloon balloon) { + hideBalloon(); + myBalloonRef = new WeakReference(balloon); + balloon.addListener(new JBPopupAdapter() { + @Override + public void onClosed(LightweightWindowEvent event) { + WeakReference ref = myBalloonRef; + if (ref != null && ref.get() == balloon) { + myBalloonRef = null; + } + } + }); } @Nullable diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index 79d6ad266bea..2d1e660c2c6d 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -415,8 +415,6 @@ public class EventLog implements Notifications { Balloon balloon = NotificationsManagerImpl.createBalloon(myNotification, true, true); Disposer.register(project, balloon); balloon.show(target, Balloon.Position.above); - myNotification.hideBalloon(); - myNotification.setBalloon(balloon); } } diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java index 6870f9459f21..50968d23171b 100644 --- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsManagerImpl.java @@ -314,13 +314,6 @@ public class NotificationsManagerImpl extends NotificationsManager implements No .setHideOnKeyOutside(hideOnClickOutside).setHideOnFrameResize(false); final Balloon balloon = builder.createBalloon(); - balloon.addListener(new JBPopupAdapter() { - @Override - public void onClosed(LightweightWindowEvent event) { - notification.setBalloon(null); - } - }); - notification.setBalloon(balloon); return balloon; } From 38a8a0166156670d32251a7194204ac39c6102df Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Thu, 26 Jan 2012 22:07:32 +0400 Subject: [PATCH 046/100] Continue implementing incrementalization log; fixed bug with removed files (compiler server). --- .../ether/dependencyView/Mappings.java | 58 +++++++++++++++++-- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 3b7c6fe7fa5a..adfcf6f7708c 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -920,13 +920,17 @@ public class Mappings { debug("Processing added methods: "); for (MethodRepr m : diff.methods().added()) { + debug("Method: ", m.name); + if (it.isAnnotation()) { + debug("Class is annotation, skipping method analysis"); continue; } if ((it.access & Opcodes.ACC_INTERFACE) > 0 || (it.access & Opcodes.ACC_ABSTRACT) > 0 || (m.access & Opcodes.ACC_ABSTRACT) > 0) { + debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses"); u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false); } @@ -940,6 +944,7 @@ public class Mappings { } else { propagated = u.propagateMethodAccess(m.name, it.name); + debug("Conservative case on overriding methods, affecting method usages"); u.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), affectedUsages, dependants); } } @@ -956,10 +961,12 @@ public class Mappings { for (MethodRepr mm : lessSpecific) { if (!mm.equals(m)) { + debug("Found less specific method, affecting method usages"); u.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), affectedUsages, dependants); } } + debug("Processing affected by specificity methods"); for (Pair p : affectedMethods) { final MethodRepr mm = p.first; final ClassRepr cc = p.second; @@ -968,7 +975,12 @@ public class Mappings { } else { + debug("Method: ", mm.name); + debug("Class : ", cc.name); + if (overrides.satisfy(mm)) { + debug("Current method overrides that found"); + final Option subtypeOf = u.isSubtypeOf(mm.type, m.type); if (weakerAccess(mm.access, m.access) || @@ -981,11 +993,15 @@ public class Mappings { final DependencyContext.S file = myClassToSourceFile.get(cc.name); if (file != null) { - affectedFiles.add(new File(myContext.getValue(file))); + final String f = myContext.getValue(file); + debug("Complex condition is satisfied, affecting file " + f); + affectedFiles.add(new File(f)); } } } else { + debug("Current method does not override that found"); + final Collection yetPropagated = self.propagateMethodAccess(mm.name, cc.name); final Collection deps = myClassToClassDependency.get(cc.name); @@ -993,6 +1009,7 @@ public class Mappings { dependants.addAll(deps); } + debug("Affecting method usages for that found"); u.affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, cc.name), affectedUsages, dependants); } } @@ -1008,8 +1025,10 @@ public class Mappings { if (r != null && sourceFileName != null) { final DependencyContext.S outerClass = r.outerClassName; - if (u.methodVisible(outerClass, m)) { - affectedFiles.add(new File(myContext.getValue(sourceFileName))); + if (u.methodVisible(outerClass, m)) { + final String f = myContext.getValue(sourceFileName); + debug("Affecting file " + f + " due to local overriding"); + affectedFiles.add(new File(f)); } } } @@ -1020,10 +1039,13 @@ public class Mappings { debug("Processing removed methods:"); for (MethodRepr m : diff.methods().removed()) { + debug("Method ", m.name); + final Collection> overridenMethods = u.findOverridenMethods(m, it); final Collection propagated = u.propagateMethodAccess(m.name, it.name); if (overridenMethods.size() == 0) { + debug("No overridden methods found, affecting method usages"); u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants); } else { @@ -1040,6 +1062,7 @@ public class Mappings { } if (!clear) { + debug("No clearly overridden methods found, affecting method usages"); u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants); } } @@ -1080,7 +1103,10 @@ public class Mappings { final DependencyContext.S source = myClassToSourceFile.get(p); if (source != null) { - affectedFiles.add(new File(myContext.getValue(source))); + final String f = myContext.getValue(source); + debug("Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ", p); + debug("Affecting subclass source file " + f); + affectedFiles.add(new File(f)); } } } @@ -1095,8 +1121,11 @@ public class Mappings { final MethodRepr.Diff d = (MethodRepr.Diff)mr.second; final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0); + debug("Method: ", m.name); + if (it.isAnnotation()) { if (d.defaultRemoved()) { + debug("Class is annotation, default value is removed => adding annotation query"); final List l = new LinkedList(); l.add(m.name); annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr @@ -1112,6 +1141,7 @@ public class Mappings { final Set usages = new HashSet(); if (d.packageLocalOn()) { + debug("Method became package-local, affecting method usages outside the package"); u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants); for (UsageRepr.Usage usage : usages) { @@ -1125,6 +1155,7 @@ public class Mappings { if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) { if (!affected) { + debug("Return type, throws list or signature changed --- affecting method usages"); u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants); affectedUsages.addAll(usages); } @@ -1134,11 +1165,13 @@ public class Mappings { (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 || (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) { if (!affected) { + debug("Added static or private specifier or removed static specifier --- affecting method usages"); u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants); affectedUsages.addAll(usages); } if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) { + debug("Added static specifier --- affecting subclasses"); u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false); } } @@ -1146,11 +1179,13 @@ public class Mappings { if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 || (d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 || (d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) { + debug("Added final, public or abstract specifier --- affecting subclasses"); u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false); } if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) { if (!constrained) { + debug("Added public or package-local method became protected --- affect method usages with protected constraint"); if (!affected) { u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants); affectedUsages.addAll(usages); @@ -1171,6 +1206,8 @@ public class Mappings { debug("Processing added fields"); for (FieldRepr f : diff.fields().added()) { + debug("Field: ", f.name); + final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0; final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0; final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0; @@ -1292,6 +1329,7 @@ public class Mappings { final Collection propagated = u.propagateFieldAccess(field.name, it.name); if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) { + debug("Type or signature changed --- affecting field usages"); u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants); } else if ((d.base() & Difference.ACCESS) > 0) { @@ -1299,7 +1337,7 @@ public class Mappings { (d.removedModifiers() & Opcodes.ACC_STATIC) > 0 || (d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 || (d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) { - + debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages"); u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants); } else { @@ -1307,12 +1345,14 @@ public class Mappings { final Set usages = new HashSet(); if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) { + debug("Added final modifier --- affecting field assign usages"); u.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, dependants); affectedUsages.addAll(usages); affected = true; } if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) { + debug("Removed public modifier, affecting field usages with appropriate constraint"); if (!affected) { u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, dependants); affectedUsages.addAll(usages); @@ -1434,6 +1474,14 @@ public class Mappings { } } + final Collection removedFiles = new HashSet(); + + for (String r : removed) { + removedFiles.add(new File(r)); + } + + affectedFiles.removeAll(removedFiles); + debug("End of Differentiate, returning true"); return true; } From f6a8d4fb1b893839d59b44fac7e513aaebb34602 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 26 Jan 2012 20:44:33 +0400 Subject: [PATCH 047/100] scroll in table on home/end (IDEA-80396) --- .../src/com/intellij/ui/TableScrollingUtil.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java index d3fd4590a245..e3993f86206d 100644 --- a/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java +++ b/platform/platform-api/src/com/intellij/ui/TableScrollingUtil.java @@ -272,6 +272,17 @@ public class TableScrollingUtil { moveEnd(list); } }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), list); + + new AnAction() { + public void actionPerformed(AnActionEvent e) { + moveHome(list); + } + }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0)), list); + new AnAction() { + public void actionPerformed(AnActionEvent e) { + moveEnd(list); + } + }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0)), list); } } From e343fa4fe0d53bd93cd543e25682cdc4fa2ae88a Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:13:10 +0400 Subject: [PATCH 048/100] remove old actions --- .../ui/layout/actions/AttachCellAction.java | 51 ---------------- .../ui/layout/actions/DetachCellAction.java | 59 ------------------- .../ui/layout/actions/MoveToGridAction.java | 50 ---------------- .../ui/layout/actions/MoveToTabAction.java | 56 ------------------ .../src/idea/LangActions.xml | 12 +--- 5 files changed, 1 insertion(+), 227 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java delete mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java delete mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java delete mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java deleted file mode 100644 index 062347e926d7..000000000000 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/AttachCellAction.java +++ /dev/null @@ -1,51 +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.execution.ui.layout.actions; - -import com.intellij.execution.ui.actions.BaseViewAction; -import com.intellij.execution.ui.layout.Grid; -import com.intellij.execution.ui.layout.GridCell; -import com.intellij.execution.ui.layout.ViewContext; -import com.intellij.idea.ActionsBundle; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.content.Content; - -public class AttachCellAction extends BaseViewAction { - - protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { - if (content.length == 0 || !isDetached(context, content[0])) { - setEnabled(e, false); - return; - } - - Grid grid = context.findGridFor(content[0]); - - GridCell cell = grid.getCellFor(content[0]); - if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) { - setEnabled(e, cell.getContentCount() == 1); - } else { - setEnabled(e, true); - if (cell.getContentCount() > 1) { - e.getPresentation().setText(ActionsBundle.message("action.Runner.AttachCells.text", cell.getContentCount())); - } - } - } - - protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { - context.findCellFor(content[0]).attach(); - } -} diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java deleted file mode 100644 index 31215923d4db..000000000000 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/DetachCellAction.java +++ /dev/null @@ -1,59 +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.execution.ui.layout.actions; - -import com.intellij.execution.ui.actions.BaseViewAction; -import com.intellij.execution.ui.layout.Grid; -import com.intellij.execution.ui.layout.GridCell; -import com.intellij.execution.ui.layout.ViewContext; -import com.intellij.idea.ActionsBundle; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.content.Content; - -public class DetachCellAction extends BaseViewAction { - protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { - if (content.length == 0 || isDetached(context, content[0])) { - setEnabled(e, false); - return; - } - - Grid grid = context.findGridFor(content[0]); - if (grid == null) { - setEnabled(e, false); - return; - } - - if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace()) || (ViewContext.TAB_POPUP_PLACE.equals(e.getPlace()))) { - setEnabled(e, grid.getContents().size() == 1); - } - else { - GridCell cell = grid.getCellFor(content[0]); - if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) { - setEnabled(e, cell.getContentCount() == 1); - } else { - setEnabled(e, true); - if (cell.getContentCount() > 1) { - e.getPresentation().setText(ActionsBundle.message("action.Runner.DetachCells.text", cell.getContentCount())); - } - } - } - } - - protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { - context.findCellFor(content[0]).detach(); - } -} diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java deleted file mode 100644 index f66f5014d878..000000000000 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToGridAction.java +++ /dev/null @@ -1,50 +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.execution.ui.layout.actions; - -import com.intellij.execution.ui.actions.BaseViewAction; -import com.intellij.execution.ui.layout.Grid; -import com.intellij.execution.ui.layout.Tab; -import com.intellij.execution.ui.layout.ViewContext; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.content.Content; - -public class MoveToGridAction extends BaseViewAction { - protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { - if (!context.isMoveToGridActionEnabled() || content.length != 1) { - setEnabled(e, false); - return; - } - - if (isDetached(context, content[0])) { - setEnabled(e, false); - return; - } - - Grid grid = context.findGridFor(content[0]); - if (grid == null) { - setEnabled(e, false); - return; - } - Tab tab = context.getTabFor(grid); - setEnabled(e, tab != null && !tab.isDefault() && grid.getContents().size() == 1); - } - - protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { - context.getCellTransform().moveToGrid(content[0]); - } -} diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java deleted file mode 100644 index bf23cb10c3f0..000000000000 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MoveToTabAction.java +++ /dev/null @@ -1,56 +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.execution.ui.layout.actions; - -import com.intellij.execution.ui.actions.BaseViewAction; -import com.intellij.execution.ui.layout.Grid; -import com.intellij.execution.ui.layout.Tab; -import com.intellij.execution.ui.layout.ViewContext; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.ui.content.Content; - -public class MoveToTabAction extends BaseViewAction { - protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { - if (!context.isMoveToGridActionEnabled() || content.length != 1) { - setEnabled(e, false); - return; - } - if (isDetached(context, content[0])) { - setEnabled(e, false); - return; - } - - Grid grid = context.findGridFor(content[0]); - if (grid == null) { - setEnabled(e, false); - return; - } - - - Tab tab = context.getTabFor(grid); - - if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace())) { - setEnabled(e, false); - } else { - setEnabled(e, tab != null && tab.isDefault()); - } - } - - protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { - context.getCellTransform().moveToTab(content[0]); - } -} \ No newline at end of file diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 83c2df79e895..58da8434f90c 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -730,16 +730,11 @@ - + - - - - - @@ -753,12 +748,7 @@ - - - - - From 7647e3b286b929f1d00df30d5cbd434b12e5b29d Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:14:36 +0400 Subject: [PATCH 049/100] allow container customization based on content --- .../src/com/intellij/ui/docking/DockContainerFactory.java | 2 +- .../fileEditor/impl/DockableEditorContainerFactory.java | 3 ++- .../src/com/intellij/ui/docking/impl/DockManagerImpl.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java b/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java index 3dcc059e3de2..6e7e581c61d7 100644 --- a/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java +++ b/platform/platform-api/src/com/intellij/ui/docking/DockContainerFactory.java @@ -20,7 +20,7 @@ import org.jdom.Element; public interface DockContainerFactory extends Disposable { - DockContainer createContainer(); + DockContainer createContainer(DockableContent content); interface Persistent extends DockContainerFactory { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java index f41ac78fee30..e2340d7f1489 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorContainerFactory.java @@ -22,6 +22,7 @@ import com.intellij.openapi.wm.IdeFrame; import com.intellij.ui.docking.DockContainer; import com.intellij.ui.docking.DockContainerFactory; import com.intellij.ui.docking.DockManager; +import com.intellij.ui.docking.DockableContent; import org.jdom.Element; public class DockableEditorContainerFactory implements DockContainerFactory.Persistent { @@ -39,7 +40,7 @@ public class DockableEditorContainerFactory implements DockContainerFactory.Pers } @Override - public DockContainer createContainer() { + public DockContainer createContainer(DockableContent content) { return createContainer(false); } diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java index 9f9700fc1987..fe6e01c69e78 100644 --- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java @@ -355,7 +355,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo } private void createNewDockContainerFor(DockableContent content, RelativePoint point) { - DockContainer container = getFactory(content.getDockContainerType()).createContainer(); + DockContainer container = getFactory(content.getDockContainerType()).createContainer(content); register(container); final DockWindow window = createWindowFor(null, container); From c0c3fbc3f8842c183e6a4b2a9474936ec87e26ab Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:15:33 +0400 Subject: [PATCH 050/100] provide some internals for subclasses --- .../src/com/intellij/ui/tabs/impl/TabLabel.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index 54dd2366b569..63237e5e51b8 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -43,7 +43,7 @@ import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; public class TabLabel extends JPanel { - private final SimpleColoredComponent myLabel = new SimpleColoredComponent() { + protected final SimpleColoredComponent myLabel = new SimpleColoredComponent() { @Override protected boolean shouldDrawMacShadow() { return SystemInfo.isMac; @@ -54,7 +54,7 @@ public class TabLabel extends JPanel { private Icon myOverlayedIcon; private final TabInfo myInfo; - private ActionPanel myActionPanel; + protected ActionPanel myActionPanel; private boolean myCentered; private final Wrapper myLabelPlaceholder = new Wrapper(); @@ -224,7 +224,7 @@ public class TabLabel extends JPanel { }); } - private int getNonSelectedOffset() { + protected int getNonSelectedOffset() { if (myTabs.isEditorTabs()) { int offset = (TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2); if (myTabs.isSingleRow()) { @@ -237,7 +237,7 @@ public class TabLabel extends JPanel { return 2; } - private int getSelectedOffset() { + protected int getSelectedOffset() { return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 1; } From c9f8c377d6c039e9324afcab3d2a496204ba571f Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:24:56 +0400 Subject: [PATCH 051/100] made public for out-of-package TabLabel inheritors --- .../platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java index f4ae28f9729e..9dcd06843d5a 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java @@ -30,7 +30,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -class ActionPanel extends NonOpaquePanel { +public class ActionPanel extends NonOpaquePanel { private final ActionGroup myGroup; private final List myButtons = new ArrayList(); From 0a3e79bff508682cf5123875bc923678c6bc3c8a Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:26:41 +0400 Subject: [PATCH 052/100] custom layout and tab label creation --- .../com/intellij/ui/tabs/impl/JBTabsImpl.java | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 3484decdc008..7439c6729ed7 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -629,7 +629,7 @@ public class JBTabsImpl extends JComponent } info.getChangeSupport().addPropertyChangeListener(this); - final TabLabel label = new TabLabel(this, info); + final TabLabel label = createTabLabel(info); myInfo2Label.put(info, label); if (!isDropTarget) { @@ -674,6 +674,9 @@ public class JBTabsImpl extends JComponent return info; } + protected TabLabel createTabLabel(TabInfo info) { + return new TabLabel(this, info); + } @NotNull public TabInfo addTab(TabInfo info) { @@ -1745,17 +1748,18 @@ public class JBTabsImpl extends JComponent return myInfo2Label.get(getSelectedInfo()); } - static class ShapeInfo { - ShapeTransform path; - ShapeTransform fillPath; - ShapeTransform labelPath; - int labelBottomY; - int labelTopY; - int labelLeftX; - int labelRightX; - Insets insets; - Color from; - Color to; + protected static class ShapeInfo { + public ShapeInfo() {} + public ShapeTransform path; + public ShapeTransform fillPath; + public ShapeTransform labelPath; + public int labelBottomY; + public int labelTopY; + public int labelLeftX; + public int labelRightX; + public Insets insets; + public Color from; + public Color to; } @@ -2977,7 +2981,7 @@ public class JBTabsImpl extends JComponent } } - public static Rectangle layout(JComponent c, Rectangle bounds) { + public Rectangle layout(JComponent c, Rectangle bounds) { final Rectangle now = c.getBounds(); if (!bounds.equals(now)) { c.setBounds(bounds); @@ -2987,7 +2991,7 @@ public class JBTabsImpl extends JComponent return bounds; } - public static Rectangle layout(JComponent c, int x, int y, int width, int height) { + public Rectangle layout(JComponent c, int x, int y, int width, int height) { return layout(c, new Rectangle(x, y, width, height)); } From bb838da86f7a7fa651e8c5d8e34e65b1876e306d Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 19 Jan 2012 19:31:32 +0400 Subject: [PATCH 053/100] custom tabs for runner ui --- .../ui/layout/impl/JBRunnerTabs.java | 248 ++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java new file mode 100644 index 000000000000..e25153e2543f --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -0,0 +1,248 @@ +/* + * Copyright 2000-2012 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.execution.ui.layout.impl; + +import com.intellij.openapi.Disposable; +import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.ui.Gray; +import com.intellij.ui.tabs.TabInfo; +import com.intellij.ui.tabs.TabsUtil; +import com.intellij.ui.tabs.UiDecorator; +import com.intellij.ui.tabs.impl.JBTabsImpl; +import com.intellij.ui.tabs.impl.TabLabel; +import com.intellij.util.ui.SameColor; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.awt.*; +import java.util.List; + +/** + * @author Dennis.Ushakov + */ +public class JBRunnerTabs extends JBTabsImpl { + public JBRunnerTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { + super(project, actionManager, focusManager, parent); + } + + @Override + protected void paintFirstGhost(Graphics2D g2d) {} + + @Override + protected void paintLastGhost(Graphics2D g2d) {} + + public boolean isGhostsAlwaysVisible() { + return false; + } + + protected void doPaintInactive(Graphics2D g2d, + boolean leftGhostExists, + TabLabel label, + Rectangle effectiveBounds, + boolean rightGhostExists) { + Insets insets = getTabsBorder().getEffectiveBorder(); + + int _x = effectiveBounds.x + insets.left; + int _y = effectiveBounds.y + insets.top + 5; + int _width = effectiveBounds.width - insets.left - insets.right; + int _height = effectiveBounds.height - insets.top - insets.bottom - 5; + _height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + + g2d + .setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 180), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 100))); + g2d.fillRect(_x, _y, _width, _height); + + g2d.setColor(new Color(255, 255, 255, 100)); + g2d.drawRect(_x, _y, _width - 1, _height - 1); + } + + @Override + protected void doPaintBackground(Graphics2D g2d, Rectangle clip) { + g2d.setColor(UIUtil.getPanelBackground()); + g2d.fill(clip); + + g2d.setColor(new Color(0, 0, 0, 50)); + g2d.fill(clip); + + List visibleInfos = getVisibleInfos(); + + Insets insets = getTabsBorder().getEffectiveBorder(); + + int maxOffset = 0; + int maxLength = 0; + + for (int i = visibleInfos.size() - 1; i >= 0; i--) { + TabInfo visibleInfo = visibleInfos.get(i); + TabLabel tabLabel = myInfo2Label.get(visibleInfo); + Rectangle r = tabLabel.getBounds(); + if (r.width == 0 || r.height == 0) continue; + maxOffset = r.x + r.width; + maxLength = r.height; + break; + } + + maxOffset++; + + Rectangle r2 = getBounds(); + + Rectangle rectangle; + int y = r2.y + insets.top; + int height = maxLength - insets.top - insets.bottom; + height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT; + + rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height); + + g2d.setPaint(UIUtil.getPanelBackground()); + g2d.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + g2d.fillRect(0, 0, rectangle.x + rectangle.width, 5); + g2d.fillRect(2, maxLength, getSize().width, getSize().height); + g2d.drawLine(0, 0, 0, getSize().height); + } + + protected void paintSelectionAndBorder(Graphics2D g2d) { + if (getSelectedInfo() == null) return; + + TabLabel label = getSelectedLabel(); + Rectangle r = label.getBounds(); + r = new Rectangle(r.x, r.y + 5, r.width, r.height - 5); + + ShapeInfo selectedShape = _computeSelectedLabelShape(r); + + Insets insets = getTabsBorder().getEffectiveBorder(); + Insets i = selectedShape.path.transformInsets(insets); + + int _x = r.x; + int _y = r.y; + int _height = r.height; + + g2d.setPaint(new GradientPaint(_x, _y, new SameColor(255), _x, _y + _height, UIUtil.getPanelBackground())); + + g2d.fill(selectedShape.fillPath.getShape()); + + g2d.setColor(new Color(255, 255, 255, 180)); + g2d.draw(selectedShape.fillPath.getShape()); + + g2d.setColor(UIUtil.getPanelBackground()); + g2d.fillRect(2, selectedShape.labelPath.getMaxY() - 3, selectedShape.path.getMaxX() - 3, 4); + g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1); + g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4, + selectedShape.path.getMaxX() - 1, getHeight() - 1); + g2d.setColor(new Color(0, 0, 0, 50)); + g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1); + g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4, + selectedShape.path.getMaxX() - 1, getHeight() - 1); + } + + @Override + public Color getBackground() { + return Gray._142; + } + + protected ShapeInfo _computeSelectedLabelShape(Rectangle r) { + final ShapeInfo shape = new ShapeInfo(); + + shape.path = getEffectiveLayout().createShapeTransform(getSize()); + shape.insets = shape.path.transformInsets(getLayoutInsets()); + shape.labelPath = shape.path.createTransform(r); + + shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1); + shape.labelTopY = shape.labelPath.getY() + shape.labelPath.deltaY(1); + shape.labelLeftX = shape.labelPath.getX(); + shape.labelRightX = shape.labelPath.getMaxX() - shape.labelPath.deltaX(1); + + int leftX = shape.insets.left; + + shape.path.moveTo(leftX, shape.labelBottomY); + shape.path.lineTo(shape.labelLeftX, shape.labelBottomY); + shape.path.lineTo(shape.labelLeftX, shape.labelTopY); + shape.path.lineTo(shape.labelRightX, shape.labelTopY); + shape.path.lineTo(shape.labelRightX, shape.labelBottomY); + + int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right); + + shape.path.lineTo(lastX, shape.labelBottomY); + shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); + shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1)); + + shape.path.closePath(); + shape.fillPath = shape.path.copy(); + + return shape; + } + + @Override + public int getToolbarInset() { + return 8; + } + + @Override + public Rectangle layout(JComponent c, Rectangle bounds) { + if (c instanceof Toolbar) { + bounds.height -= 5; + return super.layout(c, bounds); + } + if (c instanceof GridImpl) { + bounds.x -= 1; + bounds.width += 1; + } + return super.layout(c, bounds); + } + + @Override + protected TabLabel createTabLabel(TabInfo info) { + return new MyTabLabel(this, info); + } + + private static class MyTabLabel extends TabLabel { + public MyTabLabel(JBTabsImpl tabs, final TabInfo info) { + super(tabs, info); + } + + @Override + public void apply(UiDecorator.UiDecoration decoration) { + setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL)); + myLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL)); + setBorder(new EmptyBorder(7, 5, 7, 5)); + } + + @Override + public void setTabActionsAutoHide(boolean autoHide) { + super.setTabActionsAutoHide(autoHide); + apply(null); + } + + @Override + public void setTabActions(ActionGroup group) { + super.setTabActions(group); + if (myActionPanel != null) { + final JComponent wrapper = (JComponent)myActionPanel.getComponent(0); + wrapper.remove(0); + wrapper.add(Box.createHorizontalStrut(6), BorderLayout.WEST); + } + } + + @Override + protected int getSelectedOffset() { + return getNonSelectedOffset(); + } + } +} From 5ad80f601f30d45563bc4a8055e0c0eebb153889 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 20 Jan 2012 19:18:21 +0400 Subject: [PATCH 054/100] changed method name --- .../src/com/intellij/ui/docking/DockContainer.java | 2 +- .../fileEditor/impl/DockableEditorTabbedContainer.java | 2 +- .../src/com/intellij/ui/docking/impl/DockManagerImpl.java | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java b/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java index f599a1d8bcd2..25fb02896813 100644 --- a/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java +++ b/platform/platform-api/src/com/intellij/ui/docking/DockContainer.java @@ -30,7 +30,7 @@ public interface DockContainer extends Disposable, Activatable { RelativeRectangle getAcceptArea(); boolean canAccept(DockableContent content, RelativePoint point); - JComponent getComponent(); + JComponent getContainerComponent(); void add(DockableContent content, RelativePoint dropTarget); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java index f2c24a9de973..11c212bc71ca 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/DockableEditorTabbedContainer.java @@ -187,7 +187,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent { } @Override - public JComponent getComponent() { + public JComponent getContainerComponent() { return mySplitters; } diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java index fe6e01c69e78..738d25fdfc26 100644 --- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java @@ -122,7 +122,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo @Override public IdeFrame getIdeFrame(DockContainer container) { - Component parent = UIUtil.findUltimateParent(container.getComponent()); + Component parent = UIUtil.findUltimateParent(container.getContainerComponent()); if (parent instanceof IdeFrame) { return (IdeFrame)parent; } @@ -143,7 +143,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo if (c == null) return null; for (DockContainer eachContainer : myContainers) { - if (SwingUtilities.isDescendingFrom(c, eachContainer.getComponent())) { + if (SwingUtilities.isDescendingFrom(c, eachContainer.getContainerComponent())) { return eachContainer; } } @@ -152,7 +152,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo if (parent == null) return null; for (DockContainer eachContainer : myContainers) { - if (parent == UIUtil.findUltimateParent(eachContainer.getComponent())) { + if (parent == UIUtil.findUltimateParent(eachContainer.getContainerComponent())) { return eachContainer; } } @@ -424,7 +424,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo center.add(myNorthPanel, BorderLayout.NORTH); myDockContentUiContainer = new NonOpaquePanel(new BorderLayout()); - myDockContentUiContainer.add(myContainer.getComponent(), BorderLayout.CENTER); + myDockContentUiContainer.add(myContainer.getContainerComponent(), BorderLayout.CENTER); center.add(myDockContentUiContainer, BorderLayout.CENTER); myUiContainer.add(center, BorderLayout.CENTER); From d50b44342adbcc5b36363f9ab3590250cb4ed396 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 24 Jan 2012 15:07:29 +0400 Subject: [PATCH 055/100] expose creation of new window --- .../src/com/intellij/ui/docking/impl/DockManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java index 738d25fdfc26..b490ba433f58 100644 --- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java @@ -354,7 +354,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo return myFactories.get(type); } - private void createNewDockContainerFor(DockableContent content, RelativePoint point) { + public void createNewDockContainerFor(DockableContent content, RelativePoint point) { DockContainer container = getFactory(content.getDockContainerType()).createContainer(content); register(container); From 972c720e0ffcbd89f024c44b540e595de3e05d4e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 24 Jan 2012 16:47:22 +0400 Subject: [PATCH 056/100] drag and drop for runner toolwindow --- .../execution/ui/actions/BaseViewAction.java | 6 - .../execution/ui/layout/CellTransform.java | 6 - .../execution/ui/layout/GridCell.java | 7 - .../intellij/execution/ui/layout/View.java | 4 + .../execution/impl/ExecutionManagerImpl.java | 3 +- .../execution/ui/RunContentManagerImpl.java | 8 +- .../ui/layout/actions/MinimizeViewAction.java | 12 +- .../impl/DockableGridContainerFactory.java | 36 ++ .../ui/layout/impl/GridCellImpl.java | 219 ++----- .../execution/ui/layout/impl/GridImpl.java | 46 +- .../ui/layout/impl/JBRunnerTabs.java | 5 +- .../ui/layout/impl/RunnerContentUi.java | 550 +++++++++++++----- .../ui/layout/impl/ViewContextEx.java | 7 +- .../execution/ui/layout/impl/ViewImpl.java | 17 +- .../src/idea/LangActions.xml | 5 +- 15 files changed, 552 insertions(+), 379 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java diff --git a/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java b/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java index 869491c8a685..06c8cd55a7d7 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java +++ b/platform/lang-api/src/com/intellij/execution/ui/actions/BaseViewAction.java @@ -17,7 +17,6 @@ package com.intellij.execution.ui.actions; import com.intellij.execution.ui.layout.Grid; -import com.intellij.execution.ui.layout.GridCell; import com.intellij.execution.ui.layout.Tab; import com.intellij.execution.ui.layout.ViewContext; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -74,11 +73,6 @@ public abstract class BaseViewAction extends DumbAwareAction { return e.getData(ViewContext.CONTENT_KEY); } - protected static boolean isDetached(ViewContext context, Content content) { - final GridCell cell = context.findCellFor(content); - return cell != null && cell.isDetached(); - } - @Nullable protected static Tab getTabFor(final ViewContext context, final Content[] content) { Grid grid = context.findGridFor(content[0]); diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java b/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java index e37c46a19083..b9c7b21da197 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java +++ b/platform/lang-api/src/com/intellij/execution/ui/layout/CellTransform.java @@ -72,12 +72,6 @@ public interface CellTransform { interface Facade { void minimize(Content content, Restore restore); - - void moveToTab(final Content content); - - void moveToGrid(final Content content); - - Restore detach(final Content[] content); } } diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java b/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java index 2201bd8d6699..ebcbdd6a2a51 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java +++ b/platform/lang-api/src/com/intellij/execution/ui/layout/GridCell.java @@ -16,17 +16,10 @@ package com.intellij.execution.ui.layout; -import com.intellij.openapi.util.ActionCallback; import com.intellij.ui.content.Content; public interface GridCell { - boolean isDetached(); - int getContentCount(); - void attach(); - void minimize(final Content content); - - ActionCallback detach(); } \ No newline at end of file diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/View.java b/platform/lang-api/src/com/intellij/execution/ui/layout/View.java index 761a1b502250..c81532e8105f 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/layout/View.java +++ b/platform/lang-api/src/com/intellij/execution/ui/layout/View.java @@ -32,4 +32,8 @@ public interface View { void assignTab(Tab tab); void setTabIndex(int tabIndex); + + int getWindow(); + + void setWindow(int windowNumber); } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java index c78850c2ca40..d2672ff88fc1 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java @@ -35,6 +35,7 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.ui.docking.DockManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -76,7 +77,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom public RunContentManager getContentManager() { if (myContentManager == null) { - myContentManager = new RunContentManagerImpl(myProject); + myContentManager = new RunContentManagerImpl(myProject, DockManager.getInstance(myProject)); Disposer.register(myProject, myContentManager); } return myContentManager; diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java index 7a42e42487ac..0a6f6b508feb 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java @@ -23,6 +23,7 @@ import com.intellij.execution.process.ProcessAdapter; import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.GenericProgramRunner; +import com.intellij.execution.ui.layout.impl.DockableGridContainerFactory; import com.intellij.ide.DataManager; import com.intellij.ide.impl.ContentManagerWatcher; import com.intellij.openapi.Disposable; @@ -47,6 +48,7 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.ui.content.*; +import com.intellij.ui.docking.DockManager; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; @@ -65,13 +67,17 @@ public class RunContentManagerImpl implements RunContentManager, Disposable { private static final Key DESCRIPTOR_KEY = new Key("Descriptor"); private final Project myProject; + private DockableGridContainerFactory myContentFactory; private final Map myToolwindowIdToContentManagerMap = new HashMap(); private final Map myListeners = new HashMap(); private final LinkedList myToolwindowIdZbuffer = new LinkedList(); - public RunContentManagerImpl(Project project) { + public RunContentManagerImpl(Project project, DockManager dockManager) { myProject = project; + myContentFactory = new DockableGridContainerFactory(); + dockManager.register(DockableGridContainerFactory.TYPE, myContentFactory); + Disposer.register(myProject, myContentFactory); } public void init() { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java index 79982fb99f8b..fc16369ed688 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/MinimizeViewAction.java @@ -39,19 +39,15 @@ public class MinimizeViewAction extends BaseViewAction { return false; } - if (isDetached(context, content[0])) { - return false; - } - if (ViewContext.TAB_TOOLBAR_PLACE.equals(place) || ViewContext.TAB_POPUP_PLACE.equals(place)) { - return false; - } - else { Tab tab = getTabFor(context, content); if (tab == null) { return false; } - return tab.isDefault(); + return !tab.isDefault(); + } + else { + return getTabFor(context, content) != null; } } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java new file mode 100644 index 000000000000..4e9c694291d9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/DockableGridContainerFactory.java @@ -0,0 +1,36 @@ +/* + * Copyright 2000-2012 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.execution.ui.layout.impl; + +import com.intellij.ui.docking.DockContainer; +import com.intellij.ui.docking.DockContainerFactory; +import com.intellij.ui.docking.DockableContent; + +/** + * @author Dennis.Ushakov + */ +public class DockableGridContainerFactory implements DockContainerFactory { + public static final String TYPE = "runner-grid"; + + @Override + public DockContainer createContainer(DockableContent content) { + final RunnerContentUi.DockableGrid dockableGrid = (RunnerContentUi.DockableGrid)content; + return new RunnerContentUi(dockableGrid.getRunnerUi(), dockableGrid.getOriginalRunnerUi(), dockableGrid.getWindow()); + } + + @Override + public void dispose() {} +} diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index f479bc7860e9..0393f7ada11a 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -18,18 +18,16 @@ package com.intellij.execution.ui.layout.impl; import com.intellij.execution.ui.layout.*; import com.intellij.execution.ui.layout.actions.MinimizeViewAction; -import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.DataProvider; -import com.intellij.openapi.ui.popup.ComponentPopupBuilder; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.ui.popup.JBPopupFactory; -import com.intellij.openapi.util.*; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.DimensionService; +import com.intellij.openapi.util.MutualMap; import com.intellij.ui.components.panels.NonOpaquePanel; -import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.content.Content; +import com.intellij.ui.docking.DockContainer; +import com.intellij.ui.docking.DockManager; import com.intellij.ui.switcher.SwitchTarget; import com.intellij.ui.tabs.JBTabs; import com.intellij.ui.tabs.TabInfo; @@ -43,14 +41,15 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.EmptyBorder; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.List; import java.util.Set; -public class GridCellImpl implements GridCell, Disposable { +public class GridCellImpl implements GridCell { + static final String CELL_KEY = "runner-grid-cell"; private final GridImpl myContainer; @@ -62,16 +61,12 @@ public class GridCellImpl implements GridCell, Disposable { private final PlaceInGrid myPlaceInGrid; private final ViewContextEx myContext; - private CellTransform.Restore.List myRestoreFromDetach; private JBPopup myPopup; - private boolean myDisposed; public GridCellImpl(ViewContextEx context, @NotNull GridImpl container, GridImpl.Placeholder placeholder, PlaceInGrid placeInGrid) { myContext = context; myContainer = container; - Disposer.register(container, this); - myPlaceInGrid = placeInGrid; myPlaceholder = placeholder; myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container).setDataProvider(new DataProvider() { @@ -97,18 +92,12 @@ public class GridCellImpl implements GridCell, Disposable { } }).setSideComponentVertical(!context.getLayoutSettings().isToolbarHorizontal()) .setStealthTabMode(true) - .setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false); + .setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false).setTabDraggingEnabled(true); myTabs.addTabMouseListener(new MouseAdapter() { public void mousePressed(final MouseEvent e) { if (UIUtil.isCloseClick(e)) { - if (isDetached()) { - myPopup.cancel(); - myPopup = null; - } - else { minimize(e); - } } } }); @@ -181,7 +170,7 @@ public class GridCellImpl implements GridCell, Disposable { } } else { - if (myPlaceholder.isNull() && !isDetached()) { + if (myPlaceholder.isNull()) { myPlaceholder.setContent(myTabs.getComponent()); } @@ -211,7 +200,7 @@ public class GridCellImpl implements GridCell, Disposable { ActionGroup group = (ActionGroup)myContext.getActionManager().getAction(RunnerContentUi.VIEW_TOOLBAR); tabInfo.setTabLabelActions(group, ViewContext.CELL_TOOLBAR_PLACE); - + tabInfo.setDragOutDelegate(((RunnerContentUi)myContext).myDragOutDelegate); return tabInfo; } @@ -248,7 +237,7 @@ public class GridCellImpl implements GridCell, Disposable { return myMinimizedContents.contains(content); } - public java.util.List getTargets(boolean onlyVisible) { + public List getTargets(boolean onlyVisible) { if (myTabs.getPresentation().isHideTabs()) return new ArrayList(); return myTabs.getTargets(onlyVisible, false); @@ -271,6 +260,7 @@ public class GridCellImpl implements GridCell, Disposable { myContent = content; myContext = context; setLayout(new BorderLayout()); + putClientProperty(CELL_KEY, Boolean.TRUE); add(content.getComponent(), BorderLayout.CENTER); } @@ -287,7 +277,7 @@ public class GridCellImpl implements GridCell, Disposable { } @Nullable - private TabInfo getTabFor(Content content) { + TabInfo getTabFor(Content content) { return myContents.getValue(content); } @@ -306,14 +296,21 @@ public class GridCellImpl implements GridCell, Disposable { restoreProportions(); Content[] contents = getContents(); + int window = 0; for (Content each : contents) { - if (myContainer.getStateFor(each).isMinimizedInGrid()) { + final View view = myContainer.getStateFor(each); + if (view.isMinimizedInGrid()) { minimize(each); } + window = view.getWindow(); } - - if (!isRestoringFromDetach() && myContainer.getTab().isDetached(myPlaceInGrid) && contents.length > 0) { - _detach(!myContext.isStateBeingRestored()).notifyWhenDone(result); + final Tab tab = myContainer.getTab(); + final boolean detached = (tab != null && tab.isDetached(myPlaceInGrid)) || window != myContext.getWindow(); + if (detached && contents.length > 0) { + if (tab != null) { + tab.setDetached(myPlaceInGrid, false); + } + _detach(window).notifyWhenDone(result); } else { result.setDone(); } @@ -321,7 +318,7 @@ public class GridCellImpl implements GridCell, Disposable { return result; } - private Content[] getContents() { + Content[] getContents() { return myContents.getKeys().toArray(new Content[myContents.size()]); } @@ -339,6 +336,14 @@ public class GridCellImpl implements GridCell, Disposable { for (Content each : myMinimizedContents) { saveState(each, true); } + + final DimensionService service = DimensionService.getInstance(); + final Dimension size = myContext.getContentManager().getComponent().getSize(); + service.setSize(getDimensionKey(), size, myContext.getProject()); + if (myContext.getWindow() != 0) { + final JFrame frame = (JFrame)DockManager.getInstance(myContext.getProject()).getIdeFrame((DockContainer)myContext); + service.setLocation(getDimensionKey(), frame.getLocationOnScreen()); + } } public void saveProportions() { @@ -350,8 +355,7 @@ public class GridCellImpl implements GridCell, Disposable { state.setMinimizedInGrid(minimized); state.setPlaceInGrid(myPlaceInGrid); state.assignTab(myContainer.getTabIndex()); - - state.getTab().setDetached(myPlaceInGrid, isDetached()); + state.setWindow(myContext.getWindow()); } public void restoreProportions() { @@ -362,7 +366,7 @@ public class GridCellImpl implements GridCell, Disposable { for (Content each : myContents.getKeys()) { final TabInfo eachTab = getTabFor(each); boolean isSelected = eachTab != null && myTabs.getSelectedInfo() == eachTab; - if (isSelected && (isShowing || isDetached())) { + if (isSelected && isShowing) { myContext.getContentManager().addSelectedContent(each); } else { @@ -391,147 +395,27 @@ public class GridCellImpl implements GridCell, Disposable { } } - public ActionCallback detach() { - return _detach(true); - } - - private ActionCallback _detach(final boolean requestFocus) { + private ActionCallback _detach(final int window) { myContext.saveUiState(); - - final DimensionService dimService = DimensionService.getInstance(); - Point storedLocation = dimService.getLocation(getDimensionKey(), myContext.getProject()); - Dimension storedSize = dimService.getSize(getDimensionKey(), myContext.getProject()); - - final IdeFrame frame = WindowManager.getInstance().getIdeFrame(myContext.getProject()); - final Rectangle targetBounds = frame.suggestChildFrameBounds(); - - - if (storedLocation != null && storedSize != null) { - targetBounds.setLocation(storedLocation); - targetBounds.setSize(storedSize); - } - - final ActionCallback result = new ActionCallback(); - - if (storedLocation == null || storedSize == null) { - if (myContents.size() > 0) { - myContext.validate(myContents.getKeys().iterator().next(), new ActiveRunnable() { - public ActionCallback run() { - if (!myTabs.getComponent().isShowing()) { - detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result); - } else { - detachForShowingTabs(requestFocus).notifyWhenDone(result); - } - - return new ActionCallback.Done(); - } - }); - - return result; - } - } - - detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result); - - return result; + return myContext.detachTo(window, this); } - private ActionCallback detachForShowingTabs(boolean requestFocus) { - return detachTo(myTabs.getComponent().getLocationOnScreen(), myTabs.getComponent().getSize(), false, requestFocus); + @Nullable + public Point getLocation() { + return DimensionService.getInstance().getLocation(getDimensionKey(), myContext.getProject()); } - private ActionCallback detachTo(Point screenPoint, Dimension size, boolean dragging, final boolean requestFocus) { - if (isDetached()) { - if (myPopup != null) { - return new ActionCallback.Done(); - } - } - - final Content[] contents = getContents(); - - myRestoreFromDetach = new CellTransform.Restore.List(); - - myRestoreFromDetach.add(myPlaceholder.detach()); - myRestoreFromDetach.add(myContainer.detach(contents)); - myRestoreFromDetach.add(new CellTransform.Restore() { - public ActionCallback restoreInGrid() { - ensureVisible(); - return new ActionCallback.Done(); - } - }); - - myPopup = createPopup(dragging, requestFocus); - myPopup.setSize(size); - myPopup.setLocation(screenPoint); - myPopup.show(myContext.getContentManager().getComponent()); - - myContext.saveUiState(); - - myTabs.updateTabActions(true); - - return new ActionCallback.Done(); + @Nullable + public Dimension getSize() { + return DimensionService.getInstance().getSize(getDimensionKey(), myContext.getProject()); } - - private void ensureVisible() { - if (myTabs.getSelectedInfo() != null) { - myContext.select(getContentFor(myTabs.getSelectedInfo()), true); - } - } - - private JBPopup createPopup(boolean dragging, final boolean requestFocus) { - Wrapper wrapper = new Wrapper(myTabs.getComponent()); - wrapper.setBorder(new EmptyBorder(1, 0, 0, 0)); - final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(wrapper, myTabs.getComponent()) - .setTitle(myContainer.getSessionName()) - .setMovable(true) - .setRequestFocus(requestFocus) - .setFocusable(true) - .setResizable(true) - .setDimensionServiceKey(myContext.getProject(), getDimensionKey(), true) - .setCancelOnOtherWindowOpen(false) - .setCancelOnClickOutside(false) - .setCancelKeyEnabled(true) - .setLocateByContent(dragging) - .setLocateWithinScreenBounds(!dragging) - .setCancelKeyEnabled(false) - .setBelongsToGlobalPopupStack(false) - .setModalContext(false) - .setCancelCallback(new Computable() { - public Boolean compute() { - if (myDisposed || myContents.size() == 0) return Boolean.TRUE; - myRestoreFromDetach.restoreInGrid(); - myRestoreFromDetach = null; - myContext.saveUiState(); - myTabs.updateTabActions(true); - return Boolean.TRUE; - } - }); - - return builder.createPopup(); - } - - public void attach() { - if (isDetached()) { - myPopup.cancel(); - myPopup = null; - } - } - - - public boolean isDetached() { - return myRestoreFromDetach != null && !myRestoreFromDetach.isRestoringNow(); - } - - public boolean isRestoringFromDetach() { - return myRestoreFromDetach != null && myRestoreFromDetach.isRestoringNow(); - } - + private String getDimensionKey() { return "GridCell.Tab." + myContainer.getTab().getIndex() + "." + myPlaceInGrid.name(); } - public boolean isValidForCalculatePropertions() { - return !isDetached() && getContentCount() > 0; + public boolean isValidForCalculateProportions() { + return getContentCount() > 0; } public void minimize(Content content) { @@ -553,13 +437,4 @@ public class GridCellImpl implements GridCell, Disposable { updateSelection(myTabs.getComponent().getRootPane() != null); return new ActionCallback.Done(); } - - public void dispose() { - myDisposed = true; - - if (myPopup != null) { - myPopup.cancel(); - myPopup = null; - } - } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java index dfb6659f6c1a..f023d86d3a9b 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridImpl.java @@ -35,7 +35,7 @@ import java.awt.*; import java.util.*; import java.util.List; -public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform.Facade, DataProvider { +public class GridImpl extends Wrapper implements Grid, Disposable, DataProvider { private final ThreeComponentsSplitter myTopSplit = new ThreeComponentsSplitter(); private final Splitter mySplitter = new Splitter(true); @@ -152,8 +152,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform public boolean updateGridUI() { for (final GridCellImpl cell : myPlaceInGrid2Cell.values()) { - final boolean eachToHide = myContents.size() == 1 && !cell.isDetached(); - cell.setHideTabs(eachToHide); + cell.setHideTabs(myContents.size() == 1); } final Content onlyContent = myContents.get(0); @@ -252,7 +251,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform final GridCellImpl cell = myPlaceInGrid2Cell.get(placeInGrid); - if (!cell.isValidForCalculatePropertions()) return; + if (!cell.isValidForCalculateProportions()) return; final TabImpl tab = (TabImpl)getTab(); @@ -335,19 +334,12 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform ArrayList result = new ArrayList(); for (Content each : getContents()) { - if (!isDetached(each)) { - result.add(each); - } + result.add(each); } return result; } - - public boolean isDetached(Content content) { - return getCellFor(content).isDetached(); - } - public List getContents() { return myContents; } @@ -360,28 +352,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform }); } - public void moveToTab(final Content content) { - myViewContext.getCellTransform().moveToTab(content); - } - - public void moveToGrid(final Content content) { - myViewContext.getCellTransform().moveToGrid(content); - } - - public CellTransform.Restore detach(final Content[] content) { - final CellTransform.Restore.List restore = new CellTransform.Restore.List(); - restore.add(myViewContext.getCellTransform().detach(content)); - restore.add(new CellTransform.Restore() { - public ActionCallback restoreInGrid() { - revalidate(); - repaint(); - return new ActionCallback.Done(); - } - }); - - return restore; - } - @Nullable public Object getData(@NonNls final String dataId) { if (ViewContext.CONTEXT_KEY.is(dataId)) { @@ -394,10 +364,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform return null; } - public String getSessionName() { - return mySessionName; - } - @Nullable public SwitchTarget getCellFor(Component c) { Component eachParent = c; @@ -419,9 +385,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform Collection cells = myPlaceInGrid2Cell.values(); ArrayList result = new ArrayList(); for (GridCellImpl each : cells) { - if (!each.isDetached()) { - result.addAll(each.getTargets(onlyVisible)); - } + result.addAll(each.getTargets(onlyVisible)); } return result; } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index e25153e2543f..33125c2ddf34 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -39,7 +39,8 @@ import java.util.List; /** * @author Dennis.Ushakov */ -public class JBRunnerTabs extends JBTabsImpl { +public class + JBRunnerTabs extends JBTabsImpl { public JBRunnerTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) { super(project, actionManager, focusManager, parent); } @@ -211,7 +212,7 @@ public class JBRunnerTabs extends JBTabsImpl { protected TabLabel createTabLabel(TabInfo info) { return new MyTabLabel(this, info); } - + private static class MyTabLabel extends TabLabel { public MyTabLabel(JBTabsImpl tabs, final TabInfo info) { super(tabs, info); diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index b2732529f4f6..72367679832f 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -28,21 +28,28 @@ import com.intellij.openapi.util.ActiveRunnable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Ref; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.ToolWindow; import com.intellij.ui.UIBundle; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.awt.RelativeRectangle; import com.intellij.ui.components.panels.NonOpaquePanel; import com.intellij.ui.components.panels.Wrapper; import com.intellij.ui.content.*; +import com.intellij.ui.docking.DockContainer; +import com.intellij.ui.docking.DockManager; +import com.intellij.ui.docking.DockableContent; +import com.intellij.ui.docking.DragSession; +import com.intellij.ui.docking.impl.DockManagerImpl; import com.intellij.ui.switcher.QuickActionProvider; import com.intellij.ui.switcher.SwitchProvider; import com.intellij.ui.switcher.SwitchTarget; import com.intellij.ui.tabs.JBTabs; import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsListener; -import com.intellij.ui.tabs.UiDecorator; -import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.AbstractLayoutManager; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -50,13 +57,15 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; +import java.util.concurrent.CopyOnWriteArraySet; public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Facade, ViewContextEx, PropertyChangeListener, SwitchProvider, - QuickActionProvider { + QuickActionProvider, DockContainer { @NonNls public static final String LAYOUT = "Runner.Layout"; @NonNls public static final String VIEW_POPUP = "Runner.View.Popup"; @@ -70,8 +79,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac MyComponent myComponent = new MyComponent(); private final Wrapper myToolbar = new Wrapper(); + final MyDragOutDelegate myDragOutDelegate = new MyDragOutDelegate(); - JBTabs myTabs; + JBRunnerTabs myTabs; private final Comparator myTabsComparator = new Comparator() { public int compare(final TabInfo o1, final TabInfo o2) { //noinspection ConstantConditions @@ -110,6 +120,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac private int myAttractionCount; private ActionGroup myLeftToolbarActions; + private JBTabs myCurrentOver; + private Image myCurrentOverImg; + private TabInfo myCurrentOverInfo; + private RunnerContentUi myOriginal; + private CopyOnWriteArraySet myDockingListeners = new CopyOnWriteArraySet(); + private List myChildren = new ArrayList(); + private int myWindow; + private int ourWindowCounter; + public RunnerContentUi(Project project, RunnerLayoutUi ui, ActionManager actionManager, @@ -124,6 +143,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac myFocusManager = focusManager; } + public RunnerContentUi(RunnerContentUi ui, RunnerContentUi original, int window) { + this(ui.myProject, ui.myRunnerUi, ui.myActionManager, ui.myFocusManager, ui.myLayoutSettings, ui.mySessionName); + myOriginal = original; + original.myChildren.add(this); + myWindow = window == 0 ? original.findFreeWindow() : window; + } public void setTopActions(@NotNull final ActionGroup topActions, @NotNull String place) { myTopActions = topActions; @@ -150,32 +175,27 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac public void initUi() { if (myTabs != null) return; - myTabs = new JBTabsImpl(myProject, myActionManager, myFocusManager, this) - .setDataProvider(new DataProvider() { - public Object getData(@NonNls final String dataId) { - if (ViewContext.CONTENT_KEY.is(dataId)) { - TabInfo info = myTabs.getTargetInfo(); - if (info != null) { - return getGridFor(info).getData(dataId); - } + myTabs = (JBRunnerTabs)new JBRunnerTabs(myProject, myActionManager, myFocusManager, this).setDataProvider(new DataProvider() { + public Object getData(@NonNls final String dataId) { + if (ViewContext.CONTENT_KEY.is(dataId)) { + TabInfo info = myTabs.getTargetInfo(); + if (info != null) { + return getGridFor(info).getData(dataId); } - else if (ViewContext.CONTEXT_KEY.is(dataId)) { - return RunnerContentUi.this; - } - return null; } - }).setProvideSwitchTargets(false).setInnerInsets(new Insets(1, 0, 0, 0)).setToDrawBorderIfTabsHidden(false) - .setUiDecorator(new UiDecorator() { - @NotNull - public UiDecoration getDecoration() { - return new UiDecoration(null, new Insets(1, 8, 1, 8)); + else if (ViewContext.CONTEXT_KEY.is(dataId)) { + return RunnerContentUi.this; } - }).getJBTabs(); + return null; + } + }).setTabLabelActionsAutoHide(false).setProvideSwitchTargets(false).setInnerInsets(new Insets(0, 0, 0, 0)) + .setToDrawBorderIfTabsHidden(false).setTabDraggingEnabled(isMoveToGridActionEnabled()).setUiDecorator(null).getJBTabs(); rebuildTabPopup(); - - myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(2).setPaintFocus(false) + myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setPaintFocus(false) .setRequestFocusOnLastFocusedComponent(true); + myTabs.getComponent().setBackground(myToolbar.getBackground()); + myTabs.getComponent().setBorder(new EmptyBorder(0, 2, 0, 0)); final NonOpaquePanel wrappper = new NonOpaquePanel(new BorderLayout(0, 0)); wrappper.add(myToolbar, BorderLayout.WEST); @@ -207,6 +227,14 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } }); + + if (myOriginal != null) { + final ContentManager manager = ContentFactory.SERVICE.getInstance().createContentManager(this, false, myProject); + Disposer.register((Disposable)myRunnerUi, manager); + manager.getComponent(); + } else { + DockManager.getInstance(myProject).register(this); + } } private void rebuildTabPopup() { @@ -249,10 +277,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return group; } - public void doWhenInitialized(final Runnable runnable) { - myInitialized.doWhenDone(runnable); + @Override + public boolean isOriginal() { + return myOriginal == null; } + @Override + public int getWindow() { + return myWindow; + } public void propertyChange(final PropertyChangeEvent evt) { Content content = (Content)evt.getSource(); @@ -302,11 +335,191 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } + @Override + public ActionCallback detachTo(int window, GridCell cell) { + if (myOriginal != null) { + return myOriginal.detachTo(window, cell); + } + RunnerContentUi target = null; + if (window > 0) { + for (RunnerContentUi child : myChildren) { + if (child.myWindow == window) { + target = child; + break; + } + } + } + final GridCellImpl gridCell = (GridCellImpl)cell; + final Content[] contents = gridCell.getContents(); + Dimension size = gridCell.getSize(); + if (size == null) { + size = new Dimension(200, 200); + } + final DockableGrid content = new DockableGrid(null, null, size, Arrays.asList(contents), window); + if (target != null) { + target.add(content, null); + } else { + final Point location = gridCell.getLocation(); + location.translate(size.width / 2, size.height / 2); + getDockManager().createNewDockContainerFor(content, new RelativePoint(location)); + } + return new ActionCallback.Done(); + } + + @Override + public RelativeRectangle getAcceptArea() { + return new RelativeRectangle(myTabs.getComponent()); + } + + @Override + public boolean canAccept(DockableContent content, RelativePoint point) { + if (!(content instanceof DockableGrid)) { + return false; + } + final RunnerContentUi ui = ((DockableGrid)content).getOriginalRunnerUi(); + return ui.getProject() == myProject && ui.mySessionName.equals(mySessionName); + } + + @Override public JComponent getComponent() { initUi(); return myComponent; } + @Override + public JComponent getContainerComponent() { + initUi(); + return myManager.getComponent(); + } + + @Override + public void add(DockableContent dockable, RelativePoint dropTarget) { + saveUiState(); + + final DockableGrid dockableGrid = (DockableGrid)dockable; + final List contents = dockableGrid.getContents(); + final boolean wasRestoring = myOriginal != null && myOriginal.isStateBeingRestored(); + setStateIsBeingRestored(true, this); + try { + final Point point = dropTarget != null ? dropTarget.getPoint(myComponent) : null; + JComponent component = point != null ? (JComponent)SwingUtilities.getDeepestComponentAt(myComponent, point.x, point.y) : null; + boolean hadGrid = false; + while (component != null && !(component instanceof JBTabs)) { + if (component.getClientProperty(GridCellImpl.CELL_KEY) == Boolean.TRUE) { + hadGrid = true; + break; + } + component = (JComponent)component.getParent(); + } + + for (Content content : contents) { + dockableGrid.getRunnerUi().myManager.removeContent(content, false); + myManager.removeContent(content, false); + if (hadGrid && contents.size() == 1 && !wasRestoring) { + getStateFor(content).assignTab(getTabFor(getSelectedGrid())); + getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content)); + } else if (contents.size() == 1 && !wasRestoring) { + getStateFor(content).assignTab(myLayoutSettings.createNewTab()); + getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content)); + } + getStateFor(content).setWindow(myWindow); + myManager.addContent(content); + } + } finally { + setStateIsBeingRestored(false, this); + } + + saveUiState(); + + updateTabsUI(true); + } + + @Override + public void closeAll() { + final Content[] contents = myManager.getContents(); + for (Content content : contents) { + getStateFor(content).setWindow(0); + } + myManager.removeAllContents(false); + for (Content content : contents) { + myOriginal.myManager.addContent(content); + myOriginal.findCellFor(content).minimize(content); + } + } + + @Override + public void addListener(final Listener listener, Disposable parent) { + myDockingListeners.add(listener); + Disposer.register(parent, new Disposable() { + @Override + public void dispose() { + myDockingListeners.remove(listener); + } + }); + } + + @Override + public boolean isEmpty() { + return myTabs.isEmptyVisible(); + } + + @Override + public Image startDropOver(DockableContent content, RelativePoint point) { + return null; + } + + @Override + public Image processDropOver(DockableContent content, RelativePoint point) { + JBTabs current = getTabsAt(content, point); + + if (myCurrentOver != null && myCurrentOver != current) { + resetDropOver(content); + } + + if (myCurrentOver == null && current != null) { + myCurrentOver = current; + Presentation presentation = content.getPresentation(); + myCurrentOverInfo = new TabInfo(new JLabel("")).setText(presentation.getText()).setIcon(presentation.getIcon()); + myCurrentOverImg = myCurrentOver.startDropOver(myCurrentOverInfo, point); + } + + if (myCurrentOver != null) { + myCurrentOver.processDropOver(myCurrentOverInfo, point); + } + + return myCurrentOverImg; + } + + @Nullable + private JBTabs getTabsAt(DockableContent content, RelativePoint point) { + if (content instanceof DockableGrid) { + final Point p = point.getPoint(getComponent()); + Component c = SwingUtilities.getDeepestComponentAt(getComponent(), p.x, p.y); + while (c != null) { + if (c instanceof JBTabs) { + return (JBTabs)c; + } + c = c.getParent(); + } + } + return null; + } + + @Override + public void resetDropOver(DockableContent content) { + if (myCurrentOver != null) { + myCurrentOver.resetDropOver(myCurrentOverInfo); + myCurrentOver = null; + myCurrentOverInfo = null; + myCurrentOverImg = null; + } + } + + @Override + public boolean isDisposeWhenEmpty() { + return true; + } + public boolean isCycleRoot() { return false; } @@ -337,6 +550,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac event.getContent().addPropertyChangeListener(RunnerContentUi.this); + fireContentOpened(event.getContent()); } public void contentRemoved(final ContentManagerEvent event) { @@ -349,6 +563,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac removeGridIfNeeded(grid); } updateTabsUI(false); + fireContentClosed(event.getContent()); } public void contentRemoveQuery(final ContentManagerEvent event) { @@ -498,9 +713,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac for (TabInfo each : tabs) { hasToolbarContent |= updateTabUI(each); } - - myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1); - myTabs.updateTabActions(validateNow); if (validateNow) { @@ -508,7 +720,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } - private static boolean updateTabUI(TabInfo tab) { + private boolean updateTabUI(TabInfo tab) { TabImpl t = getTabFor(tab); if (t == null) { return false; @@ -534,9 +746,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } if (icon == null && contents.size() == 1) { + tab.setHidden(grid.isMinimized(contents.get(0))); icon = contents.get(0).getIcon(); } + tab.setDragOutDelegate(myTabs.getTabs().size() > 1 || !isOriginal() ? myDragOutDelegate : null); Tab gridTab = grid.getTab(); tab.setText(title).setIcon(gridTab != null && gridTab.isDefault() ? null : icon); @@ -573,6 +787,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac GridImpl eachGrid = getGridFor(each); eachGrid.saveUiState(); } + + for (RunnerContentUi child : myChildren) { + child.saveUiState(); + } } @Nullable @@ -581,6 +799,20 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return getTabFor(info); } + @Override + public void showNotify() { + final Window window = SwingUtilities.getWindowAncestor(myComponent); + if (window instanceof IdeFrame.Child) { + ((IdeFrame.Child)window).setFrameTitle(mySessionName); + //final Dimension size = DimensionService.getInstance().getSize("GridCell.Tab.0.center"); + //final Rectangle bounds = window.getBounds(); + //window.setBounds(bounds.x, bounds.y, size.width, size.height); + } + } + + @Override + public void hideNotify() {} + @Nullable private static TabImpl getTabFor(@Nullable final TabInfo tab) { if (tab == null) { @@ -640,6 +872,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac if (myComponent.getRootPane() != null) { saveUiState(); } + myManager.removeAllContents(true); } public boolean canChangeSelectionTo(Content content, boolean implicit) { @@ -674,14 +907,25 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } public void dispose() { - + if (myOriginal != null) { + myOriginal.myChildren.remove(this); + } } public void restoreLayout() { - Content[] all = myManager.getContents(); + final RunnerContentUi[] children = myChildren.toArray(new RunnerContentUi[myChildren.size()]); + final List contents = new ArrayList(); + Collections.addAll(contents, myManager.getContents()); + for (RunnerContentUi child : children) { + Collections.addAll(contents, child.myManager.getContents()); + } + Content[] all = contents.toArray(new Content[contents.size()]); setStateIsBeingRestored(true, this); try { + for (RunnerContentUi child : children) { + child.myManager.removeAllContents(false); + } myManager.removeAllContents(false); myMinimizedViewActions.removeAll(); } @@ -730,7 +974,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } public boolean isMinimizeActionEnabled() { - return myMinimizeActionEnabled; + return myMinimizeActionEnabled && myOriginal == null; } public boolean isMoveToGridActionEnabled() { @@ -820,12 +1064,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac public void addNotify() { super.addNotify(); - if (!myUiLastStateWasRestored) { + if (!myUiLastStateWasRestored && myOriginal == null) { myUiLastStateWasRestored = true; - //noinspection SSBasedInspection // [kirillk] this is done later since restoreUiState doesn't work properly in the addNotify call chain //todo to investigate and to fix (may cause extra flickering) + //noinspection SSBasedInspection SwingUtilities.invokeLater(new Runnable() { public void run() { restoreLastUiState().doWhenDone(new Runnable() { @@ -946,90 +1190,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac updateTabsUI(false); } - private static boolean willBeEmptyOnRemove(GridImpl grid, List toRemove) { - List attachedToGrid = grid.getAttachedContents(); - for (Content each : attachedToGrid) { - if (!toRemove.contains(each)) return false; - } - - return true; - } - - - public CellTransform.Restore detach(final Content[] content) { - List contents = Arrays.asList(content); - - for (Content each : content) { - GridImpl eachGrid = getGridFor(each, false); - if (willBeEmptyOnRemove(eachGrid, contents)) { - TabInfo info = myTabs.findInfo(eachGrid); - if (info != null) { - info.setHidden(true); - } - } - } - - updateTabsUI(true); - - return new CellTransform.Restore() { - public ActionCallback restoreInGrid() { - showHiddenTabs(); - updateTabsUI(true); - return new ActionCallback.Done(); - } - }; - } - - private void showHiddenTabs() { - List tabs = myTabs.getTabs(); - for (TabInfo eachInfos : tabs) { - GridImpl eachGrid = (GridImpl)eachInfos.getComponent(); - if (!eachGrid.getAttachedContents().isEmpty()) { - eachInfos.setHidden(false); - } - } - } - - public void moveToTab(final Content content) { - saveUiState(); - - setStateIsBeingRestored(true, this); - try { - myManager.removeContent(content, false); - getStateFor(content).assignTab(myLayoutSettings.createNewTab()); - getStateFor(content).setPlaceInGrid(PlaceInGrid.center); - myManager.addContent(content); - } - finally { - setStateIsBeingRestored(false, this); - } - - saveUiState(); - } - - public void moveToGrid(final Content content) { - saveUiState(); - - setStateIsBeingRestored(true, this); - - try { - myManager.removeContent(content, false); - getStateFor(content).assignTab(myLayoutSettings.getDefaultTab()); - getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content)); - myManager.addContent(content); - } - finally { - setStateIsBeingRestored(false, this); - } - - select(content, true).doWhenDone(new Runnable() { - public void run() { - saveUiState(); - } - }); - } - - public Project getProject() { return myProject; } @@ -1055,7 +1215,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } public boolean isHorizontalToolbar() { - return myLayoutSettings.isToolbarHorizontal(); + return false; } public ActionCallback select(final Content content, final boolean requestFocus) { @@ -1068,18 +1228,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac final ActionCallback result = new ActionCallback(); - if (grid.isDetached(content)) { - if (requestFocus) { + myTabs.select(info, false).doWhenDone(new Runnable() { + public void run() { grid.select(content, requestFocus).notifyWhenDone(result); } - } - else { - myTabs.select(info, false).doWhenDone(new Runnable() { - public void run() { - grid.select(content, requestFocus).notifyWhenDone(result); - } - }); - } + }); + return result; } @@ -1233,4 +1387,140 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return result; } + + + private int findFreeWindow() { + int i; + for (i = 1; i < Integer.MAX_VALUE; i++) { + if (!isUsed(i)) { + return i; + } + } + return i; + } + + private boolean isUsed(int i) { + for (RunnerContentUi child : myChildren) { + if (child.getWindow() == i) { + return true; + } + } + return false; + } + + private DockManagerImpl getDockManager() { + return (DockManagerImpl)DockManager.getInstance(myProject); + } + + class MyDragOutDelegate implements TabInfo.DragOutDelegate { + private DragSession mySession; + + @Override + public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) { + final JComponent component = info.getComponent(); + final Content[] data = CONTENT_KEY.getData((DataProvider)component); + final List contents = Arrays.asList(data); + + final Dimension size = info.getComponent().getSize(); + final Image image = myTabs.getComponentImage(info); + if (component instanceof Grid) { + info.setHidden(true); + } + + Presentation presentation = new Presentation(info.getText()); + presentation.setIcon(info.getIcon()); + mySession = getDockManager().createDragSession(mouseEvent, new DockableGrid(image, presentation, + size, + contents, 0)); + } + + @Override + public void processDragOut(MouseEvent event, TabInfo source) { + mySession.process(event); + } + + @Override + public void dragOutFinished(MouseEvent event, TabInfo source) { + final Component component = event.getComponent(); + final IdeFrame window = UIUtil.getParentOfType(IdeFrame.class, component); + if (window != null) { + + } + mySession.process(event); + mySession = null; + } + } + + class DockableGrid implements DockableContent> { + final Image myImg; + private Presentation myPresentation; + private final Dimension myPreferredSize; + private final List myContents; + private final int myWindow; + + public DockableGrid(Image img, Presentation presentation, final Dimension size, List contents, int window) { + myImg = img; + myPresentation = presentation; + myPreferredSize = size; + myContents = contents; + myWindow = window; + } + + @Override + public List getKey() { + return myContents; + } + + @Override + public Image getPreviewImage() { + return myImg; + } + + @Override + public Dimension getPreferredSize() { + return myPreferredSize; + } + + @Override + public String getDockContainerType() { + return DockableGridContainerFactory.TYPE; + } + + @Override + public Presentation getPresentation() { + return myPresentation; + } + + public RunnerContentUi getRunnerUi() { + return RunnerContentUi.this; + } + + public RunnerContentUi getOriginalRunnerUi() { + return myOriginal != null ? myOriginal : RunnerContentUi.this; + } + + public List getContents() { + return myContents; + } + + @Override + public void close() { + } + + public int getWindow() { + return myWindow; + } + } + + void fireContentOpened(Content content) { + for (Listener each : myDockingListeners) { + each.contentAdded(content); + } + } + + void fireContentClosed(Content content) { + for (Listener each : myDockingListeners) { + each.contentRemoved(content); + } + } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java index 13d0e593c255..84282337391b 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewContextEx.java @@ -16,14 +16,19 @@ package com.intellij.execution.ui.layout.impl; +import com.intellij.execution.ui.layout.GridCell; import com.intellij.execution.ui.layout.ViewContext; import com.intellij.openapi.actionSystem.ActionGroup; +import com.intellij.openapi.util.ActionCallback; public interface ViewContextEx extends ViewContext { RunnerLayout getLayoutSettings(); ActionGroup getCellPopupGroup(String place); - void doWhenInitialized(Runnable runnable); + boolean isOriginal(); + + int getWindow(); + ActionCallback detachTo(int window, GridCell cell); } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java index 89673d9d600d..83b8d0833827 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/ViewImpl.java @@ -31,16 +31,19 @@ public class ViewImpl implements View { private Tab myTab; private int myTabIndex; + + private int myWindow; private PlaceInGrid myPlaceInGrid; private boolean myMinimizedInGrid; - public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid) { + public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid, int window) { myID = id; myTab = tab; myPlaceInGrid = placeInGrid; myMinimizedInGrid = minimizedInGrid; + myWindow = window; } public ViewImpl(RunnerLayout settings, Element element) { @@ -94,6 +97,16 @@ public class ViewImpl implements View { myTabIndex = tabIndex; } + @Override + public int getWindow() { + return myWindow; + } + + @Override + public void setWindow(int windowNumber) { + myWindow = windowNumber; + } + public static class Default { private final String myID; @@ -110,7 +123,7 @@ public class ViewImpl implements View { public ViewImpl createView(RunnerLayout settings) { final TabImpl tab = myTabID == Integer.MAX_VALUE ? settings.createNewTab() : settings.getOrCreateTab(myTabID); - return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid); + return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid, 0); } public PlaceInGrid getPlaceInGrid() { diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 58da8434f90c..4f5ec9700bbf 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -728,8 +728,9 @@ - - + + From 395785e50664b4c4832d66497e62e249da455f6e Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 12:10:18 +0400 Subject: [PATCH 057/100] IDEA-80336 Run/Debug tool window: generic UI: old Horizontal Toolbars setting is used, but cannot be changed --- .../src/com/intellij/execution/ui/layout/impl/RunnerLayout.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java index 5cc040503267..dfd2b61dc8c2 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java @@ -172,7 +172,7 @@ public class RunnerLayout { } public boolean isToolbarHorizontal() { - return myGeneral.horizontalToolbar; + return false; } public void setToolbarHorizontal(boolean horizontal) { From 83ea24c607e8f4fbfa39d2409b4c32d825641744 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 12:45:45 +0400 Subject: [PATCH 058/100] IDEA-80345 Debug tool window: generic UI: mouse pointer over splitter between views drops the view to the tab row --- .../execution/ui/layout/impl/GridCellImpl.java | 3 --- .../execution/ui/layout/impl/JBRunnerTabs.java | 9 +++++++++ .../execution/ui/layout/impl/RunnerContentUi.java | 10 +--------- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index 0393f7ada11a..3834cef853ed 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -49,8 +49,6 @@ import java.util.List; import java.util.Set; public class GridCellImpl implements GridCell { - static final String CELL_KEY = "runner-grid-cell"; - private final GridImpl myContainer; private final MutualMap myContents = new MutualMap(true); @@ -260,7 +258,6 @@ public class GridCellImpl implements GridCell { myContent = content; myContext = context; setLayout(new BorderLayout()); - putClientProperty(CELL_KEY, Boolean.TRUE); add(content.getComponent(), BorderLayout.CENTER); } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index 33125c2ddf34..0f185c92639d 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -194,6 +194,15 @@ public class public int getToolbarInset() { return 8; } + + public boolean shouldAddToGlobal(Point point) { + final TabLabel label = getSelectedLabel(); + if (label == null || point == null) { + return true; + } + final Rectangle bounds = label.getBounds(); + return point.y <= bounds.y + bounds.height; + } @Override public Rectangle layout(JComponent c, Rectangle bounds) { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 72367679832f..32573192e192 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -402,15 +402,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac setStateIsBeingRestored(true, this); try { final Point point = dropTarget != null ? dropTarget.getPoint(myComponent) : null; - JComponent component = point != null ? (JComponent)SwingUtilities.getDeepestComponentAt(myComponent, point.x, point.y) : null; - boolean hadGrid = false; - while (component != null && !(component instanceof JBTabs)) { - if (component.getClientProperty(GridCellImpl.CELL_KEY) == Boolean.TRUE) { - hadGrid = true; - break; - } - component = (JComponent)component.getParent(); - } + boolean hadGrid = !myTabs.shouldAddToGlobal(point); for (Content content : contents) { dockableGrid.getRunnerUi().myManager.removeContent(content, false); From dd5fb3ae9ce70d68dfa55e43844678491b7c12a4 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 13:47:27 +0400 Subject: [PATCH 059/100] IDEA-80343 Run/Debug tool window: generic UI: dragging tab from tab row into another tab always makes Debug tab current --- .../execution/ui/layout/impl/JBRunnerTabs.java | 15 +++++++++++++++ .../src/com/intellij/ui/tabs/impl/JBTabsImpl.java | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java index 0f185c92639d..83feb8f097b1 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/JBRunnerTabs.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.Gray; +import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.UiDecorator; @@ -35,6 +36,7 @@ import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; import java.util.List; +import java.util.Map; /** * @author Dennis.Ushakov @@ -217,6 +219,19 @@ public class return super.layout(c, bounds); } + @Override + public void processDropOver(TabInfo over, RelativePoint relativePoint) { + super.processDropOver(over, relativePoint); + final Point point = relativePoint.getPoint(getComponent()); + for (Map.Entry entry : myInfo2Label.entrySet()) { + final TabLabel label = entry.getValue(); + if (label.getBounds().contains(point) && myDropInfo != entry.getKey()) { + select(entry.getKey(), false); + break; + } + } + } + @Override protected TabLabel createTabLabel(TabInfo info) { return new MyTabLabel(this, info); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index 7439c6729ed7..eab721b1b562 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -163,7 +163,7 @@ public class JBTabsImpl extends JComponent private boolean myOwnSwitchProvider = true; private SwitchProvider mySwitchDelegate; - private TabInfo myDropInfo; + protected TabInfo myDropInfo; private int myDropInfoIndex; private TabInfo myOldSelection; From 5c979da7adbb9a6abef1b7ae4e9825b6db613783 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 14:48:46 +0400 Subject: [PATCH 060/100] cleanup --- .../com/intellij/execution/ui/layout/impl/RunnerContentUi.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 32573192e192..7f87a1f89830 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -796,9 +796,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac final Window window = SwingUtilities.getWindowAncestor(myComponent); if (window instanceof IdeFrame.Child) { ((IdeFrame.Child)window).setFrameTitle(mySessionName); - //final Dimension size = DimensionService.getInstance().getSize("GridCell.Tab.0.center"); - //final Rectangle bounds = window.getBounds(); - //window.setBounds(bounds.x, bounds.y, size.width, size.height); } } From b6c4dce2027a6e77a9f114f9a072d2af05f6ade7 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 16:10:41 +0400 Subject: [PATCH 061/100] add drag finished notification --- .../src/com/intellij/ui/tabs/TabsListener.java | 6 ++++++ .../src/com/intellij/ui/tabs/impl/DragHelper.java | 3 +++ .../src/com/intellij/ui/tabs/impl/JBTabsImpl.java | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java index ff798575ac6a..a9bba15c4d37 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/TabsListener.java @@ -22,12 +22,18 @@ public interface TabsListener { void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection); + void tabsMoved(); + class Adapter implements TabsListener { public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) { } public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) { } + + @Override + public void tabsMoved() { + } } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java index 94c737a0ff74..70428d60ca50 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/DragHelper.java @@ -253,6 +253,9 @@ class DragHelper extends MouseDragHelper { myDragRec = null; myTabs.resetTabsCache(); + if (!willDragOutStart) { + myTabs.fireTabsMoved(); + } myTabs.relayout(true, false); myTabs.revalidate(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index eab721b1b562..6d49d1718d60 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -835,6 +835,14 @@ public class JBTabsImpl extends JComponent } } + void fireTabsMoved() { + for (TabsListener eachListener : myTabListeners) { + if (eachListener != null) { + eachListener.tabsMoved(); + } + } + } + private ActionCallback requestFocus(final JComponent toFocus) { if (toFocus == null) return new ActionCallback.Done(); From c11142bc037571eb8343f12b39915e8562ee31b2 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 16:41:25 +0400 Subject: [PATCH 062/100] IDEA-80340 Run/Debug tool window: generic UI: reorder tabs fails, if tab was dragged out of tab row --- .../ui/layout/impl/GridCellImpl.java | 2 +- .../ui/layout/impl/RunnerContentUi.java | 59 ++++++++++++++++++- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index 3834cef853ed..8c2491099805 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -100,7 +100,7 @@ public class GridCellImpl implements GridCell { } }); rebuildPopupGroup(); - myTabs.addListener(new TabsListener() { + myTabs.addListener(new TabsListener.Adapter() { public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) { if (oldSelection != null && myContext.isStateBeingRestored()) { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 7f87a1f89830..22fc32582665 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -125,9 +125,13 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac private TabInfo myCurrentOverInfo; private RunnerContentUi myOriginal; private CopyOnWriteArraySet myDockingListeners = new CopyOnWriteArraySet(); - private List myChildren = new ArrayList(); + private Set myChildren = new TreeSet(new Comparator() { + @Override + public int compare(RunnerContentUi o1, RunnerContentUi o2) { + return o1.myWindow - o2.myWindow; + } + }); private int myWindow; - private int ourWindowCounter; public RunnerContentUi(Project project, RunnerLayoutUi ui, @@ -214,6 +218,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } } + @Override + public void tabsMoved() { + saveUiState(); + } + public void selectionChanged(final TabInfo oldSelection, final TabInfo newSelection) { if (!myTabs.getComponent().isShowing()) return; @@ -594,6 +603,17 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac grid = new GridImpl(this, mySessionName); grid.setBorder(new EmptyBorder(1, 0, 0, 0)); + if (myCurrentOver != null) { + final int index = ((JBRunnerTabs)myCurrentOver).getDropInfoIndex() + (myOriginal != null ? myOriginal.getTabOffsetFor(this) : 0); + for (TabInfo info : myTabs.getTabs()) { + final TabImpl tab = getTabFor(info); + if (tab != null && tab.getIndex() >= index) { + tab.setIndex(tab.getIndex() + 1); + } + } + getStateFor(content).assignTab(myLayoutSettings.getOrCreateTab(index)); + } + TabInfo tab = new TabInfo(grid).setObject(getStateFor(content).getTab()).setText("Tab"); @@ -625,6 +645,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return grid; } + private int getTabOffsetFor(RunnerContentUi ui) { + int offset = myTabs.getTabCount(); + for (RunnerContentUi child : myChildren) { + if (child == ui) break; + offset += child.myTabs.getTabCount(); + } + return offset; + } + @Nullable public GridCell findCellFor(final Content content) { GridImpl cell = getGridFor(content, false); @@ -775,13 +804,37 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac public void saveUiState() { if (isStateBeingRestored()) return; + if (myOriginal != null) { + myOriginal.saveUiState(); + return; + } + int offset = updateTabsIndices(myTabs, 0); + for (RunnerContentUi child : myChildren) { + offset = updateTabsIndices(child.myTabs, offset); + } + + doSaveUiState(); + } + + private int updateTabsIndices(final JBRunnerTabs tabs, int offset) { + for (TabInfo each : tabs.getTabs()) { + final int index = myTabs.getIndexOf(each); + final TabImpl tab = getTabFor(each); + if (tab != null) tab.setIndex(index + offset); + } + return offset + tabs.getTabCount(); + } + + private void doSaveUiState() { + if (isStateBeingRestored()) return; + for (TabInfo each : myTabs.getTabs()) { GridImpl eachGrid = getGridFor(each); eachGrid.saveUiState(); } for (RunnerContentUi child : myChildren) { - child.saveUiState(); + child.doSaveUiState(); } } From 7914713e5a84cb1fcbec04d57dad74c28901e884 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 16:46:47 +0400 Subject: [PATCH 063/100] fix leaked focus requestor --- .../intellij/execution/ui/layout/impl/RunnerContentUi.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 22fc32582665..5c3099b0cbf9 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -914,7 +914,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac if (myComponent.getRootPane() != null) { saveUiState(); } - myManager.removeAllContents(true); + if (myOriginal != null) { + myManager.removeAllContents(true); + } } public boolean canChangeSelectionTo(Content content, boolean implicit) { From d3751958fd662c91d6359f9979edacae1c8470b8 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 18:35:51 +0400 Subject: [PATCH 064/100] close action for closeable content --- platform/platform-resources/src/idea/LangActions.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources/src/idea/LangActions.xml b/platform/platform-resources/src/idea/LangActions.xml index 4f5ec9700bbf..12a87ccd6ed0 100644 --- a/platform/platform-resources/src/idea/LangActions.xml +++ b/platform/platform-resources/src/idea/LangActions.xml @@ -750,6 +750,7 @@ + From 603ef5529d3ed049e43e6faef8908417769dab48 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 19:32:39 +0400 Subject: [PATCH 065/100] remove double adding of console --- .../src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java index 177f04560a45..6a0c734fb28b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebugSessionTab.java @@ -151,7 +151,6 @@ public class XDebugSessionTab extends DebuggerSessionTabBase { debugProcess.registerAdditionalContent(myUi); RunContentBuilder.addAdditionalConsoleEditorActions(myConsole, consoleContent); - myUi.addContent(consoleContent, 0, PlaceInGrid.bottom, false); if (ApplicationManager.getApplication().isUnitTestMode()) { return myRunContentDescriptor; From c28d5fc1335d914bbf0bd7fdce64c697a4d0e0b7 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 21:37:03 +0400 Subject: [PATCH 066/100] fixed persisting after tabs reordering --- .../com/intellij/execution/ui/layout/Tab.java | 1 + .../execution/ui/layout/impl/AbstractTab.java | 2 + .../ui/layout/impl/GridCellImpl.java | 7 +--- .../ui/layout/impl/RunnerContentUi.java | 41 ++++++++++++------- .../ui/layout/impl/RunnerLayout.java | 14 +++---- .../execution/ui/layout/impl/TabImpl.java | 9 ++++ 6 files changed, 47 insertions(+), 27 deletions(-) diff --git a/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java b/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java index c208e3c49b1f..686162a17391 100644 --- a/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java +++ b/platform/lang-api/src/com/intellij/execution/ui/layout/Tab.java @@ -22,6 +22,7 @@ public interface Tab { void setDetached(final PlaceInGrid placeInGrid, final boolean detached); int getIndex(); + int getDefaultIndex(); boolean isDetached(final PlaceInGrid placeInGrid); } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java index 282ce022dc1a..fb2f1293e2a9 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/AbstractTab.java @@ -21,6 +21,7 @@ import javax.swing.*; abstract class AbstractTab { int myIndex; + int myDefaultIndex = -1; String myDisplayName; Icon myIcon; @@ -38,6 +39,7 @@ abstract class AbstractTab { void copyFrom(final AbstractTab from) { myIndex = from.myIndex; + myDefaultIndex = from.myDefaultIndex; myDisplayName = from.myDisplayName; myIcon = from.myIcon; diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java index 8c2491099805..53df6f2e8ea8 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/GridCellImpl.java @@ -307,7 +307,7 @@ public class GridCellImpl implements GridCell { if (tab != null) { tab.setDetached(myPlaceInGrid, false); } - _detach(window).notifyWhenDone(result); + myContext.detachTo(window, this).notifyWhenDone(result); } else { result.setDone(); } @@ -392,11 +392,6 @@ public class GridCellImpl implements GridCell { } } - private ActionCallback _detach(final int window) { - myContext.saveUiState(); - return myContext.detachTo(window, this); - } - @Nullable public Point getLocation() { return DimensionService.getInstance().getLocation(getDimensionKey(), myContext.getProject()); diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java index 5c3099b0cbf9..5cd770aa4add 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerContentUi.java @@ -132,6 +132,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } }); private int myWindow; + private boolean myDisposing; public RunnerContentUi(Project project, RunnerLayoutUi ui, @@ -360,6 +361,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac } final GridCellImpl gridCell = (GridCellImpl)cell; final Content[] contents = gridCell.getContents(); + storeDefaultIndices(contents); + for (Content content : contents) { + content.putUserData(RunnerLayout.DROP_INDEX, getStateFor(content).getTab().getIndex()); + } Dimension size = gridCell.getSize(); if (size == null) { size = new Dimension(200, 200); @@ -375,6 +380,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac return new ActionCallback.Done(); } + private void storeDefaultIndices(Content[] contents) { + for (Content content : contents) { + content.putUserData(RunnerLayout.DEFAULT_INDEX, getStateFor(content).getTab().getDefaultIndex()); + } + } + @Override public RelativeRectangle getAcceptArea() { return new RelativeRectangle(myTabs.getComponent()); @@ -461,7 +472,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac @Override public boolean isEmpty() { - return myTabs.isEmptyVisible(); + return myTabs.isEmptyVisible() || myDisposing; } @Override @@ -518,7 +529,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac @Override public boolean isDisposeWhenEmpty() { - return true; + return myOriginal != null; } public boolean isCycleRoot() { @@ -603,15 +614,14 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac grid = new GridImpl(this, mySessionName); grid.setBorder(new EmptyBorder(1, 0, 0, 0)); - if (myCurrentOver != null) { - final int index = ((JBRunnerTabs)myCurrentOver).getDropInfoIndex() + (myOriginal != null ? myOriginal.getTabOffsetFor(this) : 0); - for (TabInfo info : myTabs.getTabs()) { - final TabImpl tab = getTabFor(info); - if (tab != null && tab.getIndex() >= index) { - tab.setIndex(tab.getIndex() + 1); - } - } - getStateFor(content).assignTab(myLayoutSettings.getOrCreateTab(index)); + if (myCurrentOver != null || myOriginal != null) { + Integer forcedDropIndex = content.getUserData(RunnerLayout.DROP_INDEX); + final int index = myTabs.getDropInfoIndex() + (myOriginal != null ? myOriginal.getTabOffsetFor(this) : 0); + final TabImpl tab = myLayoutSettings.getOrCreateTab(-1); + final Integer defaultIndex = content.getUserData(RunnerLayout.DEFAULT_INDEX); + tab.setDefaultIndex(defaultIndex != null ? defaultIndex : -1); + tab.setIndex(forcedDropIndex != null ? forcedDropIndex : index); + getStateFor(content).assignTab(tab); } TabInfo tab = new TabInfo(grid).setObject(getStateFor(content).getTab()).setText("Tab"); @@ -816,9 +826,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac doSaveUiState(); } - private int updateTabsIndices(final JBRunnerTabs tabs, int offset) { + private static int updateTabsIndices(final JBRunnerTabs tabs, int offset) { for (TabInfo each : tabs.getTabs()) { - final int index = myTabs.getIndexOf(each); + final int index = tabs.getIndexOf(each); final TabImpl tab = getTabFor(each); if (tab != null) tab.setIndex(index + offset); } @@ -915,7 +925,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac saveUiState(); } if (myOriginal != null) { - myManager.removeAllContents(true); + myDisposing = true; + fireContentClosed(null); } } @@ -1465,6 +1476,8 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac final Content[] data = CONTENT_KEY.getData((DataProvider)component); final List contents = Arrays.asList(data); + storeDefaultIndices(data); + final Dimension size = info.getComponent().getSize(); final Image image = myTabs.getComponentImage(info); if (component instanceof Grid) { diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java index dfd2b61dc8c2..b336d791e504 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/RunnerLayout.java @@ -20,6 +20,7 @@ import com.intellij.execution.ui.layout.LayoutAttractionPolicy; import com.intellij.execution.ui.layout.PlaceInGrid; import com.intellij.execution.ui.layout.Tab; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.content.Content; @@ -33,7 +34,8 @@ import javax.swing.*; import java.util.*; public class RunnerLayout { - + public static final Key DEFAULT_INDEX = Key.create("RunnerLayoutDefaultIndex"); + public static final Key DROP_INDEX = Key.create("RunnerLayoutDropIndex"); private final String myID; protected Map myViews = new HashMap(); @@ -64,10 +66,6 @@ public class RunnerLayout { return tab; } - public TabImpl getDefaultTab() { - return getOrCreateTab(0); - } - private TabImpl createNewTab(final int index) { final TabImpl tab; @@ -153,7 +151,9 @@ public class RunnerLayout { } for (TabImpl eachTab : myTabs) { - eachTab.write(parentNode); + if (isUsed(eachTab)) { + eachTab.write(parentNode); + } } parentNode.addContent(XmlSerializer.serialize(myGeneral)); @@ -166,7 +166,7 @@ public class RunnerLayout { myViews.clear(); for (TabImpl each : myTabs) { - final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getIndex()); + final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getDefaultIndex()); each.copyFrom(defaultTab); } } diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java index 268029f68165..673c7bbe9898 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/impl/TabImpl.java @@ -40,6 +40,10 @@ public class TabImpl extends AbstractTab implements Tab { return myIndex; } + public int getDefaultIndex() { + return myDefaultIndex >= 0 ? myDefaultIndex : myIndex; + } + public String getDisplayName() { return myDisplayName; } @@ -52,6 +56,10 @@ public class TabImpl extends AbstractTab implements Tab { myIndex = index; } + public void setDefaultIndex(final int index) { + myDefaultIndex = index; + } + public void setDisplayName(final String displayName) { myDisplayName = displayName; } @@ -161,6 +169,7 @@ public class TabImpl extends AbstractTab implements Tab { public Default(final int index, final String displayName, final Icon icon) { myIndex = index; + myDefaultIndex = index; myDisplayName = displayName; myIcon = icon; } From b4bbffbd3b88befe7ef5e8b172171d3110a3b791 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Thu, 26 Jan 2012 22:08:54 +0400 Subject: [PATCH 067/100] new-style close button --- .../execution/ui/layout/actions/CloseViewAction.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java index 98bfe91eecfe..cb18ab9d5840 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/layout/actions/CloseViewAction.java @@ -19,11 +19,19 @@ package com.intellij.execution.ui.layout.actions; import com.intellij.execution.ui.actions.BaseViewAction; import com.intellij.execution.ui.layout.ViewContext; import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.util.IconLoader; import com.intellij.ui.content.Content; +import javax.swing.*; + public class CloseViewAction extends BaseViewAction { + private static final Icon ICON = IconLoader.getIcon("/actions/closeNew.png"); + private static final Icon HOVERED_ICON = IconLoader.getIcon("/actions/closeNewHovered.png"); + protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) { setEnabled(e, isEnabled(context, content, e.getPlace())); + e.getPresentation().setIcon(ICON); + e.getPresentation().setHoveredIcon(HOVERED_ICON); } protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) { From 78d94de52b0835ce25195491d49d9dfe78c393dd Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 26 Jan 2012 22:04:43 +0300 Subject: [PATCH 068/100] Toggling, EOL markers, disabled descr support --- .../GenerateHighlightingMarkupAction.java | 92 +++++++++++++------ 1 file changed, 64 insertions(+), 28 deletions(-) diff --git a/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java b/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java index 540e7ef751ad..4fe6c3d9e9ab 100644 --- a/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java +++ b/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java @@ -35,6 +35,8 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.LinkedList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author gregsh @@ -53,60 +55,77 @@ public class GenerateHighlightingMarkupAction extends AnAction { PsiFile file = LangDataKeys.PSI_FILE.getData(e.getDataContext()); if (editor == null || file == null) return; final Project project = file.getProject(); - CommandProcessorEx commandProcessorEx = (CommandProcessorEx)CommandProcessorEx.getInstance(); - Object commandToken = commandProcessorEx - .startCommand(project, e.getPresentation().getText(), e.getPresentation().getText(), UndoConfirmationPolicy.DEFAULT); + CommandProcessorEx commandProcessor = (CommandProcessorEx)CommandProcessorEx.getInstance(); + Object commandToken = commandProcessor.startCommand(project, e.getPresentation().getText(), e.getPresentation().getText(), UndoConfirmationPolicy.DEFAULT); AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { - perform(project, editor.getDocument()); + perform(project, editor.getDocument(), true); } finally { token.finish(); - commandProcessorEx.finishCommand(project, commandToken, null); + commandProcessor.finishCommand(project, commandToken, null); } } - private static void perform(Project project, final Document document) { + private static void perform(Project project, final Document document, final boolean compact) { final CharSequence sequence = document.getCharsSequence(); final StringBuilder sb = new StringBuilder(); - final int[] offset = new int[] {0}; - final ArrayList infos = new ArrayList(); - DaemonCodeAnalyzerImpl.processHighlights( - document, project, HighlightSeverity.WARNING, 0, sequence.length(), - new Processor() { - @Override - public boolean process(HighlightInfo info) { - if (info.severity != HighlightSeverity.WARNING && info.severity != HighlightSeverity.ERROR) return true; - offset[0] = appendInfo(info, sb, sequence, offset[0], infos); - return true; - } - }); - offset[0] = appendInfo(null, sb, sequence, offset[0], infos); - sb.append(sequence.subSequence(offset[0], sequence.length())); + Pattern pattern = Pattern.compile("<(error|warning|EOLError|EOLWarning)(?:\\s|=|\\w+|\\\"(?:[^\"]|\\\\\\\")*?\\\")*>(.*?)"); + Matcher matcher = pattern.matcher(sequence); + if (matcher.find()) { + int pos = 0; + do { + sb.append(sequence, pos, matcher.start(0)); + sb.append(sequence, matcher.start(2), matcher.end(2)); + pos = matcher.end(0); + } + while (matcher.find(pos)); + sb.append(sequence, pos, sequence.length()); + } + else { + final int[] offset = new int[] {0}; + final ArrayList infos = new ArrayList(); + DaemonCodeAnalyzerImpl.processHighlights( + document, project, HighlightSeverity.WARNING, 0, sequence.length(), + new Processor() { + @Override + public boolean process(HighlightInfo info) { + if (info.severity != HighlightSeverity.WARNING && info.severity != HighlightSeverity.ERROR) return true; + offset[0] = appendInfo(info, sb, sequence, offset[0], infos, compact); + return true; + } + }); + offset[0] = appendInfo(null, sb, sequence, offset[0], infos, compact); + sb.append(sequence.subSequence(offset[0], sequence.length())); + } document.setText(sb); } - private static int appendInfo(@Nullable HighlightInfo info, StringBuilder sb, CharSequence sequence, int offset, ArrayList infos) { + private static int appendInfo(@Nullable HighlightInfo info, + StringBuilder sb, + CharSequence sequence, + int offset, + ArrayList infos, final boolean compact) { if (info == null || !infos.isEmpty() && infos.get(infos.size() - 1).getEndOffset() < info.getStartOffset()) { if (infos.size() == 1) { HighlightInfo cur = infos.remove(0); sb.append(sequence.subSequence(offset, cur.getStartOffset())); - sb.append(cur.severity == HighlightSeverity.WARNING ? "" : ""); + appendTag(sb, cur, true, compact); sb.append(sequence.subSequence(cur.getStartOffset(), cur.getEndOffset())); - sb.append(cur.severity == HighlightSeverity.WARNING ? "" : ""); + appendTag(sb, cur, false, compact); offset = cur.getEndOffset(); } else { // process overlapped LinkedList stack = new LinkedList(); for (HighlightInfo cur : infos) { - offset = processStack(stack, sb, sequence, offset, cur.getStartOffset()); + offset = processStack(stack, sb, sequence, offset, cur.getStartOffset(), compact); sb.append(sequence.subSequence(offset, cur.getStartOffset())); offset = cur.getStartOffset(); - sb.append(cur.severity == HighlightSeverity.WARNING ? "" : ""); + appendTag(sb, cur, true, compact); stack.addLast(cur); } - offset = processStack(stack, sb, sequence, offset, sequence.length()); + offset = processStack(stack, sb, sequence, offset, sequence.length(), compact); infos.clear(); } } @@ -127,7 +146,8 @@ public class GenerateHighlightingMarkupAction extends AnAction { StringBuilder sb, CharSequence sequence, int offset, - final int endOffset) { + final int endOffset, + final boolean compact) { if (stack.isEmpty()) return offset; for (HighlightInfo cur = stack.peekLast(); cur != null && cur.getEndOffset() <= endOffset; cur = stack.peekLast()) { stack.removeLast(); @@ -138,8 +158,24 @@ public class GenerateHighlightingMarkupAction extends AnAction { //System.out.println("Incorrect overlapping infos: " + offset + " > " + cur.getEndOffset()); } offset = cur.getEndOffset(); - sb.append(cur.severity == HighlightSeverity.WARNING ? "" : ""); + appendTag(sb, cur, false, compact); } return offset; } + + private static void appendTag(StringBuilder sb, HighlightInfo cur, boolean opening, final boolean compact) { + sb.append("<"); + if (!opening) sb.append("/"); + if (cur.isAfterEndOfLine) { + sb.append(cur.severity == HighlightSeverity.WARNING ? "EOLWarning" : "EOLError"); + } + else { + sb.append(cur.severity == HighlightSeverity.WARNING ? "warning" : "error"); + } + if (opening && !compact) { + sb.append(" descr=\"").append(cur.description).append("\""); + + } + sb.append(">"); + } } From 1926e5bd83766ae27f9ab1d49ef32d296b7bdffe Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 26 Jan 2012 22:15:36 +0400 Subject: [PATCH 069/100] EA-32918 (assert for negative file size) --- .../openapi/vfs/impl/local/LocalFileSystemBase.java | 4 +++- .../openapi/vfs/newvfs/persistent/PersistentFS.java | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java index f2ff048a9429..915ca59e82b8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemBase.java @@ -535,7 +535,9 @@ public abstract class LocalFileSystemBase extends LocalFileSystem { public byte[] contentsToByteArray(@NotNull final VirtualFile file) throws IOException { final FileInputStream stream = new FileInputStream(convertToIOFileAndCheck(file)); try { - return FileUtil.loadBytes(stream, (int)file.getLength()); + final int length = (int)file.getLength(); + assert length >= 0 : file; + return FileUtil.loadBytes(stream, length); } finally { stream.close(); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java index 9623d30cec49..9a2de59babeb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFS.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -508,7 +508,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent { } else { try { - return FileUtil.loadBytes(contentStream, (int)file.getLength()); + final int length = (int)file.getLength(); + assert length >= 0 : file; + return FileUtil.loadBytes(contentStream, length); } catch (IOException e) { throw FSRecords.handleError(e); From 13f7e623f933dcb097049e57a0c5974c9e3cf38d Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Thu, 26 Jan 2012 22:34:18 +0400 Subject: [PATCH 070/100] Implemented incrementalization log; fixed bug in bugfix with removed files (compiler server). --- .../ether/dependencyView/Mappings.java | 141 ++++++++++-------- 1 file changed, 76 insertions(+), 65 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index adfcf6f7708c..6b00c9aa80a6 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1,13 +1,12 @@ package org.jetbrains.ether.dependencyView; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import org.jetbrains.annotations.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.Opcodes; -import com.intellij.openapi.diagnostic.Logger; -import org.jetbrains.annotations.*; - import java.io.File; import java.io.IOException; import java.lang.annotation.ElementType; @@ -22,7 +21,7 @@ import java.util.*; * To change this template use File | Settings | File Templates. */ public class Mappings { - private final static Logger LOG = Logger.getInstance ("#org.jetbrains.ether.dependencyView.Mappings"); + private final static Logger LOG = Logger.getInstance("#org.jetbrains.ether.dependencyView.Mappings"); private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab"; private final static String CLASS_TO_CLASS = "classToClass.tab"; @@ -535,7 +534,7 @@ public class Mappings { final Collection dependants, final boolean usages) { debug("Affecting subclasses of class: ", className); - + final DependencyContext.S fileName = myClassToSourceFile.get(className); if (fileName == null) { @@ -588,6 +587,7 @@ public class Mappings { dependents.addAll(deps); } + debug("Affect field usage referenced of class ", p); affectedUsages .add(rootUsage instanceof UsageRepr.FieldAssignUsage ? field.createAssignUsage(myContext, p) : field.createUsage(myContext, p)); } @@ -607,6 +607,8 @@ public class Mappings { dependents.addAll(deps); } + debug("Affect method usage referenced of class ", p); + affectedUsages .add(rootUsage instanceof UsageRepr.MetaMethodUsage ? method.createMetaUsage(myContext, p) : method.createUsage(myContext, p)); } @@ -758,10 +760,10 @@ public class Mappings { } final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name)); - + debug("Softening non-incremental decision: adding all package classes for a recompilation"); debug("Package name: " + packageName); - + // Package-local branch for (Map.Entry e : myClassToSourceFile.entrySet()) { final DependencyContext.S className = e.getKey(); @@ -783,7 +785,7 @@ public class Mappings { final Collection compiledFiles, final Collection affectedFiles) { debug("Begin of Differentiate:"); - + delta.compensateRemovedContent(filesToCompile); final Util u = new Util(delta); @@ -833,13 +835,13 @@ public class Mappings { debug("Superclass changed: " + superClassChanged); debug("Interfaces changed: " + interfacesChanged); debug("Signature changed " + signatureChanged); - + final boolean extendsChanged = superClassChanged && !diff.extendsAdded(); final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty(); debug("Extends changed: " + extendsChanged); - debug("Interfaces removed: " + interfacesRemoved); - + debug("Interfaces removed: " + interfacesRemoved); + u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged); } @@ -851,7 +853,7 @@ public class Mappings { if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) { debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested"); if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { - debug("End of Differentiate, returning false"); + debug("End of Differentiate, returning false"); return false; } } @@ -884,7 +886,7 @@ public class Mappings { if (it.isAnnotation()) { debug("Class is annotation, performing annotation-specific analysis"); - + if (diff.retentionChanged()) { debug("Retention policy change detected, adding class usage to affected usages"); affectedUsages.add(it.createUsage()); @@ -895,7 +897,7 @@ public class Mappings { if (removedtargets.contains(ElementType.LOCAL_VARIABLE)) { debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested"); if (!incrementalDecision(it.outerClassName, it, affectedFiles)) { - debug("End of Differentiate, returning false"); + debug("End of Differentiate, returning false"); return false; } } @@ -914,14 +916,14 @@ public class Mappings { } } } - + debug("End of annotation-specific analysis"); } debug("Processing added methods: "); for (MethodRepr m : diff.methods().added()) { debug("Method: ", m.name); - + if (it.isAnnotation()) { debug("Class is annotation, skipping method analysis"); continue; @@ -977,10 +979,10 @@ public class Mappings { else { debug("Method: ", mm.name); debug("Class : ", cc.name); - + if (overrides.satisfy(mm)) { debug("Current method overrides that found"); - + final Option subtypeOf = u.isSubtypeOf(mm.type, m.type); if (weakerAccess(mm.access, m.access) || @@ -993,7 +995,7 @@ public class Mappings { final DependencyContext.S file = myClassToSourceFile.get(cc.name); if (file != null) { - final String f = myContext.getValue(file); + final String f = myContext.getValue(file); debug("Complex condition is satisfied, affecting file " + f); affectedFiles.add(new File(f)); } @@ -1001,7 +1003,7 @@ public class Mappings { } else { debug("Current method does not override that found"); - + final Collection yetPropagated = self.propagateMethodAccess(mm.name, cc.name); final Collection deps = myClassToClassDependency.get(cc.name); @@ -1025,7 +1027,7 @@ public class Mappings { if (r != null && sourceFileName != null) { final DependencyContext.S outerClass = r.outerClassName; - if (u.methodVisible(outerClass, m)) { + if (u.methodVisible(outerClass, m)) { final String f = myContext.getValue(sourceFileName); debug("Affecting file " + f + " due to local overriding"); affectedFiles.add(new File(f)); @@ -1036,11 +1038,11 @@ public class Mappings { } } debug("End of added methods processing"); - - debug("Processing removed methods:"); + + debug("Processing removed methods:"); for (MethodRepr m : diff.methods().removed()) { debug("Method ", m.name); - + final Collection> overridenMethods = u.findOverridenMethods(m, it); final Collection propagated = u.propagateMethodAccess(m.name, it.name); @@ -1104,7 +1106,9 @@ public class Mappings { if (source != null) { final String f = myContext.getValue(source); - debug("Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ", p); + debug( + "Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ", + p); debug("Affecting subclass source file " + f); affectedFiles.add(new File(f)); } @@ -1113,8 +1117,8 @@ public class Mappings { } } } - debug("End of removed methods processing"); - + debug("End of removed methods processing"); + debug("Processing changed methods:"); for (Pair mr : diff.methods().changed()) { final MethodRepr m = mr.first; @@ -1122,7 +1126,7 @@ public class Mappings { final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0); debug("Method: ", m.name); - + if (it.isAnnotation()) { if (d.defaultRemoved()) { debug("Class is annotation, default value is removed => adding annotation query"); @@ -1200,8 +1204,8 @@ public class Mappings { } } } - debug("End of changed methods processing"); - + debug("End of changed methods processing"); + final int mask = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL; debug("Processing added fields"); @@ -1216,34 +1220,38 @@ public class Mappings { if (!fPrivate) { final Collection subClasses = getAllSubclasses(it.name); - if (subClasses != null) { - for (final DependencyContext.S subClass : subClasses) { - final ClassRepr r = u.reprByName(subClass); - final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass); + // if (subClasses != null) { + for (final DependencyContext.S subClass : subClasses) { + final ClassRepr r = u.reprByName(subClass); + final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass); - if (r != null && sourceFileName != null) { - if (r.isLocal) { + if (r != null && sourceFileName != null) { + if (r.isLocal) { + debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ", + sourceFileName); + affectedFiles.add(new File(myContext.getValue(sourceFileName))); + } + else { + final DependencyContext.S outerClass = r.outerClassName; + + if (!empty(outerClass) && u.fieldVisible(outerClass, f)) { + debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName); affectedFiles.add(new File(myContext.getValue(sourceFileName))); } - else { - final DependencyContext.S outerClass = r.outerClassName; - - if (!empty(outerClass) && u.fieldVisible(outerClass, f)) { - affectedFiles.add(new File(myContext.getValue(sourceFileName))); - } - } - } - - final Collection propagated = u.propagateFieldAccess(f.name, subClass); - u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants); - - final Collection deps = myClassToClassDependency.get(subClass); - - if (deps != null) { - dependants.addAll(deps); } } + + debug("Affecting field usages referenced from subclass ", subClass); + final Collection propagated = u.propagateFieldAccess(f.name, subClass); + u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants); + + final Collection deps = myClassToClassDependency.get(subClass); + + if (deps != null) { + dependants.addAll(deps); + } } + // } } final Collection> overridden = u.findOverridenFields(f, it); @@ -1261,6 +1269,7 @@ public class Mappings { final Collection propagated = o.propagateFieldAccess(ff.name, cc.name); final Set localUsages = new HashSet(); + debug("Affecting usages of overridden field in class ", cc.name); u.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, dependants); if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) { @@ -1290,7 +1299,7 @@ public class Mappings { } } debug("End of added fields processing"); - + debug("Processing removed fields:"); for (FieldRepr f : diff.fields().removed()) { debug("Field: ", it.name); @@ -1298,7 +1307,7 @@ public class Mappings { if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) { debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested"); if (!incrementalDecision(it.name, f, affectedFiles)) { - debug("End of Differentiate, returning false"); + debug("End of Differentiate, returning false"); return false; } } @@ -1318,8 +1327,8 @@ public class Mappings { if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) { if ((d.base() & Difference.ACCESS) > 0 || (d.base() & Difference.VALUE) > 0) { debug("Inline field changed it's access or value => a switch to non-incremental mode requested"); - if (!incrementalDecision(it.name, field, affectedFiles)){ - debug("End of Differentiate, returning false"); + if (!incrementalDecision(it.name, field, affectedFiles)) { + debug("End of Differentiate, returning false"); return false; } } @@ -1371,10 +1380,10 @@ public class Mappings { } } } - debug("End of changed fields processing"); + debug("End of changed fields processing"); } debug("End of changed classes processing"); - + debug("Processing removed classes:"); for (ClassRepr c : classDiff.removed()) { debug("Adding usages of class ", c.name); @@ -1392,7 +1401,7 @@ public class Mappings { if (fName != null) { final String f = myContext.getValue(fName); - debug("Adding dependent file " + f); + debug("Adding dependent file " + f); affectedFiles.add(new File(f)); } } @@ -1475,14 +1484,16 @@ public class Mappings { } final Collection removedFiles = new HashSet(); - - for (String r : removed) { - removedFiles.add(new File(r)); + + if (removed != null) { + for (String r : removed) { + removedFiles.add(new File(r)); + } + + affectedFiles.removeAll(removedFiles); } - affectedFiles.removeAll(removedFiles); - - debug("End of Differentiate, returning true"); + debug("End of Differentiate, returning true"); return true; } From 50ae85ce3643e3b6615a868467fce73141b4d421 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 26 Jan 2012 19:41:03 +0100 Subject: [PATCH 071/100] IDEA-80385 Quickdoc doesn't support 'Back'/'Forward' keyboard buttons --- .../documentation/DocumentationComponent.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index f4f219c30e12..dbe5d13a980b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -268,10 +268,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr myScrollPane.setViewportBorder(JBScrollPane.createIndentBorder()); final DefaultActionGroup actions = new DefaultActionGroup(); - actions.add(new BackAction()); - actions.add(new ForwardAction()); + final BackAction back = new BackAction(); + final ForwardAction forward = new ForwardAction(); + actions.add(back); + actions.add(forward); actions.add(myExternalDocAction = new ExternalDocAction()); - + back.registerCustomShortcutSet(CustomShortcutSet.fromString("LEFT"), this); + forward.registerCustomShortcutSet(CustomShortcutSet.fromString("RIGHT"), this); + myExternalDocAction.registerCustomShortcutSet(CustomShortcutSet.fromString("UP"), this); if (additionalActions != null) { for (final AnAction action : additionalActions) { actions.add(action); From f9f2c467fde9eb25d4281457cc6f234137fffcc4 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 26 Jan 2012 23:02:18 +0400 Subject: [PATCH 072/100] IDEA-79765 (Grails View: please make it look consistent with Project View (merge toolbars)) --- .../mvc/projectView/MvcProjectViewPane.java | 50 +++++++++++-------- .../projectView/MvcToolWindowDescriptor.java | 24 ++------- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java index b8e88faf0ca2..67eb6591b9b0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcProjectViewPane.java @@ -21,9 +21,11 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.*; +import com.intellij.openapi.wm.ex.ToolWindowEx; import com.intellij.psi.*; import com.intellij.ui.AutoScrollFromSourceHandler; import com.intellij.ui.AutoScrollToSourceHandler; +import com.intellij.ui.content.ContentManager; import com.intellij.util.Alarm; import com.intellij.util.IJSwingUtilities; import com.intellij.util.containers.ContainerUtil; @@ -67,7 +69,7 @@ import java.util.List; */ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements IdeView { private final CopyPasteDelegator myCopyPasteDelegator; - private final JPanel myComponent; + private final JComponent myComponent; private final DeleteProvider myDeletePSIElementProvider; private final ModuleDeleteProvider myDeleteModuleProvider = new ModuleDeleteProvider(); @@ -120,9 +122,7 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id project.getMessageBus().connect(this).subscribe(PsiModificationTracker.TOPIC, new TreeUpdater()); - myComponent = new JPanel(new BorderLayout()); - myComponent.add(createComponent(), BorderLayout.CENTER); - myComponent.add(createToolbar(), BorderLayout.NORTH); + myComponent = createComponent(); DataManager.registerDataProvider(myComponent, this); myCopyPasteDelegator = new CopyPasteDelegator(project, myComponent) { @@ -135,18 +135,33 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id myDeletePSIElementProvider = new DeleteHandler.DefaultDeleteProvider(); } - private JComponent createToolbar() { + public void setup(ToolWindowEx toolWindow) { + JPanel p = new JPanel(new BorderLayout()); + p.add(myComponent, BorderLayout.CENTER); + + ContentManager contentManager = toolWindow.getContentManager(); + Content content = contentManager.getFactory().createContent(p, null, false); + content.setDisposer(this); + content.setCloseable(false); + + content.setPreferredFocusableComponent(createComponent()); + contentManager.addContent(content); + + contentManager.setSelectedContent(content, true); + DefaultActionGroup group = new DefaultActionGroup(); + group.add(new HideEmptyMiddlePackagesAction()); + group.add(myAutoScrollToSourceHandler.createToggleAction()); + group.add(myAutoScrollFromSourceHandler.createToggleAction()); - final TreeExpander expander = new DefaultTreeExpander(myTree); - final CommonActionsManager actionsManager = CommonActionsManager.getInstance(); - group.addAction(new ScrollFromSourceAction()); - group.addAction(myAutoScrollFromSourceHandler.createToggleAction()).setAsSecondary(true); - group.addAction(myAutoScrollToSourceHandler.createToggleAction()).setAsSecondary(true); - group.add(actionsManager.createCollapseAllAction(expander, myTree)); - group.addAction(new HideEmptyMiddlePackagesAction()).setAsSecondary(true); + toolWindow.setAdditionalGearActions(group); - return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); + TreeExpander expander = new DefaultTreeExpander(myTree); + CommonActionsManager actionsManager = CommonActionsManager.getInstance(); + AnAction collapseAction = actionsManager.createCollapseAllAction(expander, myTree); + collapseAction.getTemplatePresentation().setIcon(IconLoader.getIcon("/general/collapseAll.png")); + + toolWindow.setTitleActions(new AnAction[]{new ScrollFromSourceAction(), collapseAction}); } @Override @@ -158,10 +173,6 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id return component; } - public JPanel getComponent() { - return myComponent; - } - public String getTitle() { throw new UnsupportedOperationException(); } @@ -436,10 +447,9 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id scrollFromSource(); } - private class ScrollFromSourceAction extends AnAction implements DumbAware { private ScrollFromSourceAction() { - super("Scroll from Source", "Select the file open in the active editor", IconLoader.getIcon("/general/autoscrollFromSource.png")); + super("Scroll from Source", "Select the file open in the active editor", IconLoader.getIcon("/general/locate.png")); } @Override @@ -475,7 +485,7 @@ public class MvcProjectViewPane extends AbstractProjectViewPSIPane implements Id myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { public void run() { - if (myProject.isDisposed() || !getComponent().isShowing()) return; + if (myProject.isDisposed() || !myComponent.isShowing()) return; if (myAutoScrollFromSource) { selectElementAtCaretNotLosingFocus(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java index 265df37d0a87..9f9e4d8bbd52 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/projectView/MvcToolWindowDescriptor.java @@ -25,17 +25,15 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentManager; +import com.intellij.openapi.wm.ex.ToolWindowEx; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.mvc.MvcFramework; import org.jetbrains.plugins.groovy.mvc.MvcModuleStructureUtil; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.awt.*; import java.util.List; /** @@ -58,20 +56,8 @@ public abstract class MvcToolWindowDescriptor implements ToolWindowFactory, Cond toolWindow.setToHideOnEmptyContent(true); toolWindow.setTitle(myFramework.getDisplayName()); - final MvcProjectViewPane view = new MvcProjectViewPane(project, this); - - final JPanel p = new JPanel(new BorderLayout()); - p.add(view.getComponent(), BorderLayout.CENTER); - - final ContentManager contentManager = toolWindow.getContentManager(); - final Content content = contentManager.getFactory().createContent(p, null, false); - content.setDisposer(view); - content.setCloseable(false); - - content.setPreferredFocusableComponent(view.createComponent()); - contentManager.addContent(content); - - contentManager.setSelectedContent(content, true); + MvcProjectViewPane view = new MvcProjectViewPane(project, this); + view.setup((ToolWindowEx)toolWindow); } public boolean value(Project project) { From 00001b8f837d9e9c03060ae21e23e4873c61712c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 26 Jan 2012 20:05:59 +0100 Subject: [PATCH 073/100] fix test data --- .../constant_string_buffer_may_be_string/expected.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml index 7ecadfbba1b4..79e526123f19 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/constant_string_buffer_may_be_string/expected.xml @@ -4,13 +4,13 @@ StringBufferReplaceableByString.java 6 Constant StringBuffer may be String - Constant StringBuffer <code>builder</code> may be declared as String #loc + Constant <code>StringBuilder builder</code> may be declared as 'String' #loc StringBufferReplaceableByString.java 7 Constant StringBuffer may be String - Constant StringBuffer <code>buffer</code> may be declared as String #loc + Constant <code>StringBuffer buffer</code> may be declared as 'String' #loc \ No newline at end of file From 656b090096076de60fca6c5fd80df83a0f2202ed Mon Sep 17 00:00:00 2001 From: Sergio Aguayo Date: Thu, 26 Jan 2012 20:11:09 +0100 Subject: [PATCH 074/100] couple more macros in file templates (IDEA-80344) --- .../fileTemplates/impl/FileTemplateManagerImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java index 323560f5efff..e39d357b7d34 100644 --- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java @@ -48,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.net.URL; import java.text.MessageFormat; +import java.text.SimpleDateFormat; import java.util.*; /** @@ -319,10 +320,17 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo @NonNls Properties props = new Properties(); Calendar calendar = Calendar.getInstance(); + Date date = new Date(calendar.getTimeInMillis()); + SimpleDateFormat sdfMonthNameShort = new SimpleDateFormat("MMM"); + SimpleDateFormat sdfMonthNameFull = new SimpleDateFormat("MMMM"); + SimpleDateFormat sdfYearFull = new SimpleDateFormat("yyyy"); + props.setProperty("DATE", DateFormatUtil.formatDate(calendar.getTime())); props.setProperty("TIME", DateFormatUtil.formatTime(calendar.getTime())); - props.setProperty("YEAR", Integer.toString(calendar.get(Calendar.YEAR))); + props.setProperty("YEAR", sdfYearFull.format(date)); props.setProperty("MONTH", getCalendarValue(calendar, Calendar.MONTH)); + props.setProperty("MONTH_NAME_SHORT", sdfMonthNameShort.format(date)); + props.setProperty("MONTH_NAME_FULL", sdfMonthNameFull.format(date)); props.setProperty("DAY", getCalendarValue(calendar, Calendar.DAY_OF_MONTH)); props.setProperty("HOUR", getCalendarValue(calendar, Calendar.HOUR_OF_DAY)); props.setProperty("MINUTE", getCalendarValue(calendar, Calendar.MINUTE)); From ad14022a28495e428935cc4aa2410f7274d522a8 Mon Sep 17 00:00:00 2001 From: Dmitry Boulytchev Date: Thu, 26 Jan 2012 23:30:32 +0400 Subject: [PATCH 075/100] Improved incrementalization log (compiler server). --- .../dependencyView/DependencyContext.java | 14 ++++++ .../ether/dependencyView/Logger.java | 2 + .../ether/dependencyView/Mappings.java | 47 ++++++++++--------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java index d8af32122f35..75756ad6f05e 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/DependencyContext.java @@ -177,6 +177,20 @@ class DependencyContext { log.debug(comment + getValue(s)); } } + + @Override + public void debug(String comment, String t) { + if (log.isDebugEnabled()){ + log.debug(comment + t); + } + } + + @Override + public void debug(String comment, boolean t) { + if (log.isDebugEnabled()) { + log.debug(comment + Boolean.toString(t)); + } + } }; } } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java index dbd95bb3a256..a409a4c9ec6f 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Logger.java @@ -24,4 +24,6 @@ package org.jetbrains.ether.dependencyView; */ public interface Logger { void debug(String comment, T t); + void debug(String comment, String t); + void debug(String comment, boolean t); } diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 6b00c9aa80a6..16846ac8e8f2 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -37,7 +37,7 @@ public class Mappings { private DependencyContext myContext; private org.jetbrains.ether.dependencyView.Logger myDebugS; - private void debug(final String s) { + private static void debug(final String s) { LOG.debug(s); } @@ -45,6 +45,14 @@ public class Mappings { myDebugS.debug(comment, s); } + private void debug(final String comment, final String s) { + myDebugS.debug(comment, s); + } + + private void debug(final String comment, final boolean s) { + myDebugS.debug(comment, s); + } + private MultiMaplet myClassToSubclasses; private MultiMaplet myClassToClassDependency; @@ -754,7 +762,7 @@ public class Mappings { for (DependencyContext.S className : propagated) { final String fileName = myContext.getValue(myClassToSourceFile.get(className)); - debug("Adding " + fileName); + debug("Adding ", fileName); affectedFiles.add(new File(fileName)); } } @@ -762,7 +770,7 @@ public class Mappings { final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name)); debug("Softening non-incremental decision: adding all package classes for a recompilation"); - debug("Package name: " + packageName); + debug("Package name: ", packageName); // Package-local branch for (Map.Entry e : myClassToSourceFile.entrySet()) { @@ -771,7 +779,7 @@ public class Mappings { if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) { final String f = myContext.getValue(fileName); - debug("Adding: " + f); + debug("Adding: ", f); affectedFiles.add(new File(f)); } } @@ -832,15 +840,15 @@ public class Mappings { final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0; if (superClassChanged || interfacesChanged || signatureChanged) { - debug("Superclass changed: " + superClassChanged); - debug("Interfaces changed: " + interfacesChanged); - debug("Signature changed " + signatureChanged); + debug("Superclass changed: ", superClassChanged); + debug("Interfaces changed: ", interfacesChanged); + debug("Signature changed ", signatureChanged); final boolean extendsChanged = superClassChanged && !diff.extendsAdded(); final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty(); - debug("Extends changed: " + extendsChanged); - debug("Interfaces removed: " + interfacesRemoved); + debug("Extends changed: ", extendsChanged); + debug("Interfaces removed: ", interfacesRemoved); u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged); } @@ -910,7 +918,7 @@ public class Mappings { for (MethodRepr m : diff.methods().added()) { if (!m.hasValue()) { - debug("Added method with no default value: " + m.name); + debug("Added method with no default value: ", m.name); debug("Adding class usage to affected usages"); affectedUsages.add(it.createUsage()); } @@ -996,7 +1004,7 @@ public class Mappings { if (file != null) { final String f = myContext.getValue(file); - debug("Complex condition is satisfied, affecting file " + f); + debug("Complex condition is satisfied, affecting file ", f); affectedFiles.add(new File(f)); } } @@ -1029,7 +1037,7 @@ public class Mappings { if (u.methodVisible(outerClass, m)) { final String f = myContext.getValue(sourceFileName); - debug("Affecting file " + f + " due to local overriding"); + debug("Affecting file due to local overriding: ", f); affectedFiles.add(new File(f)); } } @@ -1109,7 +1117,7 @@ public class Mappings { debug( "Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ", p); - debug("Affecting subclass source file " + f); + debug("Affecting subclass source file ", f); affectedFiles.add(new File(f)); } } @@ -1220,7 +1228,6 @@ public class Mappings { if (!fPrivate) { final Collection subClasses = getAllSubclasses(it.name); - // if (subClasses != null) { for (final DependencyContext.S subClass : subClasses) { final ClassRepr r = u.reprByName(subClass); final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass); @@ -1251,7 +1258,6 @@ public class Mappings { dependants.addAll(deps); } } - // } } final Collection> overridden = u.findOverridenFields(f, it); @@ -1401,7 +1407,7 @@ public class Mappings { if (fName != null) { final String f = myContext.getValue(fName); - debug("Adding dependent file " + f); + debug("Adding dependent file ", f); affectedFiles.add(new File(f)); } } @@ -1429,7 +1435,7 @@ public class Mappings { continue filewise; } - debug("Dependent file: " + theFile.getAbsolutePath()); + debug("Dependent file: ", depFile); final Collection depClusters = mySourceFileToUsages.get(depFile); @@ -1483,14 +1489,10 @@ public class Mappings { } } - final Collection removedFiles = new HashSet(); - if (removed != null) { for (String r : removed) { - removedFiles.add(new File(r)); + affectedFiles.remove(new File(r)); } - - affectedFiles.removeAll(removedFiles); } debug("End of Differentiate, returning true"); @@ -1538,7 +1540,6 @@ public class Mappings { } } - myClassToSubclasses.putAll(delta.myClassToSubclasses); mySourceFileToClasses.putAll(delta.mySourceFileToClasses); mySourceFileToUsages.putAll(delta.mySourceFileToUsages); From e2979514f8fe3a6e503195f496bb19ee72b87eba Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 26 Jan 2012 23:30:28 +0300 Subject: [PATCH 076/100] toggle descriptions --- plugins/devkit/resources/META-INF/plugin.xml | 4 +-- ...va => ToggleHighlightingMarkupAction.java} | 27 +++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) rename plugins/devkit/src/actions/{GenerateHighlightingMarkupAction.java => ToggleHighlightingMarkupAction.java} (90%) diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index 330e83d18fec..7a2ea5d49803 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -115,8 +115,8 @@ - + diff --git a/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java b/plugins/devkit/src/actions/ToggleHighlightingMarkupAction.java similarity index 90% rename from plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java rename to plugins/devkit/src/actions/ToggleHighlightingMarkupAction.java index 4fe6c3d9e9ab..02d4be0d1ccd 100644 --- a/plugins/devkit/src/actions/GenerateHighlightingMarkupAction.java +++ b/plugins/devkit/src/actions/ToggleHighlightingMarkupAction.java @@ -41,7 +41,7 @@ import java.util.regex.Pattern; /** * @author gregsh */ -public class GenerateHighlightingMarkupAction extends AnAction { +public class ToggleHighlightingMarkupAction extends AnAction { @Override public void update(AnActionEvent e) { Editor editor = PlatformDataKeys.EDITOR.getData(e.getDataContext()); @@ -59,7 +59,7 @@ public class GenerateHighlightingMarkupAction extends AnAction { Object commandToken = commandProcessor.startCommand(project, e.getPresentation().getText(), e.getPresentation().getText(), UndoConfirmationPolicy.DEFAULT); AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); try { - perform(project, editor.getDocument(), true); + perform(project, editor.getDocument()); } finally { token.finish(); @@ -67,16 +67,27 @@ public class GenerateHighlightingMarkupAction extends AnAction { } } - private static void perform(Project project, final Document document, final boolean compact) { + private static void perform(Project project, final Document document) { final CharSequence sequence = document.getCharsSequence(); final StringBuilder sb = new StringBuilder(); - Pattern pattern = Pattern.compile("<(error|warning|EOLError|EOLWarning)(?:\\s|=|\\w+|\\\"(?:[^\"]|\\\\\\\")*?\\\")*>(.*?)"); + Pattern pattern = Pattern.compile("<(error|warning|EOLError|EOLWarning)((?:\\s|=|\\w+|\\\"(?:[^\"]|\\\\\\\")*?\\\")*?)>(.*?)"); Matcher matcher = pattern.matcher(sequence); if (matcher.find()) { + boolean compactMode = false; int pos = 0; do { - sb.append(sequence, pos, matcher.start(0)); - sb.append(sequence, matcher.start(2), matcher.end(2)); + if (matcher.start(2) < matcher.end(2)) { + if (!compactMode) { + sb.setLength(pos = 0); + compactMode = true; + } + sb.append(sequence, pos, matcher.start(2)); + sb.append(sequence, matcher.end(2), matcher.end(0)); + } + else if (!compactMode) { + sb.append(sequence, pos, matcher.start(0)); + sb.append(sequence, matcher.start(3), matcher.end(3)); + } pos = matcher.end(0); } while (matcher.find(pos)); @@ -91,11 +102,11 @@ public class GenerateHighlightingMarkupAction extends AnAction { @Override public boolean process(HighlightInfo info) { if (info.severity != HighlightSeverity.WARNING && info.severity != HighlightSeverity.ERROR) return true; - offset[0] = appendInfo(info, sb, sequence, offset[0], infos, compact); + offset[0] = appendInfo(info, sb, sequence, offset[0], infos, false); return true; } }); - offset[0] = appendInfo(null, sb, sequence, offset[0], infos, compact); + offset[0] = appendInfo(null, sb, sequence, offset[0], infos, false); sb.append(sequence.subSequence(offset[0], sequence.length())); } document.setText(sb); From 1e30481c82d8517167910a3ef1a8b40c66314b3e Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 26 Jan 2012 22:17:16 +0100 Subject: [PATCH 077/100] updated netty to v3.3 --- lib/netty-3.2.5.Final.jar | Bin 792314 -> 0 bytes lib/netty-3.3.0.Final.jar | Bin 0 -> 872371 bytes lib/required_for_dist.txt | 2 +- lib/src/netty-3.2.5.Final-sources.jar | Bin 775148 -> 0 bytes lib/src/netty-3.3.0.Final-sources.jar | Bin 0 -> 820181 bytes 5 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 lib/netty-3.2.5.Final.jar create mode 100644 lib/netty-3.3.0.Final.jar delete mode 100644 lib/src/netty-3.2.5.Final-sources.jar create mode 100644 lib/src/netty-3.3.0.Final-sources.jar diff --git a/lib/netty-3.2.5.Final.jar b/lib/netty-3.2.5.Final.jar deleted file mode 100644 index f3b79fcbaa750dcfc8e12c8d7dad2e1723e8c00d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792314 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

BJt}-S4z0km;BE{w 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 ^gpLFx*g2(rwvv_t8&gm~;LY{M?VB!2gt#88L9 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%0A$N3@rMA|xUI#Z#3 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