diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java index 5f5fa3af6813..332257a0994c 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompilerConfigurationImpl.java @@ -338,6 +338,7 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements } } + @Override public ExcludedEntriesConfiguration getExcludedEntriesConfiguration() { return myExcludedEntriesConfiguration; } diff --git a/java/compiler/impl/src/com/intellij/compiler/ProblemsView.java b/java/compiler/impl/src/com/intellij/compiler/ProblemsView.java index 63d055e55e44..7963493c7c6b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ProblemsView.java +++ b/java/compiler/impl/src/com/intellij/compiler/ProblemsView.java @@ -54,13 +54,11 @@ public abstract class ProblemsView { myProject = project; } - public abstract void clearMessages(CompileScope scope); - - public abstract void clearMessages(); + public abstract void clearOldMessages(CompileScope scope, UUID currentSessionId); public abstract void addMessage(int type, @NotNull String[] text, @Nullable String groupName, @NotNull Navigatable navigatable, @Nullable String exportTextPrefix, @Nullable String rendererTextPrefix, @NotNull UUID sessionId); - public void addMessage(CompilerMessage message, @NotNull UUID sessionId) { + public final void addMessage(CompilerMessage message, @NotNull UUID sessionId) { final VirtualFile file = message.getVirtualFile(); Navigatable navigatable = message.getNavigatable(); if (navigatable == null) { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index daa36a0445fd..889c4bf463ad 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -445,13 +445,13 @@ public class CompileDriver { return buildManager.scheduleBuild(myProject, compileContext.isRebuild(), compileContext.isMake(), scopes, paths, builderParams, new DefaultMessageHandler(myProject) { @Override public void buildStarted(UUID sessionId) { - final ProblemsView view = ProblemsViewImpl.SERVICE.getInstance(myProject); - view.clearMessages(compileContext.getCompileScope()); - view.clearProgress(); } @Override public void sessionTerminated(UUID sessionId) { + final ProblemsView view = ProblemsViewImpl.SERVICE.getInstance(myProject); + view.clearProgress(); + view.clearOldMessages(compileContext.getCompileScope(), sessionId); } @Override diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java index 0e20e9e450b0..e962c21cf219 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/ProblemsViewImpl.java @@ -16,21 +16,28 @@ package com.intellij.compiler.impl; import com.intellij.compiler.ProblemsView; +import com.intellij.ide.errorTreeView.ErrorTreeElement; +import com.intellij.ide.errorTreeView.ErrorViewStructure; +import com.intellij.ide.errorTreeView.GroupingElement; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.pom.Navigatable; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; +import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.UUID; +import java.util.concurrent.Executor; /** * @author Eugene Zhuravlev @@ -40,6 +47,12 @@ public class ProblemsViewImpl extends ProblemsView{ private static final String PROBLEMS_TOOLWINDOW_ID = "Problems"; private final ProblemsViewPanel myPanel; + private final SequentialTaskExecutor myViewUpdater = new SequentialTaskExecutor(new Executor() { + @Override + public void execute(Runnable command) { + ApplicationManager.getApplication().executeOnPooledThread(command); + } + }); public ProblemsViewImpl(final Project project, final ToolWindowManager wm) { super(project); @@ -71,21 +84,39 @@ public class ProblemsViewImpl extends ProblemsView{ } @Override - public void clearMessages(CompileScope scope) { - // todo: temporary solution: - clearMessages(); - - /* - final ErrorViewStructure structure = myPanel.getErrorViewStructure(); - for (ErrorTreeElement element : structure.getChildElements(structure.getRootElement())) { - // todo: add ability to remove selected messages in structure - } - */ + public void clearOldMessages(@Nullable final CompileScope scope, @NotNull final UUID currentSessionId) { + myViewUpdater.execute(new Runnable() { + @Override + public void run() { + cleanupChildrenRecursively(myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId); + myPanel.reload(); + } + }); } - @Override - public void clearMessages() { - myPanel.clearMessages(); + private void cleanupChildrenRecursively(@NotNull final Object fromElement, final @Nullable CompileScope scope, @NotNull UUID currentSessionId) { + final ErrorViewStructure structure = myPanel.getErrorViewStructure(); + for (ErrorTreeElement element : structure.getChildElements(fromElement)) { + if (element instanceof GroupingElement) { + if (scope != null) { + final VirtualFile file = ((GroupingElement)element).getFile(); + if (file != null && !scope.belongs(file.getUrl())) { + continue; + } + } + if (!currentSessionId.equals(element.getData())) { + structure.removeElement(element); + } + else { + cleanupChildrenRecursively(element, scope, currentSessionId); + } + } + else { + if (!currentSessionId.equals(element.getData())) { + structure.removeElement(element); + } + } + } } @Override @@ -94,7 +125,18 @@ public class ProblemsViewImpl extends ProblemsView{ @Nullable final String groupName, @NotNull final Navigatable navigatable, @Nullable final String exportTextPrefix, @Nullable final String rendererTextPrefix, @Nullable final UUID sessionId) { - myPanel.addMessage(type, text, groupName, navigatable, exportTextPrefix, rendererTextPrefix, sessionId); + + myViewUpdater.execute(new Runnable() { + @Override + public void run() { + final ErrorViewStructure structure = myPanel.getErrorViewStructure(); + final GroupingElement group = structure.lookupGroupingElement(groupName); + if (group != null && !sessionId.equals(group.getData())) { + structure.removeElement(group); + } + myPanel.addMessage(type, text, groupName, navigatable, exportTextPrefix, rendererTextPrefix, sessionId); + } + }); } @Override diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java index ab05c44f79bd..3cb2305d6a66 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java @@ -15,34 +15,21 @@ */ package com.intellij.compiler.options; -import com.intellij.compiler.CompilerConfiguration; -import com.intellij.compiler.CompilerConfigurationImpl; import com.intellij.compiler.CompilerSettingsFactory; -import com.intellij.compiler.impl.rmiCompiler.RmicConfiguration; -import com.intellij.compiler.server.BuildManager; import com.intellij.openapi.compiler.CompilerBundle; -import com.intellij.openapi.compiler.options.ExcludedEntriesConfigurable; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.vcs.FileStatusManager; -import org.jetbrains.annotations.Nls; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; public class CompilerConfigurable implements SearchableConfigurable.Parent, Configurable.NoScroll { - private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.options.CompilerConfigurable"); private final Project myProject; private final CompilerUIConfigurable myCompilerUIConfigurable; @@ -101,100 +88,16 @@ public class CompilerConfigurable implements SearchableConfigurable.Parent, Conf public Configurable[] getConfigurables() { if (myKids == null) { - List kids = new ArrayList(); - - CompilerConfigurationImpl compilerConfiguration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject); - final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, true, false, false, false, true); - - final ExcludedEntriesConfigurable excludes = - new ExcludedEntriesConfigurable(myProject, descriptor, compilerConfiguration.getExcludedEntriesConfiguration()) { - public void apply() { - super.apply(); - FileStatusManager.getInstance(myProject).fileStatusesChanged(); // refresh exclude from compile status - //ProjectView.getInstance(myProject).refresh(); - } - }; - - kids.add(createExcludesWrapper(excludes, myProject)); - - ArrayList additional = new ArrayList(); - final CompilerSettingsFactory[] factories = Extensions.getExtensions(CompilerSettingsFactory.EP_NAME, myProject); - if (factories.length > 0) { - for (CompilerSettingsFactory factory : factories) { - final Configurable configurable; - try { - configurable = factory.create(myProject); - } - catch (Exception e) { - LOG.error(e); - continue; - } - additional.add(configurable); + myKids = ContainerUtil.mapNotNull(factories, new NullableFunction() { + @Nullable + @Override + public Configurable fun(CompilerSettingsFactory factory) { + return factory.create(myProject); } - Collections.sort(additional, new Comparator() { - public int compare(final Configurable o1, final Configurable o2) { - return Comparing.compare(o1.getDisplayName(), o2.getDisplayName()); - } - }); - } - - additional.add(0, new RmicConfigurable(RmicConfiguration.getSettings(myProject))); - additional.add(0, new AnnotationProcessorsConfigurable(myProject)); - additional.add(0, new JavaCompilersTab(myProject, compilerConfiguration.getRegisteredJavaCompilers(), - compilerConfiguration.getDefaultCompiler())); - - kids.addAll(additional); - myKids = kids.toArray(new Configurable[kids.size()]); + }, new Configurable[0]); } return myKids; } - - private static Configurable createExcludesWrapper(final ExcludedEntriesConfigurable excludes, final Project project) { - return new SearchableConfigurable() { - @Nls - public String getDisplayName() { - return "Excludes"; - } - - public String getHelpTopic() { - return "reference.projectsettings.compiler.excludes"; - } - - public JComponent createComponent() { - return excludes.createComponent(); - } - - public void apply() { - excludes.apply(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - BuildManager.getInstance().clearState(project); - } - }); - } - - public boolean isModified() { - return excludes.isModified(); - } - - public void reset() { - excludes.reset(); - } - - public void disposeUIResources() { - excludes.disposeUIResources(); - } - - @NotNull - public String getId() { - return getHelpTopic(); - } - - public Runnable enableSearch(String option) { - return null; - } - }; - } } diff --git a/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java b/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java index 369c43093bc3..e7c767089f9a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java @@ -54,6 +54,11 @@ public class JavaCompilersTab implements SearchableConfigurable, Configurable.No private final Collection myConfigurables; private final TargetOptionsComponent myTargetLevelComponent; + public JavaCompilersTab(final Project project) { + this(project, ((CompilerConfigurationImpl)CompilerConfiguration.getInstance(project)).getRegisteredJavaCompilers(), + ((CompilerConfigurationImpl)CompilerConfiguration.getInstance(project)).getDefaultCompiler()); + } + public JavaCompilersTab(final Project project, Collection compilers, BackendCompiler defaultCompiler) { myProject = project; myDefaultCompiler = defaultCompiler; diff --git a/java/compiler/impl/src/com/intellij/compiler/options/RmicConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/RmicConfigurable.java index 95adcdf44cbd..75572c467308 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/RmicConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/RmicConfigurable.java @@ -15,11 +15,13 @@ */ package com.intellij.compiler.options; +import com.intellij.compiler.impl.rmiCompiler.RmicConfiguration; import com.intellij.compiler.impl.rmiCompiler.RmicSettings; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.project.Project; import com.intellij.ui.RawCommandLineEditor; import org.jetbrains.annotations.NotNull; @@ -41,8 +43,8 @@ public class RmicConfigurable implements SearchableConfigurable, Configurable.No private final RmicSettings myRmicSettings; private JLabel myFieldLabel; - public RmicConfigurable(final RmicSettings javacSettings) { - myRmicSettings = javacSettings; + public RmicConfigurable(final Project project) { + myRmicSettings = RmicConfiguration.getSettings(project); myCbEnabled.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { setOptionsEnabled(e.getStateChange() == ItemEvent.SELECTED); diff --git a/java/compiler/impl/src/com/intellij/compiler/server/AutoMakeMessageHandler.java b/java/compiler/impl/src/com/intellij/compiler/server/AutoMakeMessageHandler.java index ec1bb548e823..58fd8cf229de 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/AutoMakeMessageHandler.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/AutoMakeMessageHandler.java @@ -54,9 +54,6 @@ class AutoMakeMessageHandler extends DefaultMessageHandler { @Override public void buildStarted(UUID sessionId) { - final ProblemsView view = ProblemsView.SERVICE.getInstance(myProject); - view.clearMessages(); - view.clearProgress(); } @Override @@ -147,7 +144,9 @@ class AutoMakeMessageHandler extends DefaultMessageHandler { myProject.putUserData(LAST_AUTO_MAKE_NOFITICATION, null); } } - ProblemsView.SERVICE.getInstance(myProject).clearProgress(); + final ProblemsView view = ProblemsView.SERVICE.getInstance(myProject); + view.clearProgress(); + view.clearOldMessages(null, sessionId); } private void informWolf(Project project, CmdlineRemoteProto.Message.BuilderMessage.CompileMessage message) { diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index dd6d4a4b2a8f..6516bb9e0a25 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -66,7 +66,6 @@ import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.NetUtils; import gnu.trove.THashSet; -import gnu.trove.TObjectHashingStrategy; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.*; import org.jboss.netty.channel.group.ChannelGroup; @@ -963,8 +962,8 @@ public class BuildManager implements ApplicationComponent{ private static class ProjectData { final SequentialTaskExecutor taskQueue; - private final Set myChanged = new THashSet(PathHashingStrategy.INSTANCE); - private final Set myDeleted = new THashSet(PathHashingStrategy.INSTANCE); + private final Set myChanged = new THashSet(FileUtil.PATH_HASHING_STRATEGY); + private final Set myDeleted = new THashSet(FileUtil.PATH_HASHING_STRATEGY); private long myNextEventOrdinal = 0L; private boolean myNeedRescan = true; @@ -1009,20 +1008,6 @@ public class BuildManager implements ApplicationComponent{ myChanged.clear(); myDeleted.clear(); } - - static class PathHashingStrategy implements TObjectHashingStrategy { - static final PathHashingStrategy INSTANCE = new PathHashingStrategy(); - - @Override - public int computeHashCode(String path) { - return FileUtil.pathHashCode(path); - } - - @Override - public boolean equals(String path1, String path2) { - return FileUtil.pathsEqual(path1, path2); - } - } } } diff --git a/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java index 76bb48a9f0ad..9aa97cf0e089 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerConfiguration.java @@ -16,6 +16,7 @@ package com.intellij.compiler; +import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; @@ -58,4 +59,6 @@ public abstract class CompilerConfiguration { public abstract boolean isAddNotNullAssertions(); public abstract void setAddNotNullAssertions(boolean enabled); + + public abstract ExcludedEntriesConfiguration getExcludedEntriesConfiguration(); } \ No newline at end of file diff --git a/java/compiler/openapi/src/com/intellij/compiler/CompilerSettingsFactory.java b/java/compiler/openapi/src/com/intellij/compiler/CompilerSettingsFactory.java index f6e1c6fda83b..c2e85efeaf1a 100644 --- a/java/compiler/openapi/src/com/intellij/compiler/CompilerSettingsFactory.java +++ b/java/compiler/openapi/src/com/intellij/compiler/CompilerSettingsFactory.java @@ -20,9 +20,11 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; /** + * Please use {@link com.intellij.openapi.options.ConfigurableEP#parentId} to put your configurable under Compiler Settings * @author Eugene Zhuravlev * Date: Sep 17, 2008 */ +@Deprecated public interface CompilerSettingsFactory { ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.compilerSettingsFactory"); diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/options/ExcludedEntriesConfigurable.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/options/ExcludedEntriesConfigurable.java index a11d37e8c0a8..7a255fa1acc0 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/options/ExcludedEntriesConfigurable.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/options/ExcludedEntriesConfigurable.java @@ -16,6 +16,7 @@ package com.intellij.openapi.compiler.options; +import com.intellij.compiler.CompilerConfiguration; import com.intellij.ide.IdeBundle; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.fileChooser.FileChooser; @@ -24,6 +25,7 @@ import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vcs.FileStatusManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.*; import com.intellij.ui.table.JBTable; @@ -47,6 +49,11 @@ public class ExcludedEntriesConfigurable implements UnnamedConfigurable { private final ExcludedEntriesConfiguration myConfiguration; private ExcludedEntriesPanel myExcludedEntriesPanel; + public ExcludedEntriesConfigurable(Project project) { + this(project, new FileChooserDescriptor(true, true, false, false, false, true), + CompilerConfiguration.getInstance(project).getExcludedEntriesConfiguration()); + } + public ExcludedEntriesConfigurable(Project project, FileChooserDescriptor descriptor, final ExcludedEntriesConfiguration configuration) { myDescriptor = descriptor; myConfiguration = configuration; @@ -79,6 +86,7 @@ public class ExcludedEntriesConfigurable implements UnnamedConfigurable { for (ExcludeEntryDescription description : myExcludeEntryDescriptions) { myConfiguration.addExcludeEntryDescription(description.copy(myProject)); } + FileStatusManager.getInstance(myProject).fileStatusesChanged(); // refresh exclude from compile status } public boolean isModified() { diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java index c6da3f5728e2..ae1e5dde8848 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java @@ -44,7 +44,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.ColoredListCellRenderer; import com.intellij.ui.SortedComboBoxModel; import com.intellij.ui.components.JBLabel; import com.intellij.util.PathUtil; @@ -190,9 +190,9 @@ public class LibraryOptionsPanel implements Disposable { updateState(); } }); - myExistingLibraryComboBox.setRenderer(new HtmlListCellRenderer() { + myExistingLibraryComboBox.setRenderer(new ColoredListCellRenderer() { @Override - protected void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (value == null) { append("[No library selected]"); } diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java index 42a3e3265160..d3fe5df6f9f4 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java @@ -60,7 +60,7 @@ public class JdkChooserPanel extends JPanel { myListModel = new DefaultListModel(); myList = new JBList(myListModel); myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - myList.setCellRenderer(new ProjectJdkListRenderer(myList.getCellRenderer())); + myList.setCellRenderer(new ProjectJdkListRenderer()); myList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent e) { diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkListRenderer.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkListRenderer.java index 3166741b8921..5847e66e3668 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkListRenderer.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkListRenderer.java @@ -17,7 +17,7 @@ package com.intellij.ide.util.projectWizard; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ui.OrderEntryAppearanceService; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.ColoredListCellRendererWrapper; import com.intellij.ui.SimpleTextAttributes; import javax.swing.*; @@ -26,11 +26,7 @@ import javax.swing.*; * @author Eugene Zhuravlev * @since May 18, 2005 */ -public class ProjectJdkListRenderer extends HtmlListCellRenderer { - public ProjectJdkListRenderer(final ListCellRenderer listCellRenderer) { - super(); - } - +public class ProjectJdkListRenderer extends ColoredListCellRendererWrapper { @Override public void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (value == null || value instanceof Sdk) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java index 6402f95c2798..4808c4148ec0 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java @@ -63,7 +63,7 @@ public class JdkComboBox extends ComboBoxWithWidePopup { super(new JdkComboBoxModel(jdkModel, filter)); myFilter = filter; myCreationFilter = creationFilter; - setRenderer(new ProjectJdkListRenderer(getRenderer()) { + setRenderer(new ProjectJdkListRenderer() { @Override public void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (JdkComboBox.this.isEnabled()) { diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 05fedc0990e5..1632dbc5f8cd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -121,7 +121,7 @@ public class HighlightMethodUtil { for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) { PsiMethod superMethod = superMethodSignature.getMethod(); PsiType declaredReturnType = superMethod.getReturnType(); - PsiType superReturnType = superMethodSignature.getSubstitutor().substitute(declaredReturnType); + PsiType superReturnType = declaredReturnType; if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType); if (returnType == null || superReturnType == null || method == superMethod) continue; PsiClass superClass = superMethod.getContainingClass(); @@ -151,10 +151,10 @@ public class HighlightMethodUtil { superMethodSignature); substitutedSuperReturnType = unifyingSubstitutor == null ? superReturnType - : unifyingSubstitutor.substitute(superMethodSignature.getSubstitutor().substitute(superReturnType)); + : unifyingSubstitutor.substitute(superReturnType); } else { - substitutedSuperReturnType = TypeConversionUtil.erasure(superReturnType); + substitutedSuperReturnType = TypeConversionUtil.erasure(superMethodSignature.getSubstitutor().substitute(superReturnType)); } if (returnType.equals(substitutedSuperReturnType)) return null; diff --git a/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java b/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java new file mode 100644 index 000000000000..eaca9f997748 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/documentation/JavaDocCommentFixer.java @@ -0,0 +1,267 @@ +/* + * 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.codeInsight.documentation; + +import com.intellij.codeInspection.InspectionManager; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.QuickFix; +import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection; +import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection; +import com.intellij.javadoc.JavadocNavigationDelegate; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.javadoc.PsiDocComment; +import com.intellij.psi.javadoc.PsiDocTag; +import com.intellij.psi.javadoc.PsiDocTagValue; +import com.intellij.util.containers.ContainerUtilRt; +import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +/** + * @author Denis Zhdanov + * @since 9/20/12 8:44 PM + */ +public class JavaDocCommentFixer implements DocCommentFixer { + + @NotNull private static final String PARAM_TAG = "@param"; + + /** + * Lists tags eligible for moving caret to after javadoc fixing. The main idea is that we want to locate caret at the + * incomplete tag description after fixing the doc comment. + *

+ * Example: + *

+   *   class Test {
+   *     /**
+   *      * Method description
+   *      *
+   *      * @param i    'i' argument
+   *      * @param j    [we want to move the caret here because j's description is missing]
+   *      */
+   *     void test(int i, int j) {
+   *     }
+   *   }
+   * 
+ */ + @NotNull private static final Set CARET_ANCHOR_TAGS = ContainerUtilRt.newHashSet(PARAM_TAG, "@throws", "@return"); + + @NotNull private static final List TAGS_ORDER = new ArrayList(); + static { + String tags = System.getProperty("java.doc.comment.fix.tags.order"); + if (tags == null) { + tags = "@param:@return:@throws"; + } + + for (String s : tags.split(":")) { + String tagName = s.trim(); + if (!tagName.isEmpty()) { + TAGS_ORDER.add("@" + tagName); + } + } + } + + private static final Comparator COMPARATOR = new Comparator() { + @Override + public int compare(PsiElement e1, PsiElement e2) { + return e2.getTextRange().getEndOffset() - e1.getTextRange().getEndOffset(); + } + }; + + @Override + public void fixComment(@NotNull Project project, @NotNull Editor editor, @NotNull PsiComment comment) { + if (!(comment instanceof PsiDocComment)) { + return; + } + + PsiDocCommentOwner owner = ((PsiDocComment)comment).getOwner(); + if (owner == null) { + return; + } + + JavaDocReferenceInspection referenceInspection = new JavaDocReferenceInspection(); + JavaDocLocalInspection localInspection = getDocLocalInspection(); + + InspectionManager inspectionManager = InspectionManager.getInstance(project); + ProblemDescriptor[] referenceProblems = null; + ProblemDescriptor[] otherProblems = null; + if (owner instanceof PsiClass) { + referenceProblems = referenceInspection.checkClass(((PsiClass)owner), inspectionManager, false); + otherProblems = localInspection.checkClass(((PsiClass)owner), inspectionManager, false); + } + else if (owner instanceof PsiField) { + referenceProblems = referenceInspection.checkField(((PsiField)owner), inspectionManager, false); + otherProblems = localInspection.checkField(((PsiField)owner), inspectionManager, false); + } + else if (owner instanceof PsiMethod) { + referenceProblems = referenceInspection.checkMethod((PsiMethod)owner, inspectionManager, false); + otherProblems = localInspection.checkMethod((PsiMethod)owner, inspectionManager, false); + } + + if (referenceProblems != null) { + fixReferenceProblems(referenceProblems, project); + } + if (otherProblems != null) { + fixCommonProblems(otherProblems, comment, editor.getDocument(), project); + } + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + locateCaret((PsiDocComment)comment, editor); + } + + @NotNull + private static JavaDocLocalInspection getDocLocalInspection() { + JavaDocLocalInspection localInspection = new JavaDocLocalInspection(); + + //region visibility + localInspection.TOP_LEVEL_CLASS_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = PsiModifier.PRIVATE; + localInspection.INNER_CLASS_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = PsiModifier.PRIVATE; + localInspection.FIELD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = PsiModifier.PRIVATE; + localInspection.METHOD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = PsiModifier.PRIVATE; + //endregion + + localInspection.IGNORE_EMPTY_DESCRIPTIONS = true; + + //region class type arguments + if (!localInspection.TOP_LEVEL_CLASS_OPTIONS.REQUIRED_TAGS.contains(PARAM_TAG)) { + localInspection.TOP_LEVEL_CLASS_OPTIONS.REQUIRED_TAGS += PARAM_TAG; + } + if (!localInspection.INNER_CLASS_OPTIONS.REQUIRED_TAGS.contains(PARAM_TAG)) { + localInspection.INNER_CLASS_OPTIONS.REQUIRED_TAGS += PARAM_TAG; + } + //endregion + + return localInspection; + } + + @SuppressWarnings("unchecked") + private static void fixReferenceProblems(@NotNull ProblemDescriptor[] problems, @NotNull Project project) { + for (ProblemDescriptor problem : problems) { + QuickFix[] fixes = problem.getFixes(); + if (fixes != null) { + fixes[0].applyFix(project, problem); + } + } + } + + // TODO den add doc + @SuppressWarnings("unchecked") + private static void fixCommonProblems(@NotNull ProblemDescriptor[] problems, + @NotNull PsiComment comment, + @NotNull final Document document, + @NotNull Project project) + { + List toRemove = new ArrayList(); + for (ProblemDescriptor problem : problems) { + PsiElement element = problem.getPsiElement(); + if (element == null) { + continue; + } + if (comment.getTextRange().contains(element.getTextRange())) { + // Unnecessary element like '@return' at the void method's javadoc. + for (PsiElement e = element; e != null; e = e.getParent()) { + if (e instanceof PsiDocTag) { + toRemove.add(e); + break; + } + } + } + else { + // Problems like 'missing @param'. + QuickFix[] fixes = problem.getFixes(); + if (fixes != null && fixes.length > 0) { + fixes[0].applyFix(project, problem); + } + } + } + + if (toRemove.isEmpty()) { + return; + } + if (toRemove.size() > 1) { + Collections.sort(toRemove, COMPARATOR); + } + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document); + CharSequence text = document.getCharsSequence(); + for (PsiElement element : toRemove) { + int startOffset = element.getTextRange().getStartOffset(); + int startLine = document.getLineNumber(startOffset); + int i = CharArrayUtil.shiftBackward(text, startOffset - 1, " \t"); + if (i >= 0) { + char c = text.charAt(i); + if (c == '*') { + i = CharArrayUtil.shiftBackward(text, i - 1, " \t"); + } + } + if (i >= 0 && text.charAt(i) == '\n') { + startOffset = Math.max(i, document.getLineStartOffset(startLine) - 1); + } + + int endOffset = element.getTextRange().getEndOffset(); + // Javadoc PSI is awkward, it includes next line text before the next tag. That's why we need to strip it. + i = CharArrayUtil.shiftBackward(text, endOffset - 1, " \t*"); + if (i > 0 && text.charAt(i) == '\n') { + endOffset = i; + } + document.deleteString(startOffset, endOffset); + } + } + + private static void locateCaret(@NotNull PsiDocComment comment, @NotNull Editor editor) { + Document document = editor.getDocument(); + int lineToNavigate = -1; + for (PsiDocTag tag : comment.getTags()) { + PsiElement nameElement = tag.getNameElement(); + if (nameElement == null || !CARET_ANCHOR_TAGS.contains(nameElement.getText())) { + continue; + } + boolean good = false; + PsiElement[] dataElements = tag.getDataElements(); + if (dataElements != null) { + PsiDocTagValue valueElement = tag.getValueElement(); + for (PsiElement element : dataElements) { + if (element == valueElement) { + continue; + } + if (!StringUtil.isEmptyOrSpaces(element.getText())) { + good = true; + break; + } + } + } + if (!good) { + int offset = tag.getTextRange().getEndOffset(); + CharSequence text = document.getCharsSequence(); + int i = CharArrayUtil.shiftBackward(text, offset - 1, " \t*"); + if (i > 0 && text.charAt(i) == '\n') { + offset = i - 1; + } + lineToNavigate = document.getLineNumber(offset); + break; + } + } + + if (lineToNavigate >= 0) { + editor.getCaretModel().moveToOffset(document.getLineEndOffset(lineToNavigate)); + JavadocNavigationDelegate.navigateToLineEnd(editor, comment.getContainingFile()); + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index 8b49b808dc1e..4d91e400d137 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -30,6 +30,7 @@ import com.intellij.codeInsight.NullableNotNullDialog; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInsight.daemon.GroupNames; import com.intellij.codeInsight.daemon.impl.quickfix.SimplifyBooleanExpressionFix; +import com.intellij.codeInsight.intention.impl.AddNullableAnnotationFix; import com.intellij.codeInspection.*; import com.intellij.codeInspection.dataFlow.instructions.*; import com.intellij.codeInspection.ex.BaseLocalInspectionTool; @@ -182,6 +183,36 @@ public class DataFlowInspection extends BaseLocalInspectionTool { reportNullableAssignments(runner, holder); reportUnboxedNullables(runner, holder); reportNullableReturns(runner, holder); + reportNullableArgumentsPassedToNonAnnotated(runner, holder); + } + + private static void reportNullableArgumentsPassedToNonAnnotated(StandardDataFlowRunner runner, ProblemsHolder holder) { + Set exprs = runner.getNullableArgumentsPassedToNonAnnotatedParam(); + for (PsiExpression expr : exprs) { + final String text = isNullLiteralExpression(expr) + ? "Passing null argument to non annotated parameter" + : "Argument #ref #loc might be null but passed to non annotated parameter"; + LocalQuickFix[] fixes = createNPEFixes(expr, expr); + final PsiElement parent = expr.getParent(); + if (parent instanceof PsiExpressionList) { + final int idx = ArrayUtil.find(((PsiExpressionList)parent).getExpressions(), expr); + if (idx > -1) { + final PsiElement gParent = parent.getParent(); + if (gParent instanceof PsiCallExpression) { + final PsiMethod psiMethod = ((PsiCallExpression)gParent).resolveMethod(); + if (psiMethod != null && psiMethod.getManager().isInProject(psiMethod)) { + final PsiParameter[] parameters = psiMethod.getParameterList().getParameters(); + if (idx < parameters.length) { + final AddNullableAnnotationFix addNullableAnnotationFix = new AddNullableAnnotationFix(parameters[idx]); + fixes = fixes == null ? new LocalQuickFix[]{addNullableAnnotationFix} : ArrayUtil.append(fixes, addNullableAnnotationFix); + holder.registerProblem(expr, text, fixes); + } + } + } + } + } + + } } private static void reportCallMayProduceNpe(ProblemsHolder holder, MethodCallInstruction mcInstruction) { @@ -577,5 +608,10 @@ public class DataFlowInspection extends BaseLocalInspectionTool { protected void onPassingNullParameter(DataFlowRunner runner, PsiExpression arg) { ((StandardDataFlowRunner)runner).onPassingNullParameter(arg); // Parameters on stack are reverted. } + + @Override + protected void onPassingNullParameterToNonAnnotated(DataFlowRunner runner, PsiExpression arg) { + ((StandardDataFlowRunner)runner).onPassingNullParameterToNonAnnotated(arg); + } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardDataFlowRunner.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardDataFlowRunner.java index b4d8c41d15bd..c09e4528c571 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardDataFlowRunner.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardDataFlowRunner.java @@ -46,6 +46,7 @@ public class StandardDataFlowRunner extends AnnotationsAwareDataFlowRunner { private final Set myNPEInstructions = new HashSet(); private final Set myCCEInstructions = new HashSet(); private final Set myNullableArguments = new HashSet(); + private final Set myNullableArgumentsPassedToNonAnnotatedParam = new HashSet(); private final Set myNullableAssignments = new HashSet(); private final Set myNullableReturns = new HashSet(); @@ -74,6 +75,7 @@ public class StandardDataFlowRunner extends AnnotationsAwareDataFlowRunner { myNPEInstructions.clear(); myCCEInstructions.clear(); myNullableArguments.clear(); + myNullableArgumentsPassedToNonAnnotatedParam.clear(); myNullableAssignments.clear(); myNullableReturns.clear(); myUnboxedNullables.clear(); @@ -109,6 +111,10 @@ public class StandardDataFlowRunner extends AnnotationsAwareDataFlowRunner { return myNullableArguments; } + public Set getNullableArgumentsPassedToNonAnnotatedParam() { + return myNullableArgumentsPassedToNonAnnotatedParam; + } + @NotNull public Set getNullableAssignments() { return myNullableAssignments; } @@ -128,6 +134,12 @@ public class StandardDataFlowRunner extends AnnotationsAwareDataFlowRunner { myNullableArguments.add(expr); } + public void onPassingNullParameterToNonAnnotated(PsiExpression expr) { + if (mySuggestNullableAnnotations) { + myNullableArgumentsPassedToNonAnnotatedParam.add(expr); + } + } + public void onAssigningToNotNullableVariable(final PsiExpression expr) { myNullableAssignments.add(expr); } @@ -147,6 +159,7 @@ public class StandardDataFlowRunner extends AnnotationsAwareDataFlowRunner { || !myCCEInstructions.isEmpty() || !getRedundantInstanceofs(this, visitor).isEmpty() || !myNullableArguments.isEmpty() + || !myNullableArgumentsPassedToNonAnnotatedParam.isEmpty() || !myNullableAssignments.isEmpty() || !myNullableReturns.isEmpty() || !myUnboxedNullables.isEmpty(); diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 0af557f5bcd7..f2ecef1f8f4d 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -56,6 +56,25 @@ public class StandardInstructionVisitor extends InstructionVisitor { } } }; + private final FactoryMap myParametersNonAnnotated = new FactoryMap() { + @Override + protected boolean[] create(MethodCallInstruction key) { + final PsiCallExpression callExpression = key.getCallExpression(); + final PsiMethod callee = callExpression == null ? null : callExpression.resolveMethod(); + if (callee != null) { + final PsiParameter[] params = callee.getParameterList().getParameters(); + boolean[] result = new boolean[params.length]; + final NullableNotNullManager notNullManager = NullableNotNullManager.getInstance(callee.getProject()); + for (int i = 0; i < params.length; i++) { + result[i] = !notNullManager.isNotNull(params[i], false) && !notNullManager.isNullable(params[i], false); + } + return result; + } + else { + return ArrayUtil.EMPTY_BOOLEAN_ARRAY; + } + } + }; private final FactoryMap myCalleeNullability = new FactoryMap() { @Override protected Boolean create(MethodCallInstruction key) { @@ -161,14 +180,22 @@ public class StandardInstructionVisitor extends InstructionVisitor { public DfaInstructionState[] visitMethodCall(MethodCallInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { final PsiExpression[] args = instruction.getArgs(); final boolean[] parametersNotNull = myParametersNotNull.get(instruction); + final boolean[] nonAnnotated = myParametersNonAnnotated.get(instruction); final DfaNotNullValue.Factory factory = runner.getFactory().getNotNullFactory(); for (int i = 0; i < args.length; i++) { final DfaValue arg = memState.pop(); final int revIdx = args.length - i - 1; - if (args.length <= parametersNotNull.length && revIdx < parametersNotNull.length && parametersNotNull[revIdx] && !memState.applyNotNull(arg)) { - onPassingNullParameter(runner, args[revIdx]); - if (arg instanceof DfaVariableValue) { - memState.setVarValue((DfaVariableValue)arg, factory.create(((DfaVariableValue)arg).getVariableType())); + if (args.length <= parametersNotNull.length && revIdx < parametersNotNull.length) { + if (parametersNotNull[revIdx]) { + if (!memState.applyNotNull(arg)) { + onPassingNullParameter(runner, args[revIdx]); + if (arg instanceof DfaVariableValue) { + memState.setVarValue((DfaVariableValue)arg, factory.create(((DfaVariableValue)arg).getVariableType())); + } + } + } + else if (nonAnnotated[revIdx] && !memState.checkNotNullable(arg)) { + onPassingNullParameterToNonAnnotated(runner, args[revIdx]); } } } @@ -248,6 +275,7 @@ public class StandardInstructionVisitor extends InstructionVisitor { protected void onUnboxingNullable(MethodCallInstruction instruction, DataFlowRunner runner) {} protected void onPassingNullParameter(DataFlowRunner runner, PsiExpression arg) {} + protected void onPassingNullParameterToNonAnnotated(DataFlowRunner runner, PsiExpression arg) {} @Override public DfaInstructionState[] visitBinop(BinopInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) { diff --git a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java index e9963add3b43..682268b983d5 100644 --- a/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspection.java @@ -92,15 +92,16 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { } } - @NonNls public Options TOP_LEVEL_CLASS_OPTIONS = new Options("none", ""); - @NonNls public Options INNER_CLASS_OPTIONS = new Options("none", ""); - @NonNls public Options METHOD_OPTIONS = new Options("none", "@return@param@throws or @exception"); - @NonNls public Options FIELD_OPTIONS = new Options("none", ""); - public boolean IGNORE_DEPRECATED = false; - public boolean IGNORE_JAVADOC_PERIOD = true; - public boolean IGNORE_DUPLICATED_THROWS = false; - public boolean IGNORE_POINT_TO_ITSELF = false; - public String myAdditionalJavadocTags = ""; + @NonNls public Options TOP_LEVEL_CLASS_OPTIONS = new Options("none", ""); + @NonNls public Options INNER_CLASS_OPTIONS = new Options("none", ""); + @NonNls public Options METHOD_OPTIONS = new Options("none", "@return@param@throws or @exception"); + @NonNls public Options FIELD_OPTIONS = new Options("none", ""); + public boolean IGNORE_DEPRECATED = false; + public boolean IGNORE_JAVADOC_PERIOD = true; + public boolean IGNORE_DUPLICATED_THROWS = false; + public boolean IGNORE_POINT_TO_ITSELF = false; + public boolean IGNORE_EMPTY_DESCRIPTIONS = false; + public String myAdditionalJavadocTags = ""; private static final Logger LOG = Logger.getInstance("com.intellij.codeInspection.javaDoc.JavaDocLocalInspection"); @@ -145,8 +146,8 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { private class MyChangeListener implements ChangeListener { private final JCheckBox myCheckBox; - private final Options myOptions; - private final String myTagName; + private final Options myOptions; + private final String myTagName; public MyChangeListener(JCheckBox checkBox, Options options, String tagName) { myCheckBox = checkBox; @@ -156,7 +157,7 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { public void stateChanged(ChangeEvent e) { if (myCheckBox.isSelected()) { - if (!isTagRequired(myOptions,myTagName)) { + if (!isTagRequired(myOptions, myTagName)) { myOptions.REQUIRED_TAGS += myTagName; } } @@ -594,27 +595,29 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { } } - for (PsiDocTag tag : tags) { - if ("param".equals(tag.getName())) { - final PsiElement[] dataElements = tag.getDataElements(); - final PsiDocTagValue valueElement = tag.getValueElement(); - boolean hasProblemsWithTag = dataElements.length < 2; - if (!hasProblemsWithTag) { - final StringBuilder buf = new StringBuilder(); - for (PsiElement element : dataElements) { - if (element != valueElement){ - buf.append(element.getText()); + if (!IGNORE_EMPTY_DESCRIPTIONS) { + for (PsiDocTag tag : tags) { + if ("param".equals(tag.getName())) { + final PsiElement[] dataElements = tag.getDataElements(); + final PsiDocTagValue valueElement = tag.getValueElement(); + boolean hasProblemsWithTag = dataElements.length < 2; + if (!hasProblemsWithTag) { + final StringBuilder buf = new StringBuilder(); + for (PsiElement element : dataElements) { + if (element != valueElement){ + buf.append(element.getText()); + } } + hasProblemsWithTag = buf.toString().trim().length() == 0; } - hasProblemsWithTag = buf.toString().trim().length() == 0; - } - if (hasProblemsWithTag) { - if (valueElement != null) { - problems.add(createDescriptor(valueElement, - InspectionsBundle.message("inspection.javadoc.method.problem.missing.tag.description", "@param " + valueElement.getText() + ""), - manager, isOnTheFly)); + if (hasProblemsWithTag) { + if (valueElement != null) { + problems.add(createDescriptor(valueElement, + InspectionsBundle.message("inspection.javadoc.method.problem.missing.tag.description", "@param " + valueElement.getText() + ""), + manager, isOnTheFly)); + } + } - } } } @@ -661,7 +664,7 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { } } else - if ("return".equals(tag.getName())) { + if ("return".equals(tag.getName()) && !IGNORE_EMPTY_DESCRIPTIONS) { if (extractTagDescription(tag).length() == 0) { String message = InspectionsBundle.message("inspection.javadoc.method.problem.missing.tag.description", "@return"); ProblemDescriptor descriptor = manager.createProblemDescriptor(tag.getNameElement(), message, (LocalQuickFix)null, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, @@ -694,10 +697,10 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { return false; } - private static void processThrowsTags(final PsiDocTag[] tags, - final Map declaredExceptions, - final InspectionManager mananger, - @NotNull final ArrayList problems, boolean isOnTheFly) { + private void processThrowsTags(final PsiDocTag[] tags, + final Map declaredExceptions, + final InspectionManager mananger, + @NotNull final ArrayList problems, boolean isOnTheFly) { for (PsiDocTag tag : tags) { if ("throws".equals(tag.getName()) || "exception".equals(tag.getName())) { final PsiDocTagValue value = tag.getValueElement(); @@ -714,7 +717,7 @@ public class JavaDocLocalInspection extends BaseLocalInspectionTool { PsiClassType classType = it.next(); final PsiClass psiClass = declaredExceptions.get(classType); if (InheritanceUtil.isInheritorOrSelf(exceptionClass, psiClass, true)) { - if (extractThrowsTagDescription(tag).length() == 0) { + if (!IGNORE_EMPTY_DESCRIPTIONS && extractThrowsTagDescription(tag).length() == 0) { problems.add(createDescriptor(tag.getNameElement(), InspectionsBundle.message("inspection.javadoc.method.problem.missing.tag.description", "" + tag.getName() + ""), mananger, isOnTheFly)); } diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java index b8e3203e55ec..6530c36e7f55 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspection.java @@ -31,7 +31,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.search.GlobalSearchScope; @@ -73,42 +72,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { checkNullableStuffForMethod(method, holder); } - @Override - public void visitMethodCallExpression(PsiMethodCallExpression expression) { - if (!PsiUtil.isLanguageLevel5OrHigher(expression) || !REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD) return; - final PsiMethod psiMethod = expression.resolveMethod(); - if (psiMethod != null && (psiMethod.getManager().isInProject(psiMethod) || CodeStyleSettingsManager.getInstance().getCurrentSettings().USE_EXTERNAL_ANNOTATIONS)) { - final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(holder.getProject()); - final PsiClass annotationsClass = - JavaPsiFacade.getInstance(holder.getProject()).findClass(nullableNotNullManager.getDefaultNullable(), psiMethod.getResolveScope()); - if (annotationsClass == null) return; - final PsiParameterList parameterList = psiMethod.getParameterList(); - final PsiParameter[] parameters = parameterList.getParameters(); - final PsiExpression[] expressions = expression.getArgumentList().getExpressions(); - for (int i = 0, expressionsLength = expressions.length; i < Math.min(expressionsLength, parameters.length); i++) { - PsiExpression psiExpression = expressions[i]; - boolean nullablePassedAsParameter = false; - if (psiExpression instanceof PsiMethodCallExpression) { - final PsiMethod method = expression.resolveMethod(); - nullablePassedAsParameter = nullableNotNullManager.isNullable(method, false); - } else if (psiExpression instanceof PsiReferenceExpression) { - final PsiElement resolve = ((PsiReferenceExpression)psiExpression).resolve(); - if (resolve instanceof PsiModifierListOwner) { - nullablePassedAsParameter = nullableNotNullManager.isNullable((PsiModifierListOwner)resolve, false); - } - } - final PsiType exprType = psiExpression.getType(); - if (exprType == PsiType.NULL || nullablePassedAsParameter) { - final PsiParameter parameter = parameters[i]; - if (!NullableNotNullManager.isNullable(parameter) && !NullableNotNullManager.isNotNull(parameter)) { - holder.registerProblem(psiExpression, "Nullable value is passed to parameter which is not yet @Nullable", - new MyAddNullableAnnotationFix(parameter)); - } - } - } - } - } - @Override public void visitField(PsiField field) { if (!PsiUtil.isLanguageLevel5OrHigher(field)) return; final PsiType type = field.getType(); @@ -450,7 +413,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { private JCheckBox myNAMethodOverridesNN; private JPanel myPanel; private JCheckBox myReportNotAnnotatedGetter; - private JCheckBox myReportNullsPassedToNonAnnotatedParameter; private JButton myConfigureAnnotationsButton; private OptionsPanel() { @@ -465,7 +427,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { myNAMethodOverridesNN.addActionListener(actionListener); myNNParameterOverridesN.addActionListener(actionListener); myReportNotAnnotatedGetter.addActionListener(actionListener); - myReportNullsPassedToNonAnnotatedParameter.addActionListener(actionListener); myConfigureAnnotationsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -482,7 +443,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { myNNParameterOverridesN.setSelected(REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE); myNAMethodOverridesNN.setSelected(REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL); myReportNotAnnotatedGetter.setSelected(REPORT_NOT_ANNOTATED_GETTER); - myReportNullsPassedToNonAnnotatedParameter.setSelected(REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD); } private void apply() { @@ -490,7 +450,6 @@ public class NullableStuffInspection extends BaseLocalInspectionTool { REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE = myNNParameterOverridesN.isSelected(); REPORT_NOT_ANNOTATED_GETTER = myReportNotAnnotatedGetter.isSelected(); REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL; - REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD = myReportNullsPassedToNonAnnotatedParameter.isSelected(); } } diff --git a/java/java-impl/src/com/intellij/codeInspection/nullable/OptionsPanel.form b/java/java-impl/src/com/intellij/codeInspection/nullable/OptionsPanel.form index 2c21e09d1329..563f3a303e29 100644 --- a/java/java-impl/src/com/intellij/codeInspection/nullable/OptionsPanel.form +++ b/java/java-impl/src/com/intellij/codeInspection/nullable/OptionsPanel.form @@ -1,6 +1,6 @@
- + @@ -10,7 +10,7 @@ - + @@ -21,14 +21,6 @@ - - - - - - - - @@ -47,7 +39,7 @@ - + diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocNavigationDelegate.java b/java/java-impl/src/com/intellij/javadoc/JavadocNavigationDelegate.java index 4a92f5bc8175..20d8005282a1 100644 --- a/java/java-impl/src/com/intellij/javadoc/JavadocNavigationDelegate.java +++ b/java/java-impl/src/com/intellij/javadoc/JavadocNavigationDelegate.java @@ -94,10 +94,10 @@ public class JavadocNavigationDelegate extends EditorNavigationDelegateAdapter { return Result.CONTINUE; } - return navigateToLineEnd(editor, project, psiFile); + return navigateToLineEnd(editor, psiFile); } - public static Result navigateToLineEnd(@NotNull Editor editor, @NotNull Project project, @NotNull PsiFile psiFile) { + public static Result navigateToLineEnd(@NotNull Editor editor, @NotNull PsiFile psiFile) { final Document document = editor.getDocument(); final CaretModel caretModel = editor.getCaretModel(); final int offset = caretModel.getOffset(); diff --git a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java index a569eb08a687..5a8a050ea450 100644 --- a/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/anonymousToInner/AnonymousToInnerDialog.java @@ -91,10 +91,11 @@ class AnonymousToInnerDialog extends DialogWrapper{ if (psiType instanceof PsiClassType) { type = TypeConversionUtil.erasure(psiType); } + if (type == null || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return ""; if (type instanceof PsiArrayType) { type = type.getDeepComponentType(); } - return type.getPresentableText(); + return StringUtil.getShortName(type.getPresentableText()); } }, "") + name, "My" + name}; } else { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java index 1dc4423e8643..43175d7d7c6e 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.typeMigration; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.Nullable; /** * @author db @@ -35,6 +36,7 @@ public class Util { return parent; } + @Nullable public static PsiElement normalizeElement(final PsiElement element) { if (element instanceof PsiMethod) { final PsiMethod superMethod = ((PsiMethod)element).findDeepestSuperMethod(); @@ -42,6 +44,18 @@ public class Util { return superMethod == null ? element : superMethod; } else if (element instanceof PsiParameter && element.getParent() instanceof PsiParameterList) { + final PsiElement declarationScope = ((PsiParameter)element).getDeclarationScope(); + if (declarationScope instanceof PsiLambdaExpression) { + final PsiType interfaceType = ((PsiLambdaExpression)declarationScope).getFunctionalInterfaceType(); + if (interfaceType != null) { + final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(interfaceType); + if (interfaceMethod != null) { + final int index = ((PsiParameterList)element.getParent()).getParameterIndex((PsiParameter)element); + return interfaceMethod.getParameterList().getParameters()[index]; + } + } + return null; + } final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); if (method != null) { @@ -64,7 +78,7 @@ public class Util { final PsiElement element = normalizeElement(e); - if (!element.getManager().isInProject(element)) { + if (element == null || !element.getManager().isInProject(element)) { return false; } diff --git a/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java b/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java index 3819fe5290b5..3b4f9a214703 100644 --- a/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java +++ b/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.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. @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.psi; import com.intellij.openapi.components.ServiceManager; @@ -27,6 +23,9 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +/** + * @author max + */ public abstract class JavaPsiFacade { private static final NotNullLazyKey INSTANCE_KEY = ServiceManager.createLazyKey(JavaPsiFacade.class); @@ -38,18 +37,6 @@ public abstract class JavaPsiFacade { return getInstance(project).getElementFactory(); } - /** - * Searches the project and all its libraries for a class with the specified full-qualified - * name and returns one if it is found. - * - * @param qualifiedName the full-qualified name of the class to find. - * @return the PSI class, or null if no class with such name is found. - * @deprecated use {@link #findClass(String, com.intellij.psi.search.GlobalSearchScope)} - */ - @Nullable - public abstract PsiClass findClass(@NotNull @NonNls String qualifiedName); - - /** * Searches the specified scope within the project for a class with the specified full-qualified * name and returns one if it is found. @@ -61,7 +48,6 @@ public abstract class JavaPsiFacade { @Nullable public abstract PsiClass findClass(@NonNls @NotNull String qualifiedName, @NotNull GlobalSearchScope scope); - /** * Searches the specified scope within the project for classes with the specified full-qualified * name and returns all found classes. @@ -94,8 +80,8 @@ public abstract class JavaPsiFacade { /** * Returns the factory for the project, which can be used to create instances of certain java constructs from their textual - * presentation. Elements created shall not be used to later interfer (like insert into) a PSI parsed from the user codebase - * since no formatting to the user codestyle will be performed in this case. Please use {@link #getElementFactory()} instead, which + * representation. Elements created shall not be used to later intermix (like insert into) a PSI parsed from the user codebase + * since no formatting to the user code style will be performed in this case. Please use {@link #getElementFactory()} instead, which * provides exactly same methods but ensures created instances will get properly formatted. * @return the parser facade. */ diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java index 64d52091062b..365581938b98 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -22,14 +22,24 @@ package com.intellij.psi.impl; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFileFilter; import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; public abstract class JavaPsiFacadeEx extends JavaPsiFacade { - public static JavaPsiFacadeEx getInstanceEx(Project project) { + @TestOnly + public static JavaPsiFacadeEx getInstanceEx(@NotNull Project project) { return (JavaPsiFacadeEx)getInstance(project); } + @TestOnly + @Nullable + public PsiClass findClass(@NotNull String qualifiedName) { + return findClass(qualifiedName, GlobalSearchScope.allScope(getProject())); + } + @TestOnly public abstract void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter); } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index 16cecad25dec..17e4eecd4d22 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -90,14 +90,6 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { JavaElementType.ANNOTATION.getIndex(); // Initialize stubs. } - /** - * @deprecated - */ - @Override - public PsiClass findClass(@NotNull String qualifiedName) { - return findClass(qualifiedName, GlobalSearchScope.allScope(myProject)); - } - @Override public PsiClass findClass(@NotNull final String qualifiedName, @NotNull GlobalSearchScope scope) { ProgressIndicatorProvider.checkCanceled(); // We hope this method is being called often enough to cancel daemon processes smoothly diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java index 485fa9289950..b84f064216b3 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -303,7 +303,9 @@ public class PsiSuperMethodImplUtil { PsiSubstitutor superSubstitutor, PsiSubstitutor derivedSubstitutor, boolean inRawContext) { if (inRawContext) { - superSubstitutor = JavaPsiFacadeEx.getElementFactory(superClass.getProject()).createRawSubstitutor(derivedSubstitutor, superSubstitutor.getSubstitutionMap().keySet().toArray(PsiTypeParameter.EMPTY_ARRAY)); + Set typeParams = superSubstitutor.getSubstitutionMap().keySet(); + PsiElementFactory factory = JavaPsiFacade.getElementFactory(superClass.getProject()); + superSubstitutor = factory.createRawSubstitutor(derivedSubstitutor, typeParams.toArray(new PsiTypeParameter[typeParams.size()])); } Map map = null; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(superClass)) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java index b04b592b48af..a8bcac5e5fcd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.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. @@ -203,7 +203,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); ElementClassHint classHint = processor.getHint(ElementClassHint.KEY); - final JavaPsiFacadeImpl facade = getFacade(); + final JavaPsiFacade facade = getFacade(); final Condition prefixMatcher = processor.getHint(JavaCompletionHints.NAME_FILTER); if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { @@ -295,8 +295,9 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya } } - final JavaPsiFacadeImpl facade = getFacade(); - for (PsiClass aClass : facade.findClasses(getQualifiedName() + ".package-info", allScope())) { + final JavaPsiFacade facade = getFacade(); + final GlobalSearchScope scope = allScope(); + for (PsiClass aClass : facade.findClasses(getQualifiedName() + ".package-info", scope)) { ContainerUtil.addIfNotNull(aClass.getModifierList(), list); } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java index 6578d5cb4f3e..8038317d6c61 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -58,10 +58,9 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC @Override @NotNull public PsiJavaCodeReferenceElement getBaseClassReference() { - final PsiJavaCodeReferenceElement result = - (PsiJavaCodeReferenceElement)getNode().findChildByRoleAsPsiElement(ChildRole.BASE_CLASS_REFERENCE); - assert result != null; - return result; + final PsiElement baseRef = getFirstChild(); + assert baseRef instanceof PsiJavaCodeReferenceElement : getText(); + return (PsiJavaCodeReferenceElement)baseRef; } @Override @@ -90,7 +89,7 @@ public class PsiAnonymousClassImpl extends PsiClassImpl implements PsiAnonymousC type = factory.createType(ref); } catch (IncorrectOperationException e) { - type = PsiClassType.getJavaLangObject(getManager(), getResolveScope()); + type = PsiType.getJavaLangObject(getManager(), getResolveScope()); } myCachedBaseType = new PatchedSoftReference(type); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java index 1c104816b082..da11f11ae200 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java @@ -272,8 +272,11 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava PsiElement lastParent, @NotNull PsiElement place) { assert isValid(); - - if (processor instanceof ClassResolverProcessor && isPhysical() && + + // TODO den remove + boolean allowCaching = true; + + if (allowCaching && processor instanceof ClassResolverProcessor && isPhysical() && (getUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING) == Boolean.TRUE || myResolveCache.hasUpToDateValue())) { final ClassResolverProcessor hint = (ClassResolverProcessor)processor; String name = hint.getName(state); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IncompatibleReturnType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IncompatibleReturnType.java new file mode 100644 index 000000000000..c6cc761e0358 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IncompatibleReturnType.java @@ -0,0 +1,20 @@ +abstract class F { + public abstract B f(A a); + + public final F> lazy() { + return new F>() { + public P1 f(final A a) { + return null; + } + }; + } + + private class TestClient extends F> { + public P1 f(final A a) { + return null; + } + } +} + +class P1 { +} \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors.log b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors.log new file mode 100644 index 000000000000..24d37739dc22 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/DeleteClassAfterCompileErrors/packageA/Server.class +End of files +Compiling files: +src/packageA/Server.java +End of files +Cleaning output files: +out/production/DeleteClassAfterCompileErrors/packageA/Client.class +End of files +Compiling files: +src/packageA/Client.java +End of files diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Client.java b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Client.java new file mode 100644 index 000000000000..fd6869be0e49 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Client.java @@ -0,0 +1,9 @@ +package packageA; + +public class Client { + + public void method(Server server) { + server.method(); + } + +} diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java new file mode 100644 index 000000000000..5168430764ac --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java @@ -0,0 +1,7 @@ +package packageA; + +public class Server { + public void method() { + System.out.println("Server.method"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java.new b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java.new new file mode 100644 index 000000000000..2dd0712564a5 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java.new @@ -0,0 +1,7 @@ +package packageA; + +public class Server { + public void method() { + System.out.println("Server.method"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java.remove1 b/java/java-tests/testData/compileServer/incremental/common/deleteClassAfterCompileErrors/src/packageA/Server.java.remove1 new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldAccessorsDfa.java b/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldAccessorsDfa.java index e166ce3f8cd7..8cf8bbdd8c2f 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldAccessorsDfa.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldAccessorsDfa.java @@ -9,7 +9,7 @@ public class BrokenAlignment { System.out.println(data.getText().hashCode()); } - data = new Data(null, null); + data = new Data(null, null); System.out.println(data.getText().hashCode()); if (data.inner() != null) { @@ -19,7 +19,7 @@ public class BrokenAlignment { System.out.println(data.inner().hashCode()); } - data = new Data(null, null); + data = new Data(null, null); System.out.println(data.inner().hashCode()); } } diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldsDfa.java b/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldsDfa.java index 8618bd0e1f66..0096d8266667 100644 --- a/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldsDfa.java +++ b/java/java-tests/testData/inspection/dataFlow/fixture/ChainedFinalFieldsDfa.java @@ -6,7 +6,7 @@ public class BrokenAlignment { System.out.println(data.text.hashCode()); } - data = new Data(null, null); + data = new Data(null, null); System.out.println(data.text.hashCode()); if (data.inner != null) { @@ -16,7 +16,7 @@ public class BrokenAlignment { System.out.println(data.inner.hashCode()); } - data = new Data(null, null); + data = new Data(null, null); System.out.println(data.inner.hashCode()); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 06941dbb4cba..9ed12bcdead6 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -148,6 +148,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA89771() throws Exception { doTest(false); } public void testIDEA89801() throws Exception { doTest(false); } public void testInconvertibleTypes() throws Exception { doTest(false); } + public void testIncompatibleReturnType() throws Exception { doTest(false); } public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy index ef0a53746c16..f3495c1e0438 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/FixDocCommentTest.groovy @@ -80,9 +80,418 @@ class Test { }''' ) } + + void testRemoveOneParameterFromMany() { + doTest( + initial: '''\ +class Test { + /** + * @param i + * @param j + * @param k + */ + void test(int i, int j) { + } +}''', + expected: '''\ +class Test { + /** + * @param i + * @param j + */ + void test(int i, int j) { + } +}''' + ) + } + + void testRemoveTheOnlyParameter() { + doTest( + initial: '''\ +class Test { + /** + * My description + * @param i + */ + void test() { + } +}''', + expected: '''\ +class Test { + /** + * My description + */ + void test() { + } +}''' + ) + } + + void testRemoveReturn() { + doTest( + initial: '''\ +class Test { + /** + * My description + * @return data + */ + void test() { + } +}''', + expected: '''\ +class Test { + /** + * My description + */ + void test() { + } +}''' + ) + } + + void testRemoveOneThrowsFromMany() { + doTest( + initial: '''\ +class MyException1 extends Exception {} +class MyException2 extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException1 text1 + * @throws MyException2 text2 + */ + void test(int i) throws MyException2 { + } +}''', + expected: '''\ +class MyException1 extends Exception {} +class MyException2 extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException2 text2 + */ + void test(int i) throws MyException2 { + } +}''' + ) + } + + void testRemoveTheOnlyThrows() { + doTest( + initial: '''\ +class MyException extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException text + */ + void test(int i) { + } +}''', + expected: '''\ +class MyException extends Exception {} + +class Test { + /** + * @param i my arg + */ + void test(int i) { + } +}''' + ) + } + + void testRemoveOneTypeParameterFromMany() { + doTest( + initial: '''\ +/** + * @param tDescription + * @param vDescription + */ +class Test { +}''', + expected: '''\ +/** + * @param vDescription + */ +class Test { +}''' + ) + } + + void testRemoveMultipleTypeParameter() { + doTest( + initial: '''\ +/** + * @param tDescription + * @param vDescription + */ +class Test { +}''', + expected: '''\ +/** + */ +class Test { +}''' + ) + } + + void testAddFirstParameter() { + doTest( + initial: '''\ +class Test { + /** + */ + void test(int i) { + } +}''', + expected: '''\ +class Test { + /** + * @param i + */ + void test(int i) { + } +}''' + ) + } + + void testAddMultipleParameter() { + doTest( + initial: '''\ +class Test { + /** + * @param i + */ + void test(int i, int j, int k) { + } +}''', + expected: '''\ +class Test { + /** + * @param i + * @param j + * @param k + */ + void test(int i, int j, int k) { + } +}''' + ) + } + + void testAddReturn() { + doTest( + initial: '''\ +class Test { + /** + */ + int test() { + } +}''', + expected: '''\ +class Test { + /** + * @return + */ + int test() { + } +}''' + ) + } + + void testAddFirstThrows() { + doTest( + initial: '''\ +class MyException extends Exception {} + +class Test { + /** + * @param i my arg + */ + void test(int i) throws MyException { + } +}''', + expected: '''\ +class MyException extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException + */ + void test(int i) throws MyException { + } +}''') + } + + void testAddNonFirstThrows() { + doTest( + initial: '''\ +class MyException1 extends Exception {} +class MyException2 extends Exception {} +class MyException3 extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException1 + */ + void test(int i) throws MyException1, MyException2, MyException3 { + } +}''', + expected: '''\ +class MyException1 extends Exception {} +class MyException2 extends Exception {} +class MyException3 extends Exception {} + +class Test { + /** + * @param i my arg + * @throws MyException1 + * @throws MyException2 + * @throws MyException3 + */ + void test(int i) throws MyException1, MyException2, MyException3 { + } +}''') + } + + void testAddFirstThrowsWhenEmptyReturnIsAvailable() { + doTest( + initial: '''\ +class MyException extends Exception {} + +class Test { + /** + * @return + */ + int test() throws MyException { + return 1; + } +}''', + expected: '''\ +class MyException extends Exception {} + +class Test { + /** + * @return + * @throws MyException + */ + int test() throws MyException { + return 1; + } +}''') + } + void testAddFirstTypeParameter() { + doTest( + initial: '''\ +/** + * My description + * @author me + */ +class Test { +}''', + expected: '''\ +/** + * My description + * @author me + * @param + */ +class Test { +}''') + } + + void testAddNonFirstTypeParameter() { + doTest( + initial: '''\ +/** + * My description + * @author me + * @param type description + */ +class Test { +}''', + expected: '''\ +/** + * My description + * @author me + * @param type description + * @param + */ +class Test { +}''') + } + + void _testCorrectParametersOrder() { + doTest( + initial: '''\ +class Test { + /** + * @param j + * @param k k description + * @param i + */ + public void test(int i, int j, int k) { + } +}''', + expected: '''\ +class Test { + /** + * @param i + * @param j + * @param k k description + */ + public void test(int i, int j, int k) { + } +}''' + ) + } + + void testCorrectTypeParametersOrder() { + // TODO den implement + } + + void testAllesZusammen() { + // TODO den implement + } + + void testNavigateToMissingParamDescription() { + doTest( + initial: '''\ +class Test { + /** + * @param i + */ + void test(int i) { + } +}''', + expected: '''\ +class Test { + /** + * @param i + */ + void test(int i) { + } +}''' + ) + } + + void testNavigateToMissingReturnDescription() { + // TODO den implement + } + + void testNavigateToMissingThrowsDescription() { + // TODO den implement + } + private def doTest(Map args) { configureFromFileText("${getTestName(false)}.java", args.initial) + myEditor.settings.virtualSpace = false executeAction(FixDocCommentAction.ACTION_ID) checkResultByText(args.expected) } diff --git a/java/java-tests/testSrc/com/intellij/psi/LibraryOrderTest.java b/java/java-tests/testSrc/com/intellij/psi/LibraryOrderTest.java index f1c7f06fd2c8..6a5218b6519d 100644 --- a/java/java-tests/testSrc/com/intellij/psi/LibraryOrderTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/LibraryOrderTest.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. + */ package com.intellij.psi; import com.intellij.JavaTestUtil; @@ -48,8 +63,7 @@ public class LibraryOrderTest extends PsiTestCase { public void testNavigation() throws Exception { setupPaths(); - final JavaPsiFacade psiManager = getJavaFacade(); - final PsiClass classA = psiManager.findClass("test.A"); + final PsiClass classA = getJavaFacade().findClass("test.A"); final PsiElement navigationElement = classA.getNavigationElement(); assertNotNull(navigationElement); assertTrue(navigationElement != classA); @@ -57,7 +71,7 @@ public class LibraryOrderTest extends PsiTestCase { } private void checkClassFromLib(String qualifiedName, String index) { - final PsiClass classA = (PsiClass)JavaPsiFacade.getInstance(myProject).findClass(qualifiedName).getNavigationElement(); + final PsiClass classA = (PsiClass)getJavaFacade().findClass(qualifiedName).getNavigationElement(); assertNotNull(classA); final PsiMethod[] methodsA = classA.getMethods(); assertEquals(1, methodsA.length); diff --git a/java/java-tests/testSrc/com/intellij/psi/TypesTest.java b/java/java-tests/testSrc/com/intellij/psi/TypesTest.java index 54b9c8cb6ecb..1ae10fadaeb1 100644 --- a/java/java-tests/testSrc/com/intellij/psi/TypesTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/TypesTest.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. + */ package com.intellij.psi; import com.intellij.openapi.application.ApplicationManager; @@ -5,6 +20,7 @@ import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.impl.JavaPsiFacadeEx; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtil; import com.intellij.testFramework.PsiTestUtil; @@ -34,7 +50,7 @@ public class TypesTest extends GenericsTestCase { } public void testSimpleStuff() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -67,7 +83,7 @@ public class TypesTest extends GenericsTestCase { } public void testRawTypes() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -93,7 +109,7 @@ public class TypesTest extends GenericsTestCase { } public void testSubstWithInheritor() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -123,7 +139,7 @@ public class TypesTest extends GenericsTestCase { } public void testSimpleRawTypeInMethodArg() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -156,8 +172,7 @@ public class TypesTest extends GenericsTestCase { public void testRawTypeInMethodArg() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); - final PsiClass classA = psiManager.findClass("A"); + final PsiClass classA = getJavaFacade().findClass("A"); assertNotNull(classA); final PsiMethod method = classA.getMethods()[0]; @@ -172,7 +187,7 @@ public class TypesTest extends GenericsTestCase { } public void testBoundedParams() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -191,7 +206,7 @@ public class TypesTest extends GenericsTestCase { } public void testRawTypeExtension() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -210,7 +225,7 @@ public class TypesTest extends GenericsTestCase { } public void testTypesInGenericClass() { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -226,8 +241,8 @@ public class TypesTest extends GenericsTestCase { assertEquals(typeT, type); } - public void testAssignableSubinheritor() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + public void testAssignableSubInheritor() throws Exception { + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classCollection = psiManager.findClass("test.Collection"); final PsiClass classList = psiManager.findClass("test.List"); @@ -242,7 +257,7 @@ public class TypesTest extends GenericsTestCase { } public void testComplexInheritance() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -259,7 +274,7 @@ public class TypesTest extends GenericsTestCase { } public void testListListInheritance() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -280,7 +295,7 @@ public class TypesTest extends GenericsTestCase { } public void testSpaceInTypeParameterList() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -294,7 +309,7 @@ public class TypesTest extends GenericsTestCase { } public void testMethodTypeParameter() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); @@ -325,7 +340,7 @@ public class TypesTest extends GenericsTestCase { } public void testRawArrayTypes() throws Exception { - final JavaPsiFacade psiManager = getJavaFacade(); + final JavaPsiFacadeEx psiManager = getJavaFacade(); final PsiElementFactory factory = psiManager.getElementFactory(); final PsiClass classA = psiManager.findClass("A"); assertNotNull(classA); diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java index ec7481a19a35..f8fdc1789a6d 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.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. + */ package com.intellij.psi.impl.source.tree.java; import com.intellij.openapi.application.ApplicationManager; @@ -19,6 +34,7 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase { check(); } + public void testRemoveBoundFromEnd() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -30,6 +46,7 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase { check(); } + public void testRemoveBoundFromMiddle() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); ApplicationManager.getApplication().runWriteAction(new Runnable() { @@ -45,20 +62,19 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase { public void testAddBoundInTheMiddle() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); final PsiReferenceList extendsList = typeParameter.getExtendsList(); - final JavaPsiFacade manager = getJavaFacade(); - final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); - assertNotNull(clonableClass); - final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + final PsiClass cloneableClass = getJavaFacade().findClass("java.lang.Cloneable"); + assertNotNull(cloneableClass); + final PsiJavaCodeReferenceElement reference = getJavaFacade().getElementFactory().createClassReferenceElement(cloneableClass); extendsList.addAfter(reference, extendsList.getReferenceElements()[0]); check(); } + public void testAddBoundInFront() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); final PsiReferenceList extendsList = typeParameter.getExtendsList(); - final JavaPsiFacade manager = getJavaFacade(); - final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); - assertNotNull(clonableClass); - final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + final PsiClass cloneableClass = getJavaFacade().findClass("java.lang.Cloneable"); + assertNotNull(cloneableClass); + final PsiJavaCodeReferenceElement reference = getJavaFacade().getElementFactory().createClassReferenceElement(cloneableClass); extendsList.addBefore(reference, extendsList.getReferenceElements()[0]); check(); } @@ -66,28 +82,23 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase { public void testAddBoundInEnd() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); final PsiReferenceList extendsList = typeParameter.getExtendsList(); - final JavaPsiFacade manager = getJavaFacade(); - final PsiClass clonableClass = manager.findClass("java.lang.Cloneable"); - assertNotNull(clonableClass); - final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + final PsiClass cloneableClass = getJavaFacade().findClass("java.lang.Cloneable"); + assertNotNull(cloneableClass); + final PsiJavaCodeReferenceElement reference = getJavaFacade().getElementFactory().createClassReferenceElement(cloneableClass); extendsList.addBefore(reference, null); check(); } - public void testAddBound() throws Exception { final PsiTypeParameter typeParameter = getTypeParameter(); final PsiReferenceList extendsList = typeParameter.getExtendsList(); - final JavaPsiFacade manager = getJavaFacade(); - final PsiClass clonableClass = manager.findClass(CommonClassNames.JAVA_LANG_RUNNABLE); - assertNotNull(clonableClass); - final PsiJavaCodeReferenceElement reference = manager.getElementFactory().createClassReferenceElement(clonableClass); + final PsiClass cloneableClass = getJavaFacade().findClass(CommonClassNames.JAVA_LANG_RUNNABLE); + assertNotNull(cloneableClass); + final PsiJavaCodeReferenceElement reference = getJavaFacade().getElementFactory().createClassReferenceElement(cloneableClass); extendsList.add(reference); check(); } - - private void check() throws Exception { outputFile(getTestName(true) + "_after.java"); } @@ -95,8 +106,7 @@ public class ExtendsBoundListTest extends LightCodeInsightTestCase { private PsiTypeParameter getTypeParameter() throws Exception { inputFile(getTestName(true) + ".java"); final PsiClass aClass = ((PsiJavaFile)getFile()).getClasses()[0]; - final PsiTypeParameter typeParameter = aClass.getTypeParameters()[0]; - return typeParameter; + return aClass.getTypeParameters()[0]; } private void outputFile(String filename) throws Exception { diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java index 0a601aa3d5dd..b91df431fe78 100644 --- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveMethodTest.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. + */ package com.intellij.psi.resolve; import com.intellij.openapi.projectRoots.Sdk; @@ -267,7 +282,7 @@ public class ResolveMethodTest extends ResolveTestCase { PsiReference ref = configureByFile("method/" + getTestName(false) + ".java"); // just assume this is called by some highlighting inspection/intention/pass before the resolve - JavaPsiFacade.getInstance(getProject()).findClass("NN").getAllMethods(); + getJavaFacade().findClass("NN").getAllMethods(); PsiElement target = ref.resolve(); assertInstanceOf(target, PsiMethod.class); diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java index e081da9e9f8d..0aa3369511d0 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -31,7 +31,7 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; -import com.intellij.psi.impl.JavaPsiFacadeImpl; +import com.intellij.psi.impl.JavaPsiFacadeEx; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.cache.impl.id.IdIndex; import com.intellij.psi.impl.cache.impl.todo.TodoIndex; @@ -181,7 +181,7 @@ public class UpdateCacheTest extends PsiTestCase{ assertNotNull(myProject); myPsiManager = (PsiManagerImpl) PsiManager.getInstance(myProject); - myJavaFacade = (JavaPsiFacadeImpl) JavaPsiFacade.getInstance(myProject); + myJavaFacade = JavaPsiFacadeEx.getInstanceEx(myProject); objectClass = myJavaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(getProject())); assertNotNull(objectClass); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java b/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java index 8f7af90edbce..51a5acfbfa63 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.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. + */ package com.intellij.refactoring; import com.intellij.codeInsight.CodeInsightTestCase; @@ -9,8 +24,8 @@ import com.intellij.testFramework.PsiTestUtil; import org.jetbrains.annotations.Nullable; /** - * User: anna - * Date: Aug 31, 2010 + * @author anna + * @since Aug 31, 2010 */ public class DndMoveTest extends CodeInsightTestCase { @Override @@ -23,7 +38,7 @@ public class DndMoveTest extends CodeInsightTestCase { @Nullable @Override public PsiElement compute() { - return JavaPsiFacade.getInstance(getProject()).findClass("d.MyClass"); + return getJavaFacade().findClass("d.MyClass"); } }, true); } @@ -33,12 +48,11 @@ public class DndMoveTest extends CodeInsightTestCase { @Nullable @Override public PsiElement compute() { - return JavaPsiFacade.getInstance(getProject()).findClass("d.Second"); + return getJavaFacade().findClass("d.Second"); } }, false); } - private void doTest(final String targetDirName, final Computable source, final boolean expected) throws Exception { String testName = getTestName(true); String root = getTestDataPath() + getTestRoot() + testName; diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java index 66942460a50a..bd70e5dafa98 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + /* * User: anna * Date: 20-Aug-2008 @@ -138,7 +154,7 @@ public class IntroduceParameterObjectTest extends MultiFileTestCase{ @Override public ParameterTablePanel.VariableData[] fun(PsiMethod psiMethod) { final PsiParameter parameter = psiMethod.getParameterList().getParameters()[0]; - final PsiClass collectionClass = JavaPsiFacade.getInstance(getProject()).findClass(CommonClassNames.JAVA_UTIL_COLLECTION); + final PsiClass collectionClass = getJavaFacade().findClass(CommonClassNames.JAVA_UTIL_COLLECTION); final ParameterTablePanel.VariableData variableData = new ParameterTablePanel.VariableData(parameter, JavaPsiFacade.getElementFactory(getProject()).createType(collectionClass)); variableData.name = parameter.getName(); diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java index e3af5151d751..2bbee1af264e 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.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. @@ -27,8 +27,8 @@ import org.jetbrains.annotations.NonNls; import java.io.IOException; /** - * User: anna - * Date: 11/4/11 + * @author anna + * @since 11/4/11 */ public class InlineLibraryMethodTest extends RefactoringTestCase { @Override @@ -45,7 +45,7 @@ public class InlineLibraryMethodTest extends RefactoringTestCase { @NonNls String fileName = "/refactoring/inlineMethod/" + getTestName(false) + ".java"; configureByFile(fileName); - PsiClass fileClass = JavaPsiFacade.getInstance(getProject()).findClass("mycompany.File"); + PsiClass fileClass = getJavaFacade().findClass("mycompany.File"); assertNotNull(fileClass); final PsiFile file = fileClass.getContainingFile(); ApplicationManager.getApplication().runWriteAction(new Runnable() { diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java index d168a632b97c..e5d8c43a8c0a 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/JavaCodeInsightTestFixture.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -15,19 +15,17 @@ */ package com.intellij.testFramework.fixtures; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiPackage; +import com.intellij.psi.impl.JavaPsiFacadeEx; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.io.IOException; - /** * @author yole */ public interface JavaCodeInsightTestFixture extends CodeInsightTestFixture { - JavaPsiFacade getJavaFacade(); + JavaPsiFacadeEx getJavaFacade(); PsiClass addClass(@NotNull @NonNls final String classText); diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java index eb2b6548fa86..7ebb31b1b1b2 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaCodeInsightTestFixtureImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.impl.JavaPsiFacadeEx; import com.intellij.psi.impl.PsiModificationTrackerImpl; import com.intellij.psi.search.ProjectScope; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; @@ -36,9 +37,9 @@ public class JavaCodeInsightTestFixtureImpl extends CodeInsightTestFixtureImpl i } @Override - public JavaPsiFacade getJavaFacade() { + public JavaPsiFacadeEx getJavaFacade() { assertInitialized(); - return JavaPsiFacade.getInstance(getProject()); + return JavaPsiFacadeEx.getInstanceEx(getProject()); } @Override diff --git a/java/testFramework/testFramework-java.iml b/java/testFramework/testFramework-java.iml index bcd446ef0028..d37693273732 100644 --- a/java/testFramework/testFramework-java.iml +++ b/java/testFramework/testFramework-java.iml @@ -15,7 +15,7 @@ - + diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java index 6ada6906e537..999ca279e30d 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java @@ -821,7 +821,7 @@ public class IncProjectBuilder { if (!outputs.isEmpty()) { context.processMessage(new FileDeletedEvent(outputs)); } - srcToOut.remove(srcPath); + srcToOut.update(srcPath, Collections.emptyList()); } return true; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java index 1370728b1800..13d9281c38f4 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java @@ -2,10 +2,10 @@ package org.jetbrains.jps.incremental.artifacts; import com.intellij.util.SmartList; import com.intellij.util.io.DataExternalizer; -import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.IOUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.jps.incremental.storage.AbstractStateStorage; +import org.jetbrains.jps.incremental.storage.PathStringDescriptor; import java.io.*; import java.util.List; @@ -42,7 +42,7 @@ public class ArtifactOutputToSourceMapping extends AbstractStateStorage currentPaths = new HashSet(); + final Set currentPaths = new THashSet(FileUtil.FILE_HASHING_STRATEGY); fsState.clearDeletedPaths(myTarget); markDirtyFiles(builder, dataManager, currentPaths, false); final SourceToOutputMapping mapping = dataManager.getSourceToOutputMap(myTarget); final Iterator iterator = mapping.getKeysIterator(); while (iterator.hasNext()) { String path = iterator.next(); - File file = new File(path); - if (!currentPaths.contains(path)) { + File file = new File(FileUtil.toSystemDependentName(path)); + if (!currentPaths.contains(file)) { fsState.registerDeleted(myTarget, file, myProjectDescriptor.timestamps.getStorage()); } } } } - private void markDirtyFiles(ArtifactInstructionsBuilder builder, BuildDataManager dataManager, @Nullable Set currentPaths, + private void markDirtyFiles(ArtifactInstructionsBuilder builder, BuildDataManager dataManager, @Nullable Set currentPaths, final boolean forceMarkDirty) throws IOException { for (Pair pair : builder.getInstructions()) { ArtifactRootDescriptor descriptor = pair.getFirst(); @@ -89,7 +93,7 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { } private void processRecursively(File file, ArtifactRootDescriptor descriptor, BuildDataManager dataManager, SourceFileFilter filter, - @Nullable Set currentPaths, final boolean forceMarkDirty) throws IOException { + @Nullable Set currentPaths, final boolean forceMarkDirty) throws IOException { final String filePath = FileUtil.toSystemIndependentName(FileUtil.toCanonicalPath(file.getPath())); if (!filter.accept(filePath, dataManager)) return; @@ -103,7 +107,7 @@ public class ArtifactSourceFilesState extends CompositeStorageOwner { } else { if (currentPaths != null) { - currentPaths.add(filePath); + currentPaths.add(file); } if (forceMarkDirty || myProjectDescriptor.timestamps.getStorage().getStamp(file, myTarget) != FileSystemUtil.lastModified(file)) { myProjectDescriptor.fsState.markDirty(null, file, descriptor, myProjectDescriptor.timestamps.getStorage()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java index e55c3e7dff1e..32532272c0c2 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java @@ -100,7 +100,7 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { } } - Set changedOutputPaths = new THashSet(); + Set changedOutputPaths = new THashSet(FileUtil.PATH_HASHING_STRATEGY); for (Map.Entry> entry : filesToRecompile.entrySet()) { int rootIndex = ((ArtifactRootDescriptor)entry.getKey()).getRootIndex(); for (File file : entry.getValue()) { @@ -110,6 +110,7 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { if (outputPaths != null) { changedOutputPaths.addAll(outputPaths); for (String outputPath : outputPaths) { + filesToDelete.putValue(outputPath, sourcePath); final List sources = outSrcMapping.getState(outputPath); if (sources != null) { for (ArtifactOutputToSourceMapping.SourcePathAndRootIndex source : sources) { @@ -177,7 +178,7 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { } Set paths = filesToProcess.get(rootIndex); if (paths == null) { - paths = new THashSet(); + paths = new THashSet(FileUtil.PATH_HASHING_STRATEGY); filesToProcess.put(rootIndex, paths); } paths.add(path); @@ -190,8 +191,8 @@ public class IncArtifactBuilder extends ProjectLevelBuilder { context.processMessage(new ProgressMessage("Deleting outdated files...")); int notDeletedFilesCount = 0; - final THashSet notDeletedPaths = new THashSet(); - final THashSet deletedPaths = new THashSet(); + final THashSet notDeletedPaths = new THashSet(FileUtil.PATH_HASHING_STRATEGY); + final THashSet deletedPaths = new THashSet(FileUtil.PATH_HASHING_STRATEGY); for (String filePath : filesToDelete.keySet()) { if (notDeletedPaths.contains(filePath)) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java index a8f666efa004..c80dea73d194 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java @@ -16,13 +16,16 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; /** @noinspection SynchronizationOnLocalVariableOrMethodParameter*/ final class FilesDelta { private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.fs.FilesDelta"); - private final Set myDeletedPaths = Collections.synchronizedSet(new HashSet()); + private final Set myDeletedPaths = Collections.synchronizedSet(new THashSet(FileUtil.PATH_HASHING_STRATEGY)); private final Map> myFilesToRecompile = Collections.synchronizedMap(new HashMap>()); public void save(DataOutput out) throws IOException { @@ -155,7 +158,9 @@ final class FilesDelta { public Set getAndClearDeletedPaths() { synchronized (myDeletedPaths) { try { - return new HashSet(myDeletedPaths); + final THashSet _paths = new THashSet(FileUtil.PATH_HASHING_STRATEGY); + _paths.addAll(myDeletedPaths); + return _paths; } finally { myDeletedPaths.clear(); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java new file mode 100644 index 000000000000..abf1ee1b23d3 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/PathStringDescriptor.java @@ -0,0 +1,19 @@ +package org.jetbrains.jps.incremental.storage; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.io.EnumeratorStringDescriptor; + +/** +* @author nik +*/ +public class PathStringDescriptor extends EnumeratorStringDescriptor { + @Override + public int getHashCode(String value) { + return FileUtil.pathHashCode(value); + } + + @Override + public boolean isEqual(String val1, String val2) { + return FileUtil.pathsEqual(val1, val2); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMapping.java index a681cce9be57..a378ea417e51 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMapping.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/SourceToOutputMapping.java @@ -2,7 +2,6 @@ package org.jetbrains.jps.incremental.storage; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.io.DataExternalizer; -import com.intellij.util.io.EnumeratorStringDescriptor; import com.intellij.util.io.IOUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,17 +21,7 @@ import java.util.List; public final class SourceToOutputMapping extends AbstractStateStorage> { public SourceToOutputMapping(File storePath) throws IOException { - super(storePath, new EnumeratorStringDescriptor() { - @Override - public int getHashCode(String value) { - return FileUtil.pathHashCode(value); - } - - @Override - public boolean isEqual(String val1, String val2) { - return FileUtil.pathsEqual(val1, val2); - } - }, new StringCollectionExternalizer()); + super(storePath, new PathStringDescriptor(), new StringCollectionExternalizer()); } @Override diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java index 9a36f6d40ee7..84da017d2899 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java @@ -36,6 +36,12 @@ public class CommonTest extends IncrementalTestCase { doTest(); } + public void testDeleteClassAfterCompileErrors() throws Exception { + setupInitialProject(); + + doTestBuild(2); + } + public void testDeleteClassPackageDoesntMatchRoot() throws Exception { doTest(); } diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index fa227455141b..23ed20d4bdce 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -97,12 +97,15 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { } } - private void modify() { + private void modify(int stage) { + final String removedSuffix = stage == 0? ".remove" : ".remove" + stage; + final String newSuffix = stage == 0? ".new" : ".new" + stage; + FileUtil.processFilesRecursively(baseDir, new Processor() { @Override public boolean process(File file) { - if (file.getName().endsWith(".remove")) { - FileUtil.delete(getTargetFile(file, ".remove")); + if (file.getName().endsWith(removedSuffix)) { + FileUtil.delete(getTargetFile(file, removedSuffix)); } return true; } @@ -111,8 +114,8 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { @Override public boolean process(File file) { try { - if (file.getName().endsWith(".new")) { - FileUtil.copyContent(file, getTargetFile(file, ".new")); + if (file.getName().endsWith(newSuffix)) { + FileUtil.copyContent(file, getTargetFile(file, newSuffix)); } } catch (IOException e) { @@ -121,6 +124,13 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { return true; } }); + if (Utils.TIMESTAMP_ACCURACY > 1) { + try { + Thread.sleep(Utils.TIMESTAMP_ACCURACY); + } + catch (InterruptedException ignored) { + } + } } private File getTargetFile(File sourceFile, final String suffix) { @@ -133,6 +143,12 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { } public BuildResult doTest() { + setupInitialProject(); + + return doTestBuild(1); + } + + protected void setupInitialProject() { if (new File(workDir, ".idea").exists()) { getOrCreateJdk(); loadProject(workDir.getAbsolutePath()); @@ -140,8 +156,6 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { else { addModule(); } - - return doTestBuild(); } protected JpsModule addModule() { @@ -153,30 +167,31 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { return addModule(moduleName, new String[]{srcPath}, null, getOrCreateJdk()); } - protected BuildResult doTestBuild() { - final TestJavaBuilderLogger - javaBuilderLogger = new TestJavaBuilderLogger(FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/"); - final ProjectDescriptor - projectDescriptor = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), javaBuilderLogger)); + protected BuildResult doTestBuild(int makesCount) { + final TestJavaBuilderLogger builderLogger = new TestJavaBuilderLogger(FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/"); + final ProjectDescriptor pd = createProjectDescriptor(new BuildLoggingManager(new ArtifactBuilderLoggerImpl(), builderLogger)); try { - doBuild(projectDescriptor, createAllModulesScope(true), false, true, false).assertSuccessful(); + doBuild(pd, createAllModulesScope(true), false, true, false).assertSuccessful(); - modify(); - if (Utils.TIMESTAMP_ACCURACY > 1) { - try { - Thread.sleep(Utils.TIMESTAMP_ACCURACY); - } - catch (InterruptedException ignored) { - } + BuildResult result = null; + + for (int idx = 0; idx < makesCount; idx++) { + modify(idx); + result = doBuild(pd, createAllModulesScope(false), true, false, false); } - - BuildResult result = doBuild(projectDescriptor, createAllModulesScope(false), true, false, false); - + assertNotNull(result); + final ByteArrayOutputStream makeDump = new ByteArrayOutputStream(); if (result.isSuccessful()) { - projectDescriptor.dataManager.getMappings().toStream(new PrintStream(makeDump)); + final PrintStream stream = new PrintStream(makeDump); + try { + pd.dataManager.getMappings().toStream(stream); + } + finally { + stream.close(); + } } makeDump.close(); @@ -186,19 +201,25 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { logFile = new File(baseDir, "build.log"); } final String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(logFile)); - final String actual = javaBuilderLogger.myLog.toString(); + final String actual = builderLogger.myLog.toString(); assertEquals(expected, actual); if (result.isSuccessful()) { - doBuild(projectDescriptor, createAllModulesScope(true), false, true, false).assertSuccessful(); - + doBuild(pd, createAllModulesScope(true), false, true, false).assertSuccessful(); + final ByteArrayOutputStream rebuildDump = new ByteArrayOutputStream(); - projectDescriptor.dataManager.getMappings().toStream(new PrintStream(rebuildDump)); + final PrintStream stream = new PrintStream(rebuildDump); + try { + pd.dataManager.getMappings().toStream(stream); + } + finally { + stream.close(); + } rebuildDump.close(); - + assertEquals(rebuildDump.toString(), makeDump.toString()); } return result; @@ -207,7 +228,7 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { throw new RuntimeException(e); } finally { - projectDescriptor.release(); + pd.release(); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java index b633ef44d007..20efb6f4b270 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MarkDirtyTest.java @@ -26,7 +26,7 @@ public class MarkDirtyTest extends IncrementalTestCase { addTestRoot(module, "testSrc"); JpsLibrary library = addLibrary("lib/a.jar"); JpsModuleRootModificationUtil.addDependency(module, library, JpsJavaDependencyScope.TEST, false); - doTestBuild().assertSuccessful(); + doTestBuild(1).assertSuccessful(); } public void testTransitiveRecompile() { @@ -38,6 +38,6 @@ public class MarkDirtyTest extends IncrementalTestCase { JpsModule lib = addModule("lib", "lib/src"); addTestRoot(lib, "lib/testSrc"); JpsModuleRootModificationUtil.addDependency(util, lib); - doTestBuild().assertSuccessful(); + doTestBuild(1).assertSuccessful(); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java index 15ee1debefd9..f1fa3b80566b 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java @@ -28,7 +28,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { change(aFile, "a2"); buildAll(); - assertCopied("aaa.txt"); + assertDeletedAndCopied("out/artifacts/a/x.jar", "aaa.txt"); assertOutput(a, fs().archive("x.jar").file("aaa.txt", "a2")); buildAllAndAssertUpToDate(); @@ -55,7 +55,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { change(cFile, "c2"); buildAll(); - assertCopied("c.txt"); + assertDeletedAndCopied("out/artifacts/a/a.jar", "c.txt"); assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.txt", "c2")); buildAllAndAssertUpToDate(); @@ -74,7 +74,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { change(xFile, "2"); buildAll(); - assertCopied("x.txt"); + assertDeletedAndCopied("out/artifacts/a/junit.jar", "x.txt"); assertOutput(a, fs().archive("junit.jar").file("x.txt", "2")); buildAllAndAssertUpToDate(); @@ -99,7 +99,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { change(jarFile, "321"); buildAll(); - assertCopied("lib/jdom.jar"); + assertDeletedAndCopied("out/artifacts/a/jdom.jar", "lib/jdom.jar"); assertOutput(a, fs().file("jdom.jar", "321")); buildAllAndAssertUpToDate(); @@ -122,7 +122,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { change(firstFile, "first2"); buildAll(); - assertCopied("d1/xxx.txt"); + assertDeletedAndCopied("out/artifacts/a/ddd/xxx.txt", "d1/xxx.txt"); assertOutput(a, fs().dir("ddd").file("xxx.txt", "first2")); buildAllAndAssertUpToDate(); @@ -170,7 +170,7 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase { final String manifestText2 = "Manifest-Version: 1.0\r\nMain-Class: B\r\n\r\n"; change(manifest, manifestText2); buildAll(); - assertCopied("d/MANIFEST.MF", "a.txt"); + assertDeletedAndCopied("out/artifacts/a/a.jar", "d/MANIFEST.MF", "a.txt"); assertOutput(a, fs().archive("a.jar").dir("META-INF").file("MANIFEST.MF", manifestText2).file("a.txt")); buildAllAndAssertUpToDate(); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java index 9c6a75277964..7086206c392f 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java @@ -27,7 +27,10 @@ import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.JpsBuildTestCase; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.cmdline.ProjectDescriptor; -import org.jetbrains.jps.incremental.*; +import org.jetbrains.jps.incremental.BuildLoggingManager; +import org.jetbrains.jps.incremental.CompileScope; +import org.jetbrains.jps.incremental.CompileScopeImpl; +import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.incremental.java.JavaBuilderLoggerImpl; import org.jetbrains.jps.model.JpsDummyElement; import org.jetbrains.jps.model.JpsElementFactory; @@ -211,7 +214,11 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { } protected void assertDeletedAndCopied(String deletedPath, String... copiedPaths) { - assertSameElements(myArtifactBuilderLogger.myDeletedFilePaths, deletedPath); + assertDeletedAndCopied(new String[]{deletedPath}, copiedPaths); + } + + protected void assertDeletedAndCopied(String[] deletedPaths, String... copiedPaths) { + assertSameElements(myArtifactBuilderLogger.myDeletedFilePaths, deletedPaths); assertSameElements(myArtifactBuilderLogger.myCopiedFilePaths, copiedPaths); } @@ -248,7 +255,10 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase { try { File file = new File(FileUtil.toSystemDependentName(path)); assertTrue("File " + file.getAbsolutePath() + " doesn't exist", file.exists()); - FileUtil.rename(file, new File(file.getParentFile(), newName)); + final File tempFile = new File(file.getParentFile(), "__" + newName); + FileUtil.rename(file, tempFile); + FileUtil.copyContent(tempFile, new File(file.getParentFile(), newName)); + FileUtil.delete(tempFile); } catch (IOException e) { throw new RuntimeException(e); diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java index 7b6c30280a32..f00c5d965ddc 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/IncrementalArtifactBuildingTest.java @@ -37,7 +37,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { change(file1, "xxx"); buildAll(); - assertCopied("dir/a.txt"); + assertDeletedAndCopied("out/artifacts/a/a.txt", "dir/a.txt"); assertOutput(a, fs().file("a.txt", "xxx").file("b.txt", "bbb")); buildAllAndAssertUpToDate(); } @@ -66,7 +66,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { change(file1, "xxx"); buildAll(); - assertCopied("dir/a.txt", "dir/b.txt"); + assertDeletedAndCopied("out/artifacts/a/a.jar", "dir/a.txt", "dir/b.txt"); assertOutput(a, fs().archive("a.jar").file("a.txt", "xxx").file("b.txt", "bbb")); buildAllAndAssertUpToDate(); } @@ -96,9 +96,9 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { buildAllAndAssertUpToDate(); change(file); - buildArtifacts(a1); assertCopied("file.txt"); + buildArtifacts(a1); assertDeletedAndCopied("out/artifacts/a1/dir/file.txt", "file.txt"); buildArtifacts(a1); assertUpToDate(); - buildArtifacts(a2); assertCopied("file.txt"); + buildArtifacts(a2); assertDeletedAndCopied("out/artifacts/a2/dir2/file.txt", "file.txt"); buildArtifacts(a2); assertUpToDate(); buildArtifacts(a1); assertUpToDate(); buildAllAndAssertUpToDate(); @@ -115,7 +115,7 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase { buildAll(); change(file1); buildAll(); - assertCopied("a/a.txt"); + assertDeletedAndCopied("out/artifacts/a/x.jar", "a/a.txt"); } public void testRenameFile() throws Exception { diff --git a/platform/core-api/src/com/intellij/psi/tree/IElementType.java b/platform/core-api/src/com/intellij/psi/tree/IElementType.java index a731db42ab14..1726c27832ed 100644 --- a/platform/core-api/src/com/intellij/psi/tree/IElementType.java +++ b/platform/core-api/src/com/intellij/psi/tree/IElementType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -35,12 +35,7 @@ import java.util.List; public class IElementType { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.tree.IElementType"); - public static final short FIRST_TOKEN_INDEX = 1; - private static short ourCounter = FIRST_TOKEN_INDEX; - - private static final short MAX_INDEXED_TYPES = 15000; - private static final List ourRegistry = new ArrayList(700); - private final short myIndex; + public static final IElementType[] EMPTY_ARRAY = new IElementType[0]; /** * Default enumeration predicate which matches all token types. @@ -54,34 +49,16 @@ public class IElementType { } }; - static int getAllocatedTypesCount() { - return ourCounter; - } + public static final short FIRST_TOKEN_INDEX = 1; + public static final short MAX_INDEXED_TYPES = 15000; - public static final IElementType[] EMPTY_ARRAY = new IElementType[0]; - private final String myDebugName; + private static short ourCounter = FIRST_TOKEN_INDEX; + private static final List ourRegistry = new ArrayList(700); + + private final short myIndex; + @NotNull private final String myDebugName; @NotNull private final Language myLanguage; - /** - * Enumerates all registered token types which match the specified predicate. - * - * @param p the predicate which should be matched by the element types. - * @return the array of matching element types. - */ - public static IElementType[] enumerate(Predicate p) { - List matches = new ArrayList(); - IElementType[] copy; - synchronized (ourRegistry) { - copy = ourRegistry.toArray(new IElementType[ourRegistry.size()]); - } - for (IElementType value : copy) { - if (p.matches(value)) { - matches.add(value); - } - } - return matches.toArray(new IElementType[matches.size()]); - } - /** * Creates and registers a new element type for the specified language. * @@ -92,7 +69,7 @@ public class IElementType { this(debugName, language, true); } - protected IElementType(String debugName, Language language, final boolean register) { + protected IElementType(@NotNull @NonNls String debugName, @Nullable Language language, boolean register) { myDebugName = debugName; myLanguage = language == null ? Language.ANY : language; if (register) { @@ -132,15 +109,41 @@ public class IElementType { return myDebugName; } + /** + * Controls whitespace balancing behavior of PsiBuilder. + *

By default, empty composite elements (containing no children) are bounded to the right (previous) neighbour, forming following tree: + *

+   *  [previous_element]
+   *  [whitespace]
+   *  [empty_element]
+   *    <empty>
+   *  [next_element]
+   * 
+ *

Left-bound elements are bounded to the left (next) neighbour instead: + *

+   *  [previous_element]
+   *  [empty_element]
+   *    <empty>
+   *  [whitespace]
+   *  [next_element]
+   * 
+ *

See com.intellij.lang.impl.PsiBuilderImpl.prepareLightTree() for details. + * @return true if empty elements of this type should be bound to the left. + */ + public boolean isLeftBound() { + return false; + } + /** * Returns the element type registered at the specified index. * * @param idx the index for which the element type should be returned. * @return the element type at the specified index. + * @throws IndexOutOfBoundsException if the index is out of registered elements' range. */ public static IElementType find(short idx) { synchronized (ourRegistry) { - if (idx == 0) return ourRegistry.get(0); // We've changed FIRST_TOKEN_INDEX from 0 to 1. This is just for old plugins to avoid crashes. + if (idx == 0) return ourRegistry.get(0); // We've changed FIRST_TOKEN_INDEX from 0 to 1. This is just for old plugins to avoid crashes. return ourRegistry.get(idx - FIRST_TOKEN_INDEX); } } @@ -154,28 +157,29 @@ public class IElementType { boolean matches(IElementType type); } + static short getAllocatedTypesCount() { + return ourCounter; + } + /** - * Controls whitespace balancing behavior of PsiBuilder. - *

By default, empty composite elements (containing no children) are bounded to the right neighbour, forming following tree: - *

-   *  [previous_element]
-   *  [whitespace]
-   *  [empty_element]
-   *    <empty>
-   *  [next_element]
-   * 
- *

Left-bound elements are bounded to the left neighbour instead: - *

-   *  [previous_element]
-   *  [empty_element]
-   *    <empty>
-   *  [whitespace]
-   *  [next_element]
-   * 
- *

See {@linkplain com.intellij.lang.impl.PsiBuilderImpl#prepareLightTree()} for details. - * @return true if empty elements of this type should be bound to the left. + * Enumerates all registered token types which match the specified predicate. + * + * @param p the predicate which should be matched by the element types. + * @return the array of matching element types. */ - public boolean isLeftBound() { - return false; + @NotNull + public static IElementType[] enumerate(@NotNull Predicate p) { + IElementType[] copy; + synchronized (ourRegistry) { + copy = ourRegistry.toArray(new IElementType[ourRegistry.size()]); + } + + List matches = new ArrayList(); + for (IElementType value : copy) { + if (p.matches(value)) { + matches.add(value); + } + } + return matches.toArray(new IElementType[matches.size()]); } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/psi/tree/TokenSet.java b/platform/core-api/src/com/intellij/psi/tree/TokenSet.java index 1628366f9f16..700bad28faa4 100644 --- a/platform/core-api/src/com/intellij/psi/tree/TokenSet.java +++ b/platform/core-api/src/com/intellij/psi/tree/TokenSet.java @@ -16,6 +16,9 @@ package com.intellij.psi.tree; import com.intellij.openapi.diagnostic.LogUtil; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -23,51 +26,105 @@ import java.util.Arrays; * A set of element types. */ public class TokenSet { - public static final TokenSet EMPTY = new TokenSet(); + public static final TokenSet EMPTY = new TokenSet(Short.MAX_VALUE, (short)0) { + @Override public boolean contains(IElementType t) { return false; } + }; - private final boolean[] mySet = new boolean[IElementType.getAllocatedTypesCount()] ; + private final short myShift, myMax, myTop; + private final long[] myWords; private volatile IElementType[] myTypes; + private TokenSet(short shift, short max) { + myShift = shift; + myMax = max; + myTop = IElementType.getAllocatedTypesCount(); + final int size = (max >> 6) + 1 - shift; + myWords = size > 0 ? new long[size] : ArrayUtil.EMPTY_LONG_ARRAY; + } + + private boolean get(int index) { + final int wordIndex = (index >> 6) - myShift; + return wordIndex >= 0 && wordIndex < myWords.length && (myWords[wordIndex] & (1l << index)) != 0; + } + + /** + * Checks if the specified element type is contained in the set. + * + * @param t the element type to search for. + * @return true if the element type is found in the set, false otherwise. + */ + public boolean contains(@Nullable IElementType t) { + if (t == null) return false; + final short i = t.getIndex(); + return 0 <= i && i <= myMax && get(i); + } + /** * Returns the array of element types contained in the set. * * @return the contents of the set. */ + @NotNull public IElementType[] getTypes() { IElementType[] types = myTypes; - if (types == null) { - int elementCount = 0; - for (boolean bit : mySet) { - if (bit) elementCount++; - } - types = new IElementType[elementCount]; - int count = 0; - for (short i = IElementType.FIRST_TOKEN_INDEX; i < mySet.length; i++) { - if (mySet[i]) { - types[count++] = IElementType.find(i); + if (types == null) { + if (myWords.length > 0) { + int elementCount = 0; + for (long word : myWords) { + elementCount += Long.bitCount(word); + } + + types = new IElementType[elementCount]; + int count = 0; + for (short i = (short)(myShift << 6); i <= myMax; i++) { + if (get(i)) { + types[count++] = IElementType.find(i); + } } } - + else { + types = IElementType.EMPTY_ARRAY; + } + myTypes = types; } return types; } + @Override + public String toString() { + return Arrays.toString(getTypes()); + } + /** * Returns a new token set containing the specified element types. * * @param types the element types contained in the set. * @return the new token set. */ + @NotNull public static TokenSet create(IElementType... types) { - TokenSet set = new TokenSet(); + if (types.length == 0) return EMPTY; + + short min = Short.MAX_VALUE, max = 0; for (IElementType type : types) { if (type != null) { final short index = type.getIndex(); assert index >= 0 : "Unregistered elements are not allowed here: " + LogUtil.objectAndClass(type); - set.mySet[index] = true; + if (min > index) min = index; + if (max < index) max = index; + } + } + + final short shift = (short)(min >> 6); + final TokenSet set = new TokenSet(shift, max); + for (IElementType type : types) { + if (type != null) { + final short index = type.getIndex(); + final int wordIndex = (index >> 6) - shift; + set.myWords[wordIndex] |= (1l << index); } } return set; @@ -79,12 +136,21 @@ public class TokenSet { * @param sets the token sets to unite. * @return the new token set. */ - public static TokenSet orSet(TokenSet... sets) { - TokenSet newSet = new TokenSet(); + @NotNull + public static TokenSet orSet(@NotNull TokenSet... sets) { + if (sets.length == 0) return EMPTY; + + short shift = sets[0].myShift, max = sets[0].myMax; + for (int i = 1; i < sets.length; i++) { + if (shift > sets[i].myShift) shift = sets[i].myShift; + if (max < sets[i].myMax) max = sets[i].myMax; + } + + final TokenSet newSet = new TokenSet(shift, max); for (TokenSet set : sets) { - for (int i = 0; i < newSet.mySet.length; i++) { - if (i >= set.mySet.length) break; - newSet.mySet[i] |= set.mySet[i]; + final int shiftDiff = set.myShift - newSet.myShift; + for (int i = 0; i < set.myWords.length; i++) { + newSet.myWords[i + shiftDiff] |= set.myWords[i]; } } return newSet; @@ -97,51 +163,47 @@ public class TokenSet { * @param b the second token set to intersect. * @return the new token set. */ - public static TokenSet andSet(TokenSet a, TokenSet b) { - TokenSet set = new TokenSet(); - final boolean[] aSet = a.mySet; - final boolean[] bSet = b.mySet; - final boolean[] newSet = set.mySet; - final int aLen = aSet.length; - final int bLen = bSet.length; - final int andSize = Math.max(newSet.length, Math.max(aLen, bLen)); - - for (int i = 0; i < andSize; i++) { - newSet[i] = (i < aLen && aSet[i]) && (i < bLen && bSet[i]); + @NotNull + public static TokenSet andSet(@NotNull TokenSet a, @NotNull TokenSet b) { + final TokenSet newSet = new TokenSet((short)Math.min(a.myShift, b.myShift), (short)Math.max(a.myMax, b.myMax)); + for (int i = 0; i < newSet.myWords.length; i++) { + final int ai = newSet.myShift - a.myShift + i, bi = newSet.myShift - b.myShift + i; + newSet.myWords[i] = (0 <= ai && ai < a.myWords.length ? a.myWords[ai] : 0l) & (0 <= bi && bi < b.myWords.length ? b.myWords[bi] : 0l); } - return set; + return newSet; } /** - * Checks if the specified element type is contained in the set. + * Returns a token set containing a result of "set subtraction" of set B from set A. * - * @param t the element type to search for. - * @return true if the element type is found in the set, false otherwise. + * @param a the basic token set. + * @param b the token set to subtract. + * @return the new token set. */ - public boolean contains(IElementType t) { - if (t == null) return false; - final short i = t.getIndex(); - return 0 <= i && i < mySet.length && mySet[i]; - } - - public TokenSet minus(TokenSet t) { - TokenSet set = new TokenSet(); - for (int i = 0; i < mySet.length; i++) { - set.mySet [i] = mySet [i] && (i >= t.mySet.length || !t.mySet[i]); + @NotNull + public static TokenSet andNot(@NotNull TokenSet a, @NotNull TokenSet b) { + final TokenSet newSet = new TokenSet((short)Math.min(a.myShift, b.myShift), (short)Math.max(a.myMax, b.myMax)); + for (int i = 0; i < newSet.myWords.length; i++) { + final int ai = newSet.myShift - a.myShift + i, bi = newSet.myShift - b.myShift + i; + newSet.myWords[i] = (0 <= ai && ai < a.myWords.length ? a.myWords[ai] : 0l) & ~(0 <= bi && bi < b.myWords.length ? b.myWords[bi] : 0l); } - return set; + return newSet; } - public static TokenSet not(TokenSet t) { - TokenSet set = new TokenSet(); - for (int i = 0; i < t.mySet.length; i++) { - set.mySet [i] = (i >= t.mySet.length || !t.mySet[i]); + /** @deprecated please use {@linkplain #andNot(TokenSet, TokenSet)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") + public TokenSet minus(@NotNull TokenSet t) { + return andNot(this, t); + } + + /** @deprecated please use {@linkplain IElementType#enumerate(com.intellij.psi.tree.IElementType.Predicate)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") + public static TokenSet not(@NotNull TokenSet set) { + final TokenSet newSet = new TokenSet((short)0, set.myTop); + for (int i = 0; i < newSet.myWords.length; i++) { + final long word = i >= set.myShift ? set.myWords[(i - set.myShift)] : 0l; + newSet.myWords[i] = ~word; } - return set; - } - - @Override - public String toString() { - return Arrays.asList(getTypes()).toString(); + return newSet; } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsConfigurable.java index 467e51fc2a7f..f0825c04a28c 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsConfigurable.java @@ -17,8 +17,8 @@ package com.intellij.application.options.editor; import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.options.AbstractConfigurableEP; import com.intellij.openapi.options.CompositeConfigurable; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -35,7 +35,7 @@ public class AutoImportOptionsConfigurable extends CompositeConfigurable createConfigurables() { - return AbstractConfigurableEP.createConfigurables(AutoImportOptionsProviderEP.EP_NAME); + return ConfigurableWrapper.createConfigurables(AutoImportOptionsProviderEP.EP_NAME); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsProviderEP.java b/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsProviderEP.java index 879c3fee3323..61c94ea12acf 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsProviderEP.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/AutoImportOptionsProviderEP.java @@ -16,7 +16,7 @@ package com.intellij.application.options.editor; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; /** * Register implementation of {@link AutoImportOptionsProvider} in the plugin.xml to provide additional options in Editor | Auto Import section: @@ -29,6 +29,6 @@ import com.intellij.openapi.options.AbstractConfigurableEP; * * @author nik */ -public class AutoImportOptionsProviderEP extends AbstractConfigurableEP { +public class AutoImportOptionsProviderEP extends ConfigurableEP { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.autoImportOptionsProvider"); } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingConfigurable.java index 7cbbe7f365fb..62203db42ae2 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingConfigurable.java @@ -23,9 +23,9 @@ import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; -import com.intellij.openapi.options.AbstractConfigurableEP; import com.intellij.openapi.options.CompositeConfigurable; import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.Nls; @@ -110,7 +110,7 @@ public class CodeFoldingConfigurable extends CompositeConfigurable createConfigurables() { - return AbstractConfigurableEP.createConfigurables(CodeFoldingOptionsProviderEP.EP_NAME); + return ConfigurableWrapper.createConfigurables(CodeFoldingOptionsProviderEP.EP_NAME); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingOptionsProviderEP.java b/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingOptionsProviderEP.java index 6f31a3f331de..dae2f81a619f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingOptionsProviderEP.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/CodeFoldingOptionsProviderEP.java @@ -16,7 +16,7 @@ package com.intellij.application.options.editor; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; /** * Register implementation of {@link CodeFoldingOptionsProvider} in the plugin.xml to provide additional options in Editor | Code Folding section: @@ -29,6 +29,6 @@ import com.intellij.openapi.options.AbstractConfigurableEP; * @author nik */ -public class CodeFoldingOptionsProviderEP extends AbstractConfigurableEP { +public class CodeFoldingOptionsProviderEP extends ConfigurableEP { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.codeFoldingOptionsProvider"); } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurable.java index abff17292504..d3b6dbe8c03e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurable.java @@ -24,10 +24,8 @@ import com.intellij.ide.ui.UISettings; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; -import com.intellij.openapi.options.CompositeConfigurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.options.*; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -194,7 +192,7 @@ public class EditorAppearanceConfigurable extends CompositeConfigurable createConfigurables() { - return AbstractConfigurableEP.createConfigurables(EP_NAME); + return ConfigurableWrapper.createConfigurables(EP_NAME); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurableEP.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurableEP.java index 2aaef3f00350..3c6778e78519 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurableEP.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorAppearanceConfigurableEP.java @@ -15,7 +15,7 @@ */ package com.intellij.application.options.editor; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; import com.intellij.openapi.options.UnnamedConfigurable; /** @@ -30,5 +30,5 @@ import com.intellij.openapi.options.UnnamedConfigurable; * * @author nik */ -public class EditorAppearanceConfigurableEP extends AbstractConfigurableEP { +public class EditorAppearanceConfigurableEP extends ConfigurableEP { } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptions.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptions.java index b87c26398982..130a726ac8ff 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptions.java @@ -17,29 +17,16 @@ package com.intellij.application.options.editor; import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.options.AbstractConfigurableEP; -import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.List; -public class EditorOptions implements SearchableConfigurable.Parent { +public class EditorOptions implements SearchableConfigurable { @NonNls public static final String ID = "preferences.editor"; private EditorOptionsPanel myEditorOptionsPanel; - private Configurable[] myChildren; - - @Override - public Configurable[] getConfigurables() { - if (myChildren == null) { - final List configurables = AbstractConfigurableEP.createConfigurables(EditorOptionsProviderEP.EP_NAME); - myChildren = configurables.toArray(new EditorOptionsProvider[configurables.size()]); - } - return myChildren; - } @Override public String getDisplayName() { @@ -62,16 +49,6 @@ public class EditorOptions implements SearchableConfigurable.Parent { return null; } - @Override - public boolean hasOwnContent() { - return true; - } - - @Override - public boolean isVisible() { - return true; - } - @Override public JComponent createComponent() { myEditorOptionsPanel = new EditorOptionsPanel(); @@ -100,6 +77,5 @@ public class EditorOptions implements SearchableConfigurable.Parent { @Override public void disposeUIResources() { myEditorOptionsPanel = null; - } } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsProviderEP.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsProviderEP.java index e74f823d8dd5..72c4fa21eaf3 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsProviderEP.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsProviderEP.java @@ -16,7 +16,7 @@ package com.intellij.application.options.editor; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; /** * Register implementation of {@link EditorOptionsProvider} in the plugin.xml to provide sub-section of Editor section in the Settings dialog: @@ -29,6 +29,6 @@ import com.intellij.openapi.options.AbstractConfigurableEP; * * @author nik */ -public class EditorOptionsProviderEP extends AbstractConfigurableEP { +public class EditorOptionsProviderEP extends ConfigurableEP { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.editorOptionsProvider"); } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurable.java index 79e0404cb322..37408febc6bb 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurable.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurable.java @@ -25,10 +25,8 @@ import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; -import com.intellij.openapi.options.CompositeConfigurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.options.*; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -96,7 +94,7 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable createConfigurables() { - return AbstractConfigurableEP.createConfigurables(EP_NAME); + return ConfigurableWrapper.createConfigurables(EP_NAME); } @Override diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java index 6525aa098168..567f0042d7f6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorSmartKeysConfigurableEP.java @@ -15,7 +15,7 @@ */ package com.intellij.application.options.editor; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; import com.intellij.openapi.options.UnnamedConfigurable; /** @@ -30,5 +30,5 @@ import com.intellij.openapi.options.UnnamedConfigurable; * * @author nik */ -public class EditorSmartKeysConfigurableEP extends AbstractConfigurableEP { +public class EditorSmartKeysConfigurableEP extends ConfigurableEP { } diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/ErrorHighlightingPanel.java b/platform/lang-impl/src/com/intellij/application/options/editor/ErrorHighlightingPanel.java index 0945b54feab1..a8bf87f8578b 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/ErrorHighlightingPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/ErrorHighlightingPanel.java @@ -17,8 +17,8 @@ package com.intellij.application.options.editor; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings; -import com.intellij.openapi.options.AbstractConfigurableEP; import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.profile.codeInspection.ui.ErrorOptionsProvider; import com.intellij.profile.codeInspection.ui.ErrorOptionsProviderEP; @@ -35,7 +35,7 @@ public class ErrorHighlightingPanel { private final List myExtensions; public ErrorHighlightingPanel() { - myExtensions = AbstractConfigurableEP.createConfigurables(ErrorOptionsProviderEP.EP_NAME); + myExtensions = ConfigurableWrapper.createConfigurables(ErrorOptionsProviderEP.EP_NAME); for (ErrorOptionsProvider optionsProvider : myExtensions) { myErrorsPanel.add(optionsProvider.createComponent()); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocCommentFixer.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocCommentFixer.java new file mode 100644 index 000000000000..923f6adfc5e0 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocCommentFixer.java @@ -0,0 +1,35 @@ +/* + * 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.codeInsight.documentation; + +import com.intellij.lang.LanguageExtension; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiComment; +import org.jetbrains.annotations.NotNull; + +/** + * @author Denis Zhdanov + * @since 9/20/12 8:37 PM + */ +public interface DocCommentFixer { + + LanguageExtension EXTENSION = new LanguageExtension("com.intellij.lang.documentationFixer"); + + // TODO den add doc + void fixComment(@NotNull Project project, @NotNull Editor editor, @NotNull PsiComment comment); +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FixDocCommentAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FixDocCommentAction.java index 353ea0cbe38a..cb3de1cb6270 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FixDocCommentAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/FixDocCommentAction.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.editorActions; +import com.intellij.codeInsight.documentation.DocCommentFixer; import com.intellij.lang.*; import com.intellij.lang.documentation.CodeDocumentationProvider; import com.intellij.lang.documentation.CompositeDocumentationProvider; @@ -104,20 +105,33 @@ public class FixDocCommentAction extends EditorAction { return; } final CodeDocumentationAwareCommenter commenter = (CodeDocumentationAwareCommenter)c; + final Runnable task; + if (pair.second == null || pair.second.getTextRange().isEmpty()) { + task = new Runnable() { + @Override + public void run() { + generateComment(pair.first, editor, docProvider, commenter, project); + } + }; + } + else { + final DocCommentFixer fixer = DocCommentFixer.EXTENSION.forLanguage(language); + if (fixer == null) { + return; + } + else { + task = new Runnable() { + @Override + public void run() { + fixer.fixComment(project, editor, pair.second); + } + }; + } + } final Runnable command = new Runnable() { @Override public void run() { - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - if (pair.second == null || pair.second.getTextRange().isEmpty()) { - generateComment(pair.first, editor, docProvider, commenter, project); - } - else { - fixCommentIfNecessary(pair.second); - } - } - }); + ApplicationManager.getApplication().runWriteAction(task); } }; CommandProcessor.getInstance().executeCommand(project, command, "Fix documentation", null); @@ -246,8 +260,4 @@ public class FixDocCommentAction extends EditorAction { } return result; } - - private static void fixCommentIfNecessary(@NotNull PsiComment docComment) { - // TODO den implement - } } diff --git a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java index 1e4568f31ad3..f6bcebd04497 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java @@ -76,6 +76,7 @@ public class RunConfigurationsComboBoxAction extends ComboBoxAction implements D if (DumbService.getInstance(project).isDumb()) { presentation.setEnabled(false); presentation.setText(""); + presentation.setIcon(null); } else { updateButton(ExecutionTargetManager.getActiveTarget(project), diff --git a/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java b/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java index a2b31898012c..63ff8d2a629f 100644 --- a/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java +++ b/platform/lang-impl/src/com/intellij/execution/actions/StopAction.java @@ -23,90 +23,33 @@ import com.intellij.execution.ui.RunContentDescriptor; import com.intellij.execution.ui.RunContentManager; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.ListItemDescriptor; import com.intellij.openapi.ui.popup.PopupChooserBuilder; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.ex.StatusBarEx; +import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.ui.components.JBList; -import com.intellij.util.NotNullFunction; +import com.intellij.ui.popup.list.GroupedItemsListRenderer; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; public class StopAction extends DumbAwareAction implements AnAction.TransparentUpdate { - - public void actionPerformed(final AnActionEvent e) { - final DataContext dataContext = e.getDataContext(); - ProcessHandler processHandler = getHandler(dataContext); - if ((processHandler == null || processHandler.isProcessTerminated()) && ActionPlaces.MAIN_MENU.equals(e.getPlace())) { - final Collection handlerItems = getItemsList(getActiveDescriptors(dataContext)); - if (!handlerItems.isEmpty()) { - final JBList list = new JBList(handlerItems); - list.installCellRenderer(new NotNullFunction() { - final JLabel label = new JLabel(); - @NotNull - public JComponent fun(HandlerItem item) { - label.setIcon(item.icon); - label.setIconTextGap(6); - label.setText(item.displayName); - return label; - } - }); - final PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(list); - final String title = handlerItems.size() == 1? "Confirm process stop" : "Select process to stop"; - - final JBPopup popup = builder.setTitle(title).setItemChoosenCallback(new Runnable() { - public void run() { - final HandlerItem item = (HandlerItem)list.getSelectedValue(); - if (item != null) { - performAction(item.handler); - } - } - }).setRequestFocus(true).createPopup(); - - popup.showInBestPositionFor(dataContext); - } - } - - if(processHandler != null) { - performAction(processHandler); - } - } - - private static Collection getItemsList(List descriptors) { - if (descriptors.isEmpty()) { - return Collections.emptyList(); - } - final ArrayList items = new ArrayList(); - for (RunContentDescriptor descriptor : descriptors) { - final ProcessHandler handler = descriptor.getProcessHandler(); - if (handler != null) { - items.add(new HandlerItem(handler, descriptor.getDisplayName(), descriptor.getIcon())); - } - } - return items; - } - - private static void performAction(ProcessHandler processHandler) { - if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) { - ((KillableProcess)processHandler).killProcess(); - return; - } - - if(processHandler.detachIsDefault()) { - processHandler.detachProcess(); - } - else { - processHandler.destroyProcess(); - } - } - public void update(final AnActionEvent e) { boolean enable = false; Icon icon = getTemplatePresentation().getIcon(); @@ -114,14 +57,7 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU final Presentation presentation = e.getPresentation(); if (ActionPlaces.MAIN_MENU.equals(e.getPlace())) { - final List descriptors = getActiveDescriptors(e.getDataContext()); - for (RunContentDescriptor descriptor : descriptors) { - final ProcessHandler handler = descriptor.getProcessHandler(); - if (handler != null && !handler.isProcessTerminated()) { - enable = true; - break; - } - } + enable = !getCancellableProcesses(e.getProject()).isEmpty() || !getActiveDescriptors(e.getDataContext()).isEmpty(); } else { final ProcessHandler processHandler = getHandler(e.getDataContext()); @@ -142,6 +78,144 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU presentation.setDescription(description); } + public void actionPerformed(final AnActionEvent e) { + final DataContext dataContext = e.getDataContext(); + ProcessHandler activeProcessHandler = getHandler(dataContext); + + List> backgroundTasks = getCancellableProcesses(e.getProject()); + if (ActionPlaces.MAIN_MENU.equals(e.getPlace())) { + if (activeProcessHandler != null && !activeProcessHandler.isProcessTerminating() && !activeProcessHandler.isProcessTerminated() + && backgroundTasks.isEmpty()) { + stopProcess(activeProcessHandler); + return; + } + + Pair, HandlerItem> + handlerItems = getItemsList(backgroundTasks, getActiveDescriptors(dataContext), activeProcessHandler); + if (handlerItems.first.isEmpty()) return; + + final JBList list = new JBList(handlerItems.first); + if (handlerItems.second != null) list.setSelectedValue(handlerItems.second, true); + + list.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() { + @Nullable + @Override + public String getTextFor(Object value) { + return value instanceof HandlerItem ? ((HandlerItem)value).displayName : null; + } + + @Nullable + @Override + public String getTooltipFor(Object value) { + return null; + } + + @Nullable + @Override + public Icon getIconFor(Object value) { + return value instanceof HandlerItem ? ((HandlerItem)value).icon : null; + } + + @Override + public boolean hasSeparatorAboveOf(Object value) { + return value instanceof HandlerItem && ((HandlerItem)value).hasSeparator; + } + + @Nullable + @Override + public String getCaptionAboveOf(Object value) { + return null; + } + })); + + final PopupChooserBuilder builder = JBPopupFactory.getInstance().createListPopupBuilder(list); + final JBPopup popup = builder + .setMovable(true) + .setTitle(handlerItems.first.size() == 1 ? "Confirm process stop" : "Stop process") + .setFilteringEnabled(new Function() { + @Override + public String fun(Object o) { + return ((HandlerItem)o).displayName; + } + }) + .setItemChoosenCallback(new Runnable() { + public void run() { + HandlerItem item = (HandlerItem)list.getSelectedValue(); + if (item != null) item.stop(); + } + }).setRequestFocus(true).createPopup(); + + popup.showCenteredInCurrentWindow(e.getProject()); + } + else { + if (activeProcessHandler != null) { + stopProcess(activeProcessHandler); + } + } + } + + private static List> getCancellableProcesses(Project project) { + IdeFrame frame = ((WindowManagerEx)WindowManager.getInstance()).findFrameFor(project); + StatusBarEx statusBar = frame == null ? null : (StatusBarEx)frame.getStatusBar(); + if (statusBar == null) return Collections.emptyList(); + + return ContainerUtil.findAll(statusBar.getBackgroundProcesses(), + new Condition>() { + @Override + public boolean value(Pair pair) { + return pair.first.isCancellable() && !pair.second.isCanceled(); + } + }); + } + + private static Pair, HandlerItem> getItemsList(List> tasks, + List descriptors, + ProcessHandler activeProcessHandler) { + if (tasks.isEmpty() && descriptors.isEmpty()) return Pair.create(Collections.emptyList(), null); + + ArrayList items = new ArrayList(tasks.size() + descriptors.size()); + HandlerItem selected = null; + for (RunContentDescriptor descriptor : descriptors) { + final ProcessHandler handler = descriptor.getProcessHandler(); + if (handler != null) { + HandlerItem item = new HandlerItem(descriptor.getDisplayName(), descriptor.getIcon(), false) { + @Override + void stop() { + stopProcess(handler); + } + }; + items.add(item); + if (handler == activeProcessHandler) selected = item; + } + } + + boolean hasSeparator = true; + for (final Pair eachPair : tasks) { + items.add(new HandlerItem(eachPair.first.getTitle(), AllIcons.Process.Step_passive, hasSeparator) { + @Override + void stop() { + eachPair.second.cancel(); + } + }); + hasSeparator = false; + } + return Pair., HandlerItem>create(items, selected); + } + + private static void stopProcess(ProcessHandler processHandler) { + if (processHandler instanceof KillableProcess && processHandler.isProcessTerminating()) { + ((KillableProcess)processHandler).killProcess(); + return; + } + + if (processHandler.detachIsDefault()) { + processHandler.detachProcess(); + } + else { + processHandler.destroyProcess(); + } + } + @Nullable private static ProcessHandler getHandler(final DataContext dataContext) { final RunContentDescriptor contentDescriptor = RunContentManager.RUN_CONTENT_DESCRIPTOR.getData(dataContext); @@ -153,8 +227,9 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU else { // main menu toolbar final Project project = PlatformDataKeys.PROJECT.getData(dataContext); - final RunContentDescriptor selectedContent = project == null? null : ExecutionManager.getInstance(project).getContentManager().getSelectedContent(); - processHandler = selectedContent == null? null : selectedContent.getProcessHandler(); + final RunContentDescriptor selectedContent = + project == null ? null : ExecutionManager.getInstance(project).getContentManager().getSelectedContent(); + processHandler = selectedContent == null ? null : selectedContent.getProcessHandler(); } return processHandler; } @@ -172,27 +247,28 @@ public class StopAction extends DumbAwareAction implements AnAction.TransparentU final List activeDescriptors = new ArrayList(); for (RunContentDescriptor descriptor : runningProcesses) { final ProcessHandler processHandler = descriptor.getProcessHandler(); - if (processHandler != null && !processHandler.isProcessTerminated()) { + if (processHandler != null && !processHandler.isProcessTerminating() && !processHandler.isProcessTerminated()) { activeDescriptors.add(descriptor); } } return activeDescriptors; } - private static class HandlerItem { - private final ProcessHandler handler; - private final String displayName; - private final Icon icon; + private abstract static class HandlerItem { + final String displayName; + final Icon icon; + final boolean hasSeparator; - private HandlerItem(final ProcessHandler processHandler, final String displayName1, Icon icon) { - this.handler = processHandler; - displayName = displayName1; + private HandlerItem(String displayName, Icon icon, boolean hasSeparator) { + this.displayName = displayName; this.icon = icon; + this.hasSeparator = hasSeparator; } public String toString() { return displayName; } - } + abstract void stop(); + } } diff --git a/platform/lang-impl/src/com/intellij/openapi/options/ModuleConfigurableEP.java b/platform/lang-impl/src/com/intellij/openapi/options/ModuleConfigurableEP.java index 19461b1c0205..4b59fc52a3ae 100644 --- a/platform/lang-impl/src/com/intellij/openapi/options/ModuleConfigurableEP.java +++ b/platform/lang-impl/src/com/intellij/openapi/options/ModuleConfigurableEP.java @@ -28,8 +28,8 @@ import com.intellij.openapi.module.Module; * * @author nik */ -public class ModuleConfigurableEP extends AbstractConfigurableEP { +public class ModuleConfigurableEP extends ConfigurableEP { public ModuleConfigurableEP(Module module) { - super(module.getPicoContainer()); + super(module.getPicoContainer(), null); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkListCellRenderer.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkListCellRenderer.java index f48df21af652..05af2835af3b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkListCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkListCellRenderer.java @@ -19,42 +19,54 @@ package com.intellij.openapi.projectRoots.impl; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkType; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.ColoredListCellRendererWrapper; import com.intellij.ui.SimpleTextAttributes; +import org.jetbrains.annotations.NotNull; import javax.swing.*; /** * @author yole */ -public class SdkListCellRenderer extends HtmlListCellRenderer { - private String myNullText = ""; - private boolean myShowHomePath; +public class SdkListCellRenderer extends ColoredListCellRendererWrapper { + private final String myNullText; + private final boolean myShowHomePath; - public SdkListCellRenderer(final ListCellRenderer listCellRenderer) { - super(); + public SdkListCellRenderer(@NotNull String nullText) { + this(nullText, false); } - public SdkListCellRenderer(final String nullText, final ListCellRenderer listCellRenderer) { - super(); - myNullText = nullText; - } - - public SdkListCellRenderer(final String nullText, final boolean showHomePath, final ListCellRenderer listCellRenderer) { - super(); + public SdkListCellRenderer(@NotNull String nullText, boolean showHomePath) { myNullText = nullText; myShowHomePath = showHomePath; } + /** @deprecated use {@linkplain #SdkListCellRenderer(String)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") + public SdkListCellRenderer(final ListCellRenderer listCellRenderer) { + this(""); + } + + /** @deprecated use {@linkplain #SdkListCellRenderer(String)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") + public SdkListCellRenderer(final String nullText, final ListCellRenderer listCellRenderer) { + this(nullText); + } + + /** @deprecated use {@linkplain #SdkListCellRenderer(String, boolean)} (to remove in IDEA 13) */ + @SuppressWarnings("UnusedDeclaration") + public SdkListCellRenderer(final String nullText, final boolean showHomePath, final ListCellRenderer listCellRenderer) { + this(nullText, showHomePath); + } + @Override protected void doCustomize(final JList list, final Sdk sdk, final int index, final boolean selected, final boolean hasFocus) { if (sdk != null) { - // icon setIcon(getSdkIcon(sdk)); - // text append(sdk.getName()); if (myShowHomePath) { - append(" (" + FileUtil.toSystemDependentName(sdk.getHomePath()) + ")", + append(" (" + FileUtil.toSystemDependentName(StringUtil.notNullize(sdk.getHomePath())) + ")", selected ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES); } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ErrorOptionsProviderEP.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ErrorOptionsProviderEP.java index b26310556fb2..295a5d7b9b32 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ErrorOptionsProviderEP.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ErrorOptionsProviderEP.java @@ -16,7 +16,7 @@ package com.intellij.profile.codeInspection.ui; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; /** * Register implementation of {@link ErrorOptionsProvider} in the plugin.xml to provide additional options in Editor | "Error highlighting" section: @@ -29,6 +29,6 @@ import com.intellij.openapi.options.AbstractConfigurableEP; * * @author nik */ -public class ErrorOptionsProviderEP extends AbstractConfigurableEP { +public class ErrorOptionsProviderEP extends ConfigurableEP { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.errorOptionsProvider"); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java index d7c610af617b..bf75f2176c71 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java @@ -15,6 +15,7 @@ */ package com.intellij.refactoring.rename.inplace; +import com.intellij.codeInsight.TargetElementUtilBase; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.impl.FinishMarkAction; import com.intellij.openapi.command.impl.StartMarkAction; @@ -105,7 +106,9 @@ public class MemberInplaceRenamer extends VariableInplaceRenamer { return super.getNameIdentifier(); } if (currentFile != null) { - final PsiElement elementAt = currentFile.findElementAt(myEditor.getCaretModel().getOffset()); + int offset = myEditor.getCaretModel().getOffset(); + offset = TargetElementUtilBase.adjustOffset(myEditor.getDocument(), offset); + final PsiElement elementAt = currentFile.findElementAt(offset); if (elementAt != null) { final PsiElement referenceExpression = elementAt.getParent(); if (referenceExpression != null) { diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java index c8e7b0709c3e..edd655ec8b12 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -156,7 +156,7 @@ public abstract class AbstractTreeNode extends PresentableNodeDescriptor impl } @Nullable - public String toTestString(Queryable.PrintInfo printInfo) { + public String toTestString(@Nullable Queryable.PrintInfo printInfo) { if (getValue() instanceof Queryable) { String text = Queryable.Util.print((Queryable)getValue(), printInfo, this); if (text != null) return text; diff --git a/platform/platform-api/src/com/intellij/openapi/options/Configurable.java b/platform/platform-api/src/com/intellij/openapi/options/Configurable.java index 714adb7716ae..343264c0e3e4 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/Configurable.java +++ b/platform/platform-api/src/com/intellij/openapi/options/Configurable.java @@ -47,9 +47,9 @@ import org.jetbrains.annotations.Nullable; */ public interface Configurable extends UnnamedConfigurable { - ExtensionPointName APPLICATION_CONFIGURABLE = ExtensionPointName.create("com.intellij.applicationConfigurable"); + ExtensionPointName> APPLICATION_CONFIGURABLE = ExtensionPointName.create("com.intellij.applicationConfigurable"); - ExtensionPointName PROJECT_CONFIGURABLE = ExtensionPointName.create("com.intellij.projectConfigurable"); + ExtensionPointName> PROJECT_CONFIGURABLE = ExtensionPointName.create("com.intellij.projectConfigurable"); /** * Returns the user-visible name of the settings component. diff --git a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java index 9d2590c4ee0a..72880d015536 100644 --- a/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java +++ b/platform/platform-api/src/com/intellij/openapi/options/ConfigurableEP.java @@ -39,7 +39,7 @@ import java.util.ResourceBundle; * @see Configurable */ @Tag("configurable") -public class ConfigurableEP extends AbstractExtensionPointBean { +public class ConfigurableEP extends AbstractExtensionPointBean { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.options.ConfigurableEP"); @Attribute("displayName") @@ -53,6 +53,7 @@ public class ConfigurableEP extends AbstractExtensionPointBean { public String getDisplayName() { if (displayName != null) return displayName; + LOG.assertTrue(bundle != null, "Bundle missed for " + instanceClass); final ResourceBundle resourceBundle = AbstractBundle.getResourceBundle(bundle, myPluginDescriptor.getPluginClassLoader()); return displayName = CommonBundle.message(resourceBundle, key); } @@ -61,11 +62,20 @@ public class ConfigurableEP extends AbstractExtensionPointBean { @AbstractCollection(surroundWithTag = false) public ConfigurableEP[] children; + /** + * Extension point of ConfigurableEP type to calculate children + */ + @Attribute("childrenEPName") + public String childrenEPName; + + @Attribute("parentId") + public String parentId; + public ConfigurableEP[] getChildren() { for (ConfigurableEP child : children) { child.myPicoContainer = myPicoContainer; child.myPluginDescriptor = myPluginDescriptor; - child.isForDefaultProject = isForDefaultProject; + child.myProject = myProject; } return children; } @@ -76,9 +86,8 @@ public class ConfigurableEP extends AbstractExtensionPointBean { @Attribute("nonDefaultProject") public boolean nonDefaultProject; - private boolean isForDefaultProject; public boolean isAvailable() { - return !(nonDefaultProject && isForDefaultProject); + return !nonDefaultProject || !(myProject != null && myProject.isDefault()); } /** @@ -91,26 +100,27 @@ public class ConfigurableEP extends AbstractExtensionPointBean { @Attribute("provider") public String providerClass; - private final AtomicNotNullLazyValue> myFactory; + private final AtomicNotNullLazyValue> myFactory; private PicoContainer myPicoContainer; + private Project myProject; @SuppressWarnings("UnusedDeclaration") public ConfigurableEP() { - this(ApplicationManager.getApplication().getPicoContainer()); + this(ApplicationManager.getApplication().getPicoContainer(), null); } @SuppressWarnings("UnusedDeclaration") public ConfigurableEP(Project project) { - this(project.getPicoContainer()); - isForDefaultProject = project.isDefault(); + this(project.getPicoContainer(), project); } - private ConfigurableEP(PicoContainer picoContainer) { + protected ConfigurableEP(PicoContainer picoContainer, @Nullable Project project) { + myProject = project; myPicoContainer = picoContainer; - myFactory = new AtomicNotNullLazyValue>() { + myFactory = new AtomicNotNullLazyValue>() { @NotNull @Override - protected NullableFactory compute() { + protected NullableFactory compute() { if (providerClass != null) { return new InstanceFromProviderFactory(); } @@ -126,7 +136,7 @@ public class ConfigurableEP extends AbstractExtensionPointBean { } @Nullable - public Configurable createConfigurable() { + public T createConfigurable() { try { return myFactory.getValue().create(); } @@ -139,9 +149,18 @@ public class ConfigurableEP extends AbstractExtensionPointBean { return null; } - private class InstanceFromProviderFactory extends AtomicNotNullLazyValue implements NullableFactory { - public Configurable create() { - return getValue().createConfigurable(); + public Project getProject() { + return myProject; + } + + @Override + public String toString() { + return getDisplayName(); + } + + private class InstanceFromProviderFactory extends AtomicNotNullLazyValue implements NullableFactory { + public T create() { + return (T)getValue().createConfigurable(); } @NotNull @@ -156,14 +175,14 @@ public class ConfigurableEP extends AbstractExtensionPointBean { } } - private class NewInstanceFactory extends NotNullLazyValue> implements NullableFactory { - public Configurable create() { + private class NewInstanceFactory extends NotNullLazyValue> implements NullableFactory { + public T create() { return instantiate(getValue(), myPicoContainer, true); } @NotNull @Override - protected Class compute() { + protected Class compute() { try { return findClass(instanceClass); } @@ -173,17 +192,17 @@ public class ConfigurableEP extends AbstractExtensionPointBean { } } - private class ImplementationFactory extends AtomicNotNullLazyValue implements NullableFactory { + private class ImplementationFactory extends AtomicNotNullLazyValue implements NullableFactory { @Override - public Configurable create() { + public T create() { return compute(); } @NotNull @Override - protected Configurable compute() { + protected T compute() { try { - final Class aClass = findClass(implementationClass); + final Class aClass = findClass(implementationClass); return instantiate(aClass, myPicoContainer, true); } catch (ClassNotFoundException e) { diff --git a/platform/platform-api/src/com/intellij/ui/ColoredListCellRendererWrapper.java b/platform/platform-api/src/com/intellij/ui/ColoredListCellRendererWrapper.java new file mode 100644 index 000000000000..096febcb9b6f --- /dev/null +++ b/platform/platform-api/src/com/intellij/ui/ColoredListCellRendererWrapper.java @@ -0,0 +1,42 @@ +/* + * 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.ui; + +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * Typed version of {@link ColoredListCellRenderer}. + */ +public abstract class ColoredListCellRendererWrapper extends ColoredListCellRenderer { + @Override + protected final void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { + @SuppressWarnings("unchecked") final T t = (T)value; + doCustomize(list, t, index, selected, hasFocus); + } + + protected abstract void doCustomize(JList list, T value, int index, boolean selected, boolean hasFocus); + + public void append(@NotNull SimpleColoredText text) { + int length = text.getTexts().size(); + for (int i = 0; i < length; i++) { + String fragment = text.getTexts().get(i); + SimpleTextAttributes attributes = text.getAttributes().get(i); + append(fragment, attributes); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java index f457d06003c1..ed54f3e591cd 100644 --- a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java @@ -17,8 +17,8 @@ package com.intellij.ide; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; -import com.intellij.openapi.options.AbstractConfigurableEP; import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.SystemInfo; @@ -107,7 +107,7 @@ public class BrowserSettingsPanel extends JPanel { myUseAlternativeBrowser.setVisible(false); } - mySettingsProviders = AbstractConfigurableEP.createConfigurables(BrowserSettingsProviderEP.EP_NAME); + mySettingsProviders = ConfigurableWrapper.createConfigurables(BrowserSettingsProviderEP.EP_NAME); for (BrowserSettingsProvider settingsProvider : mySettingsProviders) { outerPanel.add(settingsProvider.createComponent()); } diff --git a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java index 8f810b8473fd..7c5f61fa5e40 100644 --- a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java +++ b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java @@ -16,11 +16,11 @@ package com.intellij.ide; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; /** * @author nik */ -public class BrowserSettingsProviderEP extends AbstractConfigurableEP { +public class BrowserSettingsProviderEP extends ConfigurableEP { public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.browserSettingsProvider"); } diff --git a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java index b2186053286e..b93a5d8f14a9 100644 --- a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java @@ -17,6 +17,7 @@ package com.intellij.ide; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.options.*; +import com.intellij.openapi.options.ex.ConfigurableWrapper; import com.intellij.ui.components.JBRadioButton; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -189,6 +190,6 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable createConfigurables() { - return AbstractConfigurableEP.createConfigurables(EP_NAME); + return ConfigurableWrapper.createConfigurables(EP_NAME); } } diff --git a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurableEP.java b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurableEP.java index dd63f535adf3..77aff6f9bc0f 100644 --- a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurableEP.java +++ b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurableEP.java @@ -15,7 +15,7 @@ */ package com.intellij.ide; -import com.intellij.openapi.options.AbstractConfigurableEP; +import com.intellij.openapi.options.ConfigurableEP; import com.intellij.openapi.options.SearchableConfigurable; /** @@ -29,5 +29,5 @@ import com.intellij.openapi.options.SearchableConfigurable; * * @author nik */ -public class GeneralSettingsConfigurableEP extends AbstractConfigurableEP { +public class GeneralSettingsConfigurableEP extends ConfigurableEP { } diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java index ce0dd75caf9a..0fbf534b6ab5 100644 --- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java +++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/ErrorViewStructure.java @@ -70,9 +70,11 @@ public class ErrorViewStructure extends AbstractTreeStructure { // simple messages synchronized (myLock) { for (final ErrorTreeElementKind kind : ourMessagesOrder) { - if (ErrorTreeElementKind.WARNING.equals(kind) || ErrorTreeElementKind.NOTE.equals(kind)) { - if (myCanHideWarnings && ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { - continue; + if (myCanHideWarnings) { + if (ErrorTreeElementKind.WARNING.equals(kind) || ErrorTreeElementKind.NOTE.equals(kind)) { + if (ErrorTreeViewConfiguration.getInstance(myProject).isHideWarnings()) { + continue; + } } } final List elems = mySimpleMessages.get(kind); @@ -274,6 +276,13 @@ public class ErrorViewStructure extends AbstractTreeStructure { } } + @Nullable + public GroupingElement lookupGroupingElement(String groupName) { + synchronized (myLock) { + return myGroupNameToElementMap.get(groupName); + } + } + public GroupingElement getGroupingElement(String groupName, Object data, VirtualFile file) { synchronized (myLock) { GroupingElement element = myGroupNameToElementMap.get(groupName); @@ -351,6 +360,35 @@ public class ErrorViewStructure extends AbstractTreeStructure { } } + public void removeElement(final ErrorTreeElement element) { + if (element == myRoot) { + return; + } + if (element instanceof GroupingElement) { + removeGroup(((GroupingElement)element).getName()); + } + else if (element instanceof NavigatableMessageElement){ + final NavigatableMessageElement navElement = (NavigatableMessageElement)element; + final GroupingElement parent = navElement.getParent(); + if (parent != null) { + synchronized (myLock) { + final List groupMessages = myGroupNameToMessagesMap.get(parent.getName()); + if (groupMessages != null) { + groupMessages.remove(navElement); + } + } + } + } + else { + synchronized (myLock) { + final List simples = mySimpleMessages.get(element.getKind()); + if (simples != null) { + simples.remove(element); + } + } + } + } + private static class MyNavigatableWithDataElement extends NavigatableMessageElement { private final VirtualFile myVf; private final CustomizeColoredTreeCellRenderer myCustomizeColoredTreeCellRenderer; diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java index 33e8e52c444d..b7f2d3cfde76 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java @@ -68,6 +68,7 @@ import java.util.List; public final class ActionManagerImpl extends ActionManagerEx implements ApplicationComponent { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.impl.ActionManagerImpl"); + private static final int DEACTIVATED_TIMER_DELAY = 5000; private static final int TIMER_DELAY = 500; private static final int UPDATE_DELAY_AFTER_TYPING = 500; @@ -1193,7 +1194,7 @@ public final class ActionManagerImpl extends ActionManagerEx implements Applicat @Override public void applicationDeactivated(IdeFrame ideFrame) { - setDelay(30000); + setDelay(DEACTIVATED_TIMER_DELAY); } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java index a8166c6ec259..2e668a33f281 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java @@ -108,13 +108,15 @@ public class IndentSelectionAction extends EditorAction { if (bulkMode) ((DocumentEx)document).setInBulkUpdate(true); try { - PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document); - IndentStrategy indentStrategy = LanguageIndentStrategy.getIndentStrategy(file); List nonModifiableLines = new ArrayList(); - if (!LanguageIndentStrategy.isDefault(indentStrategy)) { - for (int i = startIndex; i <= endIndex; i++) { - if (!canIndent(document, file, i, indentStrategy)) { - nonModifiableLines.add(i); + if (project != null) { + PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document); + IndentStrategy indentStrategy = LanguageIndentStrategy.getIndentStrategy(file); + if (!LanguageIndentStrategy.isDefault(indentStrategy)) { + for (int i = startIndex; i <= endIndex; i++) { + if (!canIndent(document, file, i, indentStrategy)) { + nonModifiableLines.add(i); + } } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/AbstractConfigurableEP.java b/platform/platform-impl/src/com/intellij/openapi/options/AbstractConfigurableEP.java deleted file mode 100644 index 50924d88a665..000000000000 --- a/platform/platform-impl/src/com/intellij/openapi/options/AbstractConfigurableEP.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.options; - -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.extensions.AbstractExtensionPointBean; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.util.AtomicNotNullLazyValue; -import com.intellij.util.xmlb.annotations.Attribute; -import org.jetbrains.annotations.NotNull; -import org.picocontainer.PicoContainer; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author nik - */ -public class AbstractConfigurableEP extends AbstractExtensionPointBean { - @Attribute("instance") - public String instanceClass; - - /** - * @deprecated use '{@link #instanceClass instance}' attribute instead - */ - @Attribute("implementation") - public String implementationClass; - - private final PicoContainer myPicoContainer; - private final AtomicNotNullLazyValue myImplementation = new AtomicNotNullLazyValue() { - @NotNull - @Override - protected T compute() { - if (implementationClass == null) { - throw new IllegalArgumentException("Neither 'instance' nor 'implementation' attribute is not specified for " + AbstractConfigurableEP.this.getClass() + " extension"); - } - try { - final Class aClass = findClass(implementationClass); - return instantiate(aClass, myPicoContainer, true); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - }; - - protected AbstractConfigurableEP(PicoContainer picoContainer) { - myPicoContainer = picoContainer; - } - - public AbstractConfigurableEP() { - myPicoContainer = ApplicationManager.getApplication().getPicoContainer(); - } - - @NotNull - public T createConfigurable() { - if (instanceClass == null) { - return myImplementation.getValue(); - } - try { - final Class aClass = findClass(instanceClass); - return instantiate(aClass, myPicoContainer); - } - catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } - - public static List createConfigurables(ExtensionPointName> pointName) { - List configurables = new ArrayList(); - for (AbstractConfigurableEP ep : pointName.getExtensions()) { - configurables.add(ep.createConfigurable()); - } - return configurables; - } -} diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java index 1e0bacaa887e..a88ca1004877 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableExtensionPointUtil.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.options.ex; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableEP; import com.intellij.openapi.options.ConfigurableProvider; @@ -24,27 +26,53 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.*; /** * @author nik */ public class ConfigurableExtensionPointUtil { + private final static Logger LOG = Logger.getInstance(ConfigurableExtensionPointUtil.class); + private ConfigurableExtensionPointUtil() { } - public static List buildConfigurablesList(final ConfigurableEP[] extensions, final Configurable[] components, @Nullable ConfigurableFilter filter) { + public static List buildConfigurablesList(final ConfigurableEP[] extensions, + final Configurable[] components, + @Nullable ConfigurableFilter filter, + ExtensionPointName> configurablesExtensionPoint) { List result = new ArrayList(); - for (ConfigurableEP extension : extensions) { - ContainerUtil.addIfNotNull(ConfigurableWrapper.wrapConfigurable(extension), result); + Map idToConfigurable = new HashMap(); + List orphans = new ArrayList(); + for (ConfigurableEP ep : extensions) { + final Configurable configurable = ConfigurableWrapper.wrapConfigurable(ep); + if (configurable instanceof ConfigurableWrapper) { + ConfigurableWrapper wrapper = (ConfigurableWrapper)configurable; + if (wrapper.getParentId() != null) { + orphans.add(wrapper); + } else { + idToConfigurable.put(wrapper.getId(), wrapper); + } + } + else { +// dumpConfigurable(configurablesExtensionPoint, ep, configurable); + ContainerUtil.addIfNotNull(configurable, result); + } } ContainerUtil.addAll(result, components); - final Iterator iterator = result.iterator(); + for (ConfigurableWrapper orphan : orphans) { + String parentId = orphan.getParentId(); + ConfigurableWrapper parent = idToConfigurable.get(parentId); + LOG.assertTrue(parent != null, "Can't find parent for " + parentId + " (" + orphan + ")"); + idToConfigurable.put(parentId, parent.addChild(orphan)); + } + + ContainerUtil.addAll(result, idToConfigurable.values()); + + final ListIterator iterator = result.listIterator(); while (iterator.hasNext()) { Configurable each = iterator.next(); if (each instanceof Configurable.Assistant @@ -57,6 +85,59 @@ public class ConfigurableExtensionPointUtil { return result; } + /* + private static void dumpConfigurable(ExtensionPointName> configurablesExtensionPoint, + ConfigurableEP ep, + Configurable configurable) { + if (configurable != null && !(configurable instanceof ConfigurableGroup)) { + if (ep.instanceClass != null && (configurable instanceof SearchableConfigurable) && (configurable instanceof Configurable.Composite)) { + Element element = dump(ep, configurable, StringUtil.getShortName(configurablesExtensionPoint.getName())); + final Configurable[] configurables = ((Configurable.Composite)configurable).getConfigurables(); + for (Configurable child : configurables) { + final Element dump = dump(null, child, "configurable"); + element.addContent(dump); + } + final StringWriter out = new StringWriter(); + try { + new XMLOutputter(Format.getPrettyFormat()).output(element, out); + } + catch (IOException e) { + } + System.out.println(out); + } + } + } + + private static Element dump(@Nullable ConfigurableEP ep, + Configurable configurable, String name) { + Element element = new Element(name); + if (ep != null) { + element.setAttribute("instance", ep.instanceClass); + String id = ep.id == null ? ((SearchableConfigurable)configurable).getId() : ep.id; + element.setAttribute("id", id); + } + else { + element.setAttribute("instance", configurable.getClass().getName()); + if (configurable instanceof SearchableConfigurable) { + element.setAttribute("id", ((SearchableConfigurable)configurable).getId()); + } + } + + CommonBundle.lastKey = null; + String displayName = configurable.getDisplayName(); + if (CommonBundle.lastKey != null) { + element.setAttribute("key", CommonBundle.lastKey).setAttribute("bundle", CommonBundle.lastBundle); + } + else { + element.setAttribute("displayName", displayName); + } + if (configurable instanceof NonDefaultProjectConfigurable) { + element.setAttribute("nonDefaultProject", "true"); + } + return element; + } + */ + /** * @deprecated create a new instance of configurable instead */ @@ -71,8 +152,8 @@ public class ConfigurableExtensionPointUtil { } @NotNull - private static T findConfigurable(ConfigurableEP[] extensions, Class configurableClass) { - for (ConfigurableEP extension : extensions) { + private static T findConfigurable(ConfigurableEP[] extensions, Class configurableClass) { + for (ConfigurableEP extension : extensions) { if (extension.providerClass != null || extension.instanceClass != null || extension.implementationClass != null) { final Configurable configurable = extension.createConfigurable(); if (configurableClass.isInstance(configurable)) { @@ -94,8 +175,8 @@ public class ConfigurableExtensionPointUtil { } @Nullable - private static Configurable createConfigurableForProvider(ConfigurableEP[] extensions, Class providerClass) { - for (ConfigurableEP extension : extensions) { + private static Configurable createConfigurableForProvider(ConfigurableEP[] extensions, Class providerClass) { + for (ConfigurableEP extension : extensions) { if (extension.providerClass != null) { final Class aClass = extension.findClassNoExceptions(extension.providerClass); if (aClass != null && providerClass.isAssignableFrom(aClass)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java index 824217a85d58..f309e7532bd5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java @@ -15,7 +15,11 @@ */ package com.intellij.openapi.options.ex; +import com.intellij.openapi.extensions.ExtensionPoint; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.options.*; +import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Nls; @@ -23,18 +27,39 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import java.util.List; /** * @author Dmitry Avdeev * Date: 9/17/12 */ -public class ConfigurableWrapper implements SearchableConfigurable, Configurable.Composite { +public class ConfigurableWrapper implements SearchableConfigurable { private static final ConfigurableWrapper[] EMPTY_ARRAY = new ConfigurableWrapper[0]; + private static final NullableFunction,Configurable> CONFIGURABLE_FUNCTION = new NullableFunction, Configurable>() { + @Override + public Configurable fun(ConfigurableEP ep) { + return wrapConfigurable(ep); + } + }; @Nullable - public static Configurable wrapConfigurable(ConfigurableEP ep) { - return ep.displayName != null || ep.key != null ? new ConfigurableWrapper(ep) : ep.createConfigurable(); + public static T wrapConfigurable(ConfigurableEP ep) { + if (ep.displayName != null || ep.key != null) { + return (T)(ep.children != null || ep.childrenEPName != null ? new CompositeWrapper(ep) : new ConfigurableWrapper(ep)); + } + else { + return ep.createConfigurable(); + } + } + + public static List createConfigurables(ExtensionPointName> name) { + return ContainerUtil.mapNotNull(Extensions.getExtensions(name), new NullableFunction, T>() { + @Override + public T fun(ConfigurableEP ep) { + return wrapConfigurable(ep); + } + }); } public static boolean isNoScroll(Configurable configurable) { @@ -48,22 +73,14 @@ public class ConfigurableWrapper implements SearchableConfigurable, Configurable } private final ConfigurableEP myEp; - private final ConfigurableWrapper[] myKids; public ConfigurableWrapper(ConfigurableEP ep) { myEp = ep; - myKids = ep.children == null ? EMPTY_ARRAY : ContainerUtil.mapNotNull(ep.getChildren(), - new NullableFunction() { - @Override - public ConfigurableWrapper fun(ConfigurableEP ep) { - return ep.isAvailable() ? new ConfigurableWrapper(ep) : null; - } - }, new ConfigurableWrapper[0]); } - private Configurable myConfigurable; + private UnnamedConfigurable myConfigurable; - private Configurable getConfigurable() { + protected UnnamedConfigurable getConfigurable() { if (myConfigurable == null) { myConfigurable = myEp.createConfigurable(); if (myConfigurable == null) { @@ -82,7 +99,8 @@ public class ConfigurableWrapper implements SearchableConfigurable, Configurable @Nullable @Override public String getHelpTopic() { - return getConfigurable().getHelpTopic(); + UnnamedConfigurable configurable = getConfigurable(); + return configurable instanceof Configurable ? ((Configurable)configurable).getHelpTopic() : null; } @Nullable @@ -111,21 +129,77 @@ public class ConfigurableWrapper implements SearchableConfigurable, Configurable getConfigurable().disposeUIResources(); } - @Override - public Configurable[] getConfigurables() { - return myKids; - } - @NotNull @Override public String getId() { return myEp.id == null ? myEp.instanceClass : myEp.id; } + + public String getParentId() { + return myEp.parentId; + } + + public ConfigurableWrapper addChild(Configurable configurable) { + return new CompositeWrapper(myEp, configurable); + } + + @Override + public String toString() { + return getDisplayName(); + } + @Nullable @Override public Runnable enableSearch(String option) { - final Configurable configurable = getConfigurable(); + final UnnamedConfigurable configurable = getConfigurable(); return configurable instanceof SearchableConfigurable ? ((SearchableConfigurable)configurable).enableSearch(option) : null; } + + private static class CompositeWrapper extends ConfigurableWrapper implements Configurable.Composite { + + private Configurable[] myKids; + + public CompositeWrapper(ConfigurableEP ep, Configurable... kids) { + super(ep); + if (ep.children == null) { + kids = EMPTY_ARRAY; + } + else { + kids = ContainerUtil.mapNotNull(ep.getChildren(), + new NullableFunction() { + @Override + public ConfigurableWrapper fun(ConfigurableEP ep) { + return ep.isAvailable() ? new ConfigurableWrapper(ep) : null; + } + }, EMPTY_ARRAY); + } + if (ep.childrenEPName != null) { + ExtensionPoint childrenEP = Extensions.getArea(ep.getProject()).getExtensionPoint(ep.childrenEPName); + Object[] extensions = childrenEP.getExtensions(); + if (extensions.length > 0) { + if (extensions[0] instanceof ConfigurableEP) { + Configurable[] children = ContainerUtil.mapNotNull(((ConfigurableEP[])extensions), + CONFIGURABLE_FUNCTION, new Configurable[0]); + kids = ArrayUtil.mergeArrays(kids, children); + } + else { + kids = ArrayUtil.mergeArrays(kids, ((Composite)getConfigurable()).getConfigurables()); + } + } + } + myKids = kids; + } + + @Override + public Configurable[] getConfigurables() { + return myKids; + } + + @Override + public ConfigurableWrapper addChild(Configurable configurable) { + myKids = ArrayUtil.append(myKids, configurable); + return this; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurablesGroupBase.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurablesGroupBase.java index 6a87cc4a1589..2de79dffab5f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurablesGroupBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurablesGroupBase.java @@ -30,10 +30,10 @@ import java.util.List; public abstract class ConfigurablesGroupBase implements ConfigurableGroup { private Configurable[] myChildren; private ComponentManager myComponentManager; - private final ExtensionPointName myConfigurablesExtensionPoint; + private final ExtensionPointName> myConfigurablesExtensionPoint; private final boolean myLoadComponents; - protected ConfigurablesGroupBase(ComponentManager componentManager, final ExtensionPointName configurablesExtensionPoint, + protected ConfigurablesGroupBase(ComponentManager componentManager, final ExtensionPointName> configurablesExtensionPoint, boolean loadComponents) { myComponentManager = componentManager; myConfigurablesExtensionPoint = configurablesExtensionPoint; @@ -43,10 +43,10 @@ public abstract class ConfigurablesGroupBase implements ConfigurableGroup { @Override public Configurable[] getConfigurables() { if (myChildren == null) { - final ConfigurableEP[] extensions = myComponentManager.getExtensions(myConfigurablesExtensionPoint); + final ConfigurableEP[] extensions = myComponentManager.getExtensions(myConfigurablesExtensionPoint); Configurable[] components = myLoadComponents ? myComponentManager.getComponents(Configurable.class) : new Configurable[0]; - List result = ConfigurableExtensionPointUtil.buildConfigurablesList(extensions, components, getConfigurableFilter()); + List result = ConfigurableExtensionPointUtil.buildConfigurablesList(extensions, components, getConfigurableFilter(), myConfigurablesExtensionPoint); myChildren = result.toArray(new Configurable[result.size()]); } return myChildren; diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadOnlyStatusDialog.java b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadOnlyStatusDialog.java index cab984c2c7ad..f7260446ff85 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadOnlyStatusDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/vcs/readOnlyHandler/ReadOnlyStatusDialog.java @@ -21,7 +21,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.ui.CollectionComboBoxModel; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.ColoredListCellRendererWrapper; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.ui.OptionsDialog; import com.intellij.util.ui.UIUtil; @@ -103,7 +103,7 @@ public class ReadOnlyStatusDialog extends OptionsDialog { final String defaultChangelist = handleType.getDefaultChangelist(); myChangelist.setModel(new CollectionComboBoxModel(changelists, defaultChangelist)); - myChangelist.setRenderer(new HtmlListCellRenderer() { + myChangelist.setRenderer(new ColoredListCellRendererWrapper() { @Override protected void doCustomize(JList list, String value, int index, boolean selected, boolean hasFocus) { if (value.equals(defaultChangelist)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/StatusBarEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/StatusBarEx.java index f6920f33b941..df0f9be229ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/StatusBarEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/StatusBarEx.java @@ -16,9 +16,11 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.Disposable; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.BalloonHandler; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.wm.StatusBar; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,6 +28,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.HyperlinkListener; import java.awt.*; +import java.util.List; /** * @author spleaner @@ -38,6 +41,7 @@ public interface StatusBarEx extends StatusBar, Disposable { BalloonHandler notifyProgressByBalloon(@NotNull MessageType type, @NotNull String htmlBody, @Nullable Icon icon, @Nullable HyperlinkListener listener); void addProgress(ProgressIndicatorEx indicator, TaskInfo info); + List> getBackgroundProcesses(); void updateWidgets(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java index 0df1acd3d2be..3c306d65d3df 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java @@ -17,11 +17,13 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.Disposable; import com.intellij.openapi.components.ApplicationComponent; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.BalloonHandler; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.StatusBar; import com.intellij.openapi.wm.StatusBarWidget; @@ -36,6 +38,8 @@ import javax.swing.*; import javax.swing.event.HyperlinkListener; import java.awt.*; import java.awt.event.ComponentEvent; +import java.util.Collections; +import java.util.List; /** * @author Anton Katilin @@ -134,6 +138,11 @@ public final class TestWindowManager extends WindowManagerEx implements Applicat public void addProgress(ProgressIndicatorEx indicator, TaskInfo info) { } + @Override + public List> getBackgroundProcesses() { + return Collections.emptyList(); + } + public void addWidget(@NotNull StatusBarWidget widget, @NotNull Disposable parentDisposable) { Disposer.register(parentDisposable, widget); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java index 3f3854e0c7f6..4532b0e6d8d6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java @@ -21,6 +21,7 @@ import com.intellij.ide.ui.UISettingsListener; import com.intellij.notification.impl.IdeNotificationArea; import com.intellij.openapi.Disposable; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.BalloonHandler; @@ -412,6 +413,11 @@ public class IdeStatusBarImpl extends JComponent implements StatusBarEx { myInfoAndProgressPanel.addProgress(indicator, info); } + @Override + public List> getBackgroundProcesses() { + return myInfoAndProgressPanel.getBackgroundProcesses(); + } + public void setProcessWindowOpen(final boolean open) { myInfoAndProgressPanel.setProcessWindowOpen(open); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 06bcaac1307d..b4a28a7d1232 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -21,6 +21,7 @@ import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.TaskInfo; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.Balloon; @@ -56,6 +57,7 @@ import java.awt.event.MouseEvent; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.*; +import java.util.List; public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidget { private final ProcessPopup myPopup; @@ -82,7 +84,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge private String myCurrentRequestor; private final boolean myProgressEnabled; - + public InfoAndProgressPanel(boolean progressEnabled) { myProgressEnabled = progressEnabled; @@ -180,6 +182,19 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge return this; } + public List> getBackgroundProcesses() { + synchronized (myOriginals) { + if (myOriginals.isEmpty()) return Collections.emptyList(); + + List> result = new ArrayList>(myOriginals.size()); + for (int i = 0; i < myOriginals.size(); i++) { + result.add(Pair.create(myInfos.get(i), myOriginals.get(i))); + } + + return Collections.unmodifiableList(result); + } + } + public void addProgress(final ProgressIndicatorEx original, TaskInfo info) { synchronized (myOriginals) { final boolean veryFirst = !hasProgressIndicators(); @@ -216,7 +231,7 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge private void removeProgress(InlineProgressIndicator progress) { synchronized (myOriginals) { if (!myInline2Original.containsKey(progress)) return; - + final boolean last = myOriginals.size() == 1; final boolean beforeLast = myOriginals.size() == 2; diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties index 73b9b7cb659e..dc13f20949b3 100644 --- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties +++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties @@ -45,7 +45,7 @@ inspection.annotate.method.quickfix.name=Annotate method as ''@{0}'' #dataflow inspection.data.flow.display.name=Constant conditions \\& exceptions -inspection.data.flow.nullable.quickfix.option=Suggest @Nullable annotation for methods that may possibly return null +inspection.data.flow.nullable.quickfix.option=Suggest @Nullable annotation for methods that may possibly return null and
report nullable values passed to non-annotated parameters inspection.data.flow.true.asserts.option=Don't report assert statements with condition statically proven to be always true inspection.data.flow.redundant.instanceof.quickfix=Replace with != null inspection.data.flow.simplify.boolean.expression.quickfix=Simplify Boolean Expression @@ -114,7 +114,6 @@ inspection.nullable.problems.display.name=@NotNull/@Nullable problems inspection.nullable.problems.method.overrides.notnull.option=report @NotNull ¶meter overrides @Nullable and
@Nullable method overrides @NotNull inspection.nullable.problems.method.overrides.option=report non-&annotated parameter or method overrides @NotNull inspection.nullable.problems.not.annotated.getters.for.annotated.fields=report non-annotated &setter parameter or getter of annotated fields -inspection.nullable.problems.non.annotated.passed.null=report &null passed to non-annotated parameter inspection.nullable.problems.annotation.not.propagated=report @NotNull not propagated to ove&rridden methods #problem descriptor messages diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index 10bb417a1494..937ea57a09fd 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -472,6 +472,8 @@ + + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index f66138aa3f15..c3b3764d3361 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -341,15 +341,11 @@ serviceImplementation="com.intellij.codeInspection.ex.ProjectInspectionProfilesVisibleTreeState"/> - + - - - - @@ -568,18 +564,20 @@ - - + + - - - - - + + + + + diff --git a/platform/platform-resources/src/idea/Keymap_Xcode.xml b/platform/platform-resources/src/idea/Keymap_Xcode.xml index 59496f66fc78..ab915e7f24c1 100644 --- a/platform/platform-resources/src/idea/Keymap_Xcode.xml +++ b/platform/platform-resources/src/idea/Keymap_Xcode.xml @@ -167,9 +167,6 @@ - - - @@ -303,14 +300,14 @@ - + - + - + diff --git a/platform/platform-tests/testSrc/com/intellij/psi/tree/TokenSetTest.java b/platform/platform-tests/testSrc/com/intellij/psi/tree/TokenSetTest.java new file mode 100644 index 000000000000..3dd6fcfaa0ff --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/psi/tree/TokenSetTest.java @@ -0,0 +1,134 @@ +/* + * 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.psi.tree; + +import com.intellij.lang.Language; +import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.util.ThrowableRunnable; +import com.intellij.util.containers.ContainerUtil; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; +import java.util.Random; +import java.util.Set; + +import static org.junit.Assert.*; + +public class TokenSetTest { + private IElementType T1, T2, T3, T4, T5, T6; + private TokenSet S1, S12, S3, S34, S5; + + @Before + public void setUp() { + T1 = new IElementType("T1", Language.ANY); + T2 = new IElementType("T2", Language.ANY); + S1 = TokenSet.create(T1); + S12 = TokenSet.create(T1, T2); + fakeElements(1, 128); + T3 = new IElementType("T3", Language.ANY); + T4 = new IElementType("T4", Language.ANY); + S3 = TokenSet.create(T3); + S34 = TokenSet.create(T3, T4); + fakeElements(201, 204); + T5 = new IElementType("T5", Language.ANY); + T6 = new IElementType("T6", Language.ANY); + S5 = TokenSet.create(T5); + } + + @Test + public void create() { + check(S1, T1); + check(S12, T1, T2); + check(S3, T3); + check(S34, T3, T4); + } + + @Test + public void getTypes() throws Exception { + assertArrayEquals(IElementType.EMPTY_ARRAY, TokenSet.EMPTY.getTypes()); + assertArrayEquals(new IElementType[]{T1, T2}, S12.getTypes()); + assertArrayEquals(new IElementType[]{T3, T4}, S34.getTypes()); + assertEquals("[]", TokenSet.EMPTY.toString()); + assertEquals("[T1, T2]", S12.toString()); + assertEquals("[T3, T4]", S34.toString()); + } + + @Test + public void orSet() { + check(TokenSet.orSet(S1, S12, S3), T1, T2, T3); + check(TokenSet.orSet(S1, S3), T1, T3); + } + + @Test + public void andSet() { + check(TokenSet.andSet(S1, S12), T1); + check(TokenSet.andSet(S12, S34)); + } + + @SuppressWarnings("deprecation") + @Test + public void andNot() throws Exception { + final TokenSet S123 = TokenSet.orSet(S12, S3); + check(S123.minus(S12), T3); + check(S123.minus(S5), T1, T2, T3); + check(TokenSet.andNot(S123, S12), T3); + check(TokenSet.andNot(S123, S5), T1, T2, T3); + } + + @SuppressWarnings("deprecation") + @Test + public void not() throws Exception { + check(TokenSet.not(S12)); + check(TokenSet.not(S34), T1, T2); + check(TokenSet.not(S5), T1, T2, T3, T4, T6); + } + + private static void fakeElements(int from, int to) { + for (int i = from; i <= to; i++) { + new IElementType("Test element #" + i, Language.ANY); + } + } + + private void check(TokenSet set, IElementType... elements) { + final Set expected = ContainerUtil.newHashSet(elements); + for (IElementType t : Arrays.asList(T1, T2, T3, T4, T5, T6)) { + if (expected.contains(t)) { + assertTrue("missed: " + t, set.contains(t)); + } + else { + assertFalse("unexpected: " + t, set.contains(t)); + } + } + } + + @Test + public void performance() throws Exception { + final IElementType[] elementTypes = IElementType.enumerate(IElementType.TRUE); + final TokenSet set = TokenSet.create(); + final int shift = new Random().nextInt(500000); + + PlatformTestUtil.startPerformanceTest("TokenSet.contains() performance", 25, new ThrowableRunnable() { + @Override + public void run() throws Throwable { + for (int i = 0; i < 1000000; i++) { + final IElementType next = elementTypes[((i + shift) % elementTypes.length)]; + assertFalse(set.contains(next)); + } + } + }).cpuBound().assertTiming(); + } +} diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java index 880746145197..756added7691 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java +++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java @@ -501,8 +501,14 @@ public class ExpectedHighlightingData { int byEnds = i2.endOffset - i1.endOffset; if (byEnds != 0) return byEnds; - int byStarts = i1.startOffset - i2.startOffset; - if (byStarts != 0) return byStarts; + if (!i1.isAfterEndOfLine && !i2.isAfterEndOfLine) { + int byStarts = i1.startOffset - i2.startOffset; + if (byStarts != 0) return byStarts; + } + else { + int byEOL = Comparing.compare(i2.isAfterEndOfLine, i1.isAfterEndOfLine); + if (byEOL != 0) return byEOL; + } int bySeverity = i2.severity.compareTo(i1.severity); if (bySeverity != 0) return bySeverity; diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java index f9a458da2e55..ec2853375721 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java @@ -98,7 +98,7 @@ public class PlatformTestUtil { } @Nullable - protected static String toString(Object node, @Nullable Queryable.PrintInfo printInfo) { + protected static String toString(@Nullable Object node, @Nullable Queryable.PrintInfo printInfo) { if (node instanceof AbstractTreeNode) { if (printInfo != null) { return ((AbstractTreeNode)node).toTestString(printInfo); @@ -492,10 +492,9 @@ public class PlatformTestUtil { String logMessage = message; if (duration > expectedOnMyMachine) { int percentage = (int)(100.0 * (duration - expectedOnMyMachine) / expectedOnMyMachine); - logMessage += ". (" + percentage + "% longer)."; + logMessage += ". (" + percentage + "% longer)"; } - logMessage += " Expected: " + expectedOnMyMachine + "." + - " Actual: " + duration + "." + Timings.getStatistics() ; + logMessage += ". Expected: " + expectedOnMyMachine + ". Actual: " + duration + "." + Timings.getStatistics() ; if (duration < expectedOnMyMachine) { int percentage = (int)(100.0 * (expectedOnMyMachine - duration) / expectedOnMyMachine); logMessage = "(" + percentage + "% faster). " + logMessage; @@ -594,8 +593,6 @@ public class PlatformTestUtil { public static void assertDirectoriesEqual(VirtualFile dirAfter, VirtualFile dirBefore, @Nullable VirtualFileFilter fileFilter) throws IOException { FileDocumentManager.getInstance().saveAllDocuments(); - dirAfter.getChildren(); - dirAfter.refresh(false, false); VirtualFile[] childrenAfter = dirAfter.getChildren(); if (dirAfter.isInLocalFileSystem()) { File[] ioAfter = new File(dirAfter.getPath()).listFiles(); diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java index afcac8ac0cd0..9e2270575594 100644 --- a/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java +++ b/platform/testFramework/testSrc/com/intellij/testFramework/ExpectedHighlightingDataTest.java @@ -30,86 +30,101 @@ public class ExpectedHighlightingDataTest { private static Map TYPES; @BeforeClass - public static void setUp() throws Exception { + public static void setUp() { TYPES = new HashMap(); TYPES.put("err", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.ERROR, false, true)); TYPES.put("warn", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.WARNING, false, true)); + TYPES.put("eol_err", new ExpectedHighlightingData.ExpectedHighlightingSet(HighlightSeverity.ERROR, true, true)); } @AfterClass - public static void tearDown() throws Exception { + public static void tearDown() { TYPES.clear(); TYPES = null; } @Test - public void empty() throws Exception { + public void empty() { doTest("text", Collections.emptyList(), "text"); } @Test - public void sequential() throws Exception { + public void sequential() { doTest("_my text_", Arrays.asList(error(1, 3, "1"), error(4, 8, "2")), "_my text_"); } @Test - public void simpleNested() throws Exception { + public void simpleNested() { doTest("[(nested)]", Arrays.asList(error(1, 9, "1"), error(2, 8, "2")), "[(nested)]"); } @Test - public void deepNested() throws Exception { + public void deepNested() { doTest("m1(m2(m3(m4(x))))", Arrays.asList(error(3, 16, "m1"), error(6, 15, "m2"), error(9, 14, "m3"), error(12, 13, "m4")), "m1(m2(m3(m4(x))))"); } @Test - public void sameStart() throws Exception { + public void sameStart() { doTest("same start", Arrays.asList(error(0, 4, "1"), error(0, 10, "2")), "same start"); } @Test - public void sameEnd() throws Exception { + public void sameEnd() { doTest("same end", Arrays.asList(error(0, 8, "1"), error(5, 8, "2")), "same end"); } @Test - public void sameBothBounds() throws Exception { + public void sameBothBounds() { doTest("same", Arrays.asList(error(0, 4, "-"), warning(0, 4, "-")), "same"); } @Test - public void samePriority() throws Exception { + public void samePriority() { doTest("same", Arrays.asList(warning(0, 4, "1"), warning(0, 4, "2")), "same"); } @Test - public void twoNests() throws Exception { + public void twoNests() { doTest("(two nests)", Arrays.asList(error(0, 11, "-"), error(1, 4, "1"), error(5, 10, "2")), "(two nests)"); } @Test - public void realistic() throws Exception { + public void realistic() { doTest("one and (two nests)", Arrays.asList(error(4, 7, "-"), error(8, 19, "-"), error(9, 12, "1"), error(13, 18, "2")), "one and (two nests)"); } + @Test + public void twoEOLs() { + doTest("text\nmore text", + Arrays.asList(eolError(4, 4, "1"), eolError(4, 4, "2")), + "text\nmore text"); + } + + @Test + public void eolAfterError() { + doTest("some error\nmore text", + Arrays.asList(error(5, 10, "1"), eolError(10, 10, "2")), + "some error\nmore text"); + } + private static void doTest(String original, Collection highlighting, String expected) { String text = ExpectedHighlightingData.composeText(TYPES, highlighting, original); assertEquals(expected, text); @@ -118,8 +133,11 @@ public class ExpectedHighlightingDataTest { private static HighlightInfo error(int start, int end, String description) { return new HighlightInfo(HighlightInfoType.ERROR, start, end, description, null); } - private static HighlightInfo warning(int start, int end, String description) { return new HighlightInfo(HighlightInfoType.WARNING, start, end, description, null); } + + private static HighlightInfo eolError(int start, int end, String description) { + return new HighlightInfo(null, null, HighlightInfoType.ERROR, start, end, description, null, HighlightSeverity.ERROR, true, null, false); + } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/IssueLinkRenderer.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/IssueLinkRenderer.java index 51cbd5af6358..e40102dd3d59 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/IssueLinkRenderer.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/IssueLinkRenderer.java @@ -18,7 +18,6 @@ package com.intellij.openapi.vcs.changes.issueLinks; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.IssueNavigationConfiguration; -import com.intellij.ui.HtmlListCellRenderer; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.Consumer; @@ -31,18 +30,10 @@ import java.util.List; */ public class IssueLinkRenderer { private final SimpleColoredComponent myColoredComponent; - private final HtmlListCellRenderer myHtmlListCellRenderer; private final IssueNavigationConfiguration myIssueNavigationConfiguration; public IssueLinkRenderer(final Project project, final SimpleColoredComponent coloredComponent) { myColoredComponent = coloredComponent; - myHtmlListCellRenderer = null; - myIssueNavigationConfiguration = IssueNavigationConfiguration.getInstance(project); - } - - public IssueLinkRenderer(final Project project, final HtmlListCellRenderer htmlListCellRenderer) { - myColoredComponent = null; - myHtmlListCellRenderer = htmlListCellRenderer; myIssueNavigationConfiguration = IssueNavigationConfiguration.getInstance(project); } @@ -70,7 +61,6 @@ public class IssueLinkRenderer { final String piece = text.substring(pos, textRange.getStartOffset()); pieces.add(piece); consumer.consume(piece); - //append(piece, baseStyle); } final String piece = textRange.substring(text); pieces.add(piece); @@ -81,27 +71,16 @@ public class IssueLinkRenderer { final String piece = text.substring(pos); pieces.add(piece); consumer.consume(piece); - //append(piece, baseStyle); } return pieces; } private void append(final String piece, final SimpleTextAttributes baseStyle) { - if (myColoredComponent != null) { - myColoredComponent.append(piece, baseStyle); - } - else { - myHtmlListCellRenderer.append(piece, baseStyle); - } + myColoredComponent.append(piece, baseStyle); } private void append(final String piece, final SimpleTextAttributes baseStyle, final IssueNavigationConfiguration.LinkMatch match) { - if (myColoredComponent != null) { - myColoredComponent.append(piece, baseStyle, new SimpleColoredComponent.BrowserLauncherTag(match.getTargetUrl())); - } - else { - myHtmlListCellRenderer.appendLink(piece, baseStyle, match.getTargetUrl()); - } + myColoredComponent.append(piece, baseStyle, new SimpleColoredComponent.BrowserLauncherTag(match.getTargetUrl())); } private static SimpleTextAttributes getLinkAttributes(final SimpleTextAttributes baseStyle) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 56441b761e83..97097a6e904f 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -71,7 +71,7 @@ public class ChangeListChooserPanel extends JPanel { } public void init() { - myExistingListsCombo.setRenderer(new HtmlListCellRenderer() { + myExistingListsCombo.setRenderer(new ColoredListCellRendererWrapper() { private final IssueLinkRenderer myLinkRenderer = new IssueLinkRenderer(myProject, this); @Override @@ -81,7 +81,8 @@ public class ChangeListChooserPanel extends JPanel { if (myExistingListsCombo.getWidth() == 0) { name = name.length() > 10 ? name.substring(0, 7) + " .." : name; - } else { + } + else { final FontMetrics fm = list.getFontMetrics(list.getFont()); final int width = fm.stringWidth(name); final int listWidth = myExistingListsCombo.getWidth(); @@ -92,8 +93,8 @@ public class ChangeListChooserPanel extends JPanel { } } } - myLinkRenderer.appendTextWithLinks(name, ((LocalChangeList)value).isDefault() ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES - : SimpleTextAttributes.REGULAR_ATTRIBUTES); + myLinkRenderer.appendTextWithLinks(name, ((LocalChangeList)value).isDefault() + ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES); } } }); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleChangeListBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleChangeListBrowser.java index 60f6048e4883..d8e7f40da984 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleChangeListBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/MultipleChangeListBrowser.java @@ -35,7 +35,7 @@ import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.actions.MoveChangesToAnotherListAction; import com.intellij.openapi.vcs.changes.actions.RollbackDialogAction; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.ColoredListCellRendererWrapper; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.EventDispatcher; import org.jetbrains.annotations.NotNull; @@ -230,7 +230,7 @@ public class MultipleChangeListBrowser extends ChangesBrowser { public ChangeListChooser(List lists) { super(new BorderLayout(4, 2)); myChooser = new JComboBox(); - myChooser.setRenderer(new HtmlListCellRenderer() { + myChooser.setRenderer(new ColoredListCellRendererWrapper() { @Override protected void doCustomize(JList list, LocalChangeList value, int index, boolean selected, boolean hasFocus) { if (value != null) { diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.java index ff5714276583..4804350a9f39 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/config/ui/LanguagePanel.java @@ -24,8 +24,8 @@ import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; +import com.intellij.ui.ColoredListCellRendererWrapper; import com.intellij.ui.EditorTextField; -import com.intellij.ui.HtmlListCellRenderer; import com.intellij.ui.ShiftTabAction; import com.intellij.ui.SimpleTextAttributes; import org.intellij.plugins.intelliLang.inject.InjectedLanguage; @@ -55,7 +55,7 @@ public class LanguagePanel extends AbstractInjectionPanel { Arrays.sort(languageIDs); myLanguage.setModel(new DefaultComboBoxModel(languageIDs)); - myLanguage.setRenderer(new HtmlListCellRenderer() { + myLanguage.setRenderer(new ColoredListCellRendererWrapper() { final Set IDs = new HashSet(Arrays.asList(languageIDs)); @Override diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index 646b8ff59747..f85102e42ab7 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -294,7 +294,10 @@ serviceImplementation="org.jetbrains.android.compiler.AndroidDexCompilerConfiguration"/> - + + + diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.form b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.form index 53097ee7e989..d5ee29df3943 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.form +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.form @@ -1,5 +1,5 @@ - + diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.java new file mode 100644 index 000000000000..f75a07cb9630 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsConfigurable.java @@ -0,0 +1,100 @@ +/* + * 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 org.jetbrains.android.compiler; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.openapi.project.Project; +import com.intellij.ui.RawCommandLineEditor; +import com.intellij.ui.components.JBCheckBox; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** +* @author Dmitry Avdeev +* Date: 9/21/12 +*/ +public class AndroidDexCompilerSettingsConfigurable implements SearchableConfigurable, Configurable.NoScroll { + private final AndroidDexCompilerConfiguration myConfig; + private JPanel myContentPanel; + private JSpinner myHeapSizeSpinner; + private JLabel myVmOptionsLabel; + private RawCommandLineEditor myVmOptionsEditor; + private JBCheckBox myOptimizeCheckBox; + + public AndroidDexCompilerSettingsConfigurable(Project project) { + myConfig = AndroidDexCompilerConfiguration.getInstance(project); + myVmOptionsLabel.setLabelFor(myVmOptionsEditor); + myVmOptionsEditor.setDialogCaption(AndroidBundle.message("android.dex.compiler.vm.options.title")); + } + + @Nls + @Override + public String getDisplayName() { + return AndroidBundle.message("android.dex.compiler.configurable.display.name"); + } + + @Override + public String getHelpTopic() { + return "settings.android.dx.compiler"; + } + + @Override + public JComponent createComponent() { + return myContentPanel; + } + + @Override + public boolean isModified() { + int maxHeapSize = ((Integer)myHeapSizeSpinner.getValue()).intValue(); + return maxHeapSize != myConfig.MAX_HEAP_SIZE || + !myVmOptionsEditor.getText().equals(myConfig.VM_OPTIONS) || + myOptimizeCheckBox.isSelected() != myConfig.OPTIMIZE; + } + + @Override + public void apply() throws ConfigurationException { + myConfig.MAX_HEAP_SIZE = ((Integer)myHeapSizeSpinner.getValue()).intValue(); + myConfig.VM_OPTIONS = myVmOptionsEditor.getText(); + myConfig.OPTIMIZE = myOptimizeCheckBox.isSelected(); + } + + @Override + public void reset() { + myHeapSizeSpinner.setModel(new SpinnerNumberModel(myConfig.MAX_HEAP_SIZE, 1, 10000000, 1)); + myVmOptionsEditor.setText(myConfig.VM_OPTIONS); + myOptimizeCheckBox.setSelected(myConfig.OPTIMIZE); + } + + @Override + public void disposeUIResources() { + } + + @NotNull + @Override + public String getId() { + return "android.dex.compiler"; + } + + @Override + public Runnable enableSearch(String option) { + return null; + } +} diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsFactory.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsFactory.java deleted file mode 100644 index 6502c7e87046..000000000000 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompilerSettingsFactory.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.android.compiler; - -import com.intellij.compiler.CompilerSettingsFactory; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import com.intellij.ui.RawCommandLineEditor; -import com.intellij.ui.components.JBCheckBox; -import org.jetbrains.android.util.AndroidBundle; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -/** - * @author Eugene.Kudelevsky - */ -public class AndroidDexCompilerSettingsFactory implements CompilerSettingsFactory { - @Override - public Configurable create(Project project) { - return new AndroidDexCompilerSettingsConfigurable(project); - } - - private static class AndroidDexCompilerSettingsConfigurable implements SearchableConfigurable, Configurable.NoScroll { - private final AndroidDexCompilerConfiguration myConfig; - private JPanel myContentPanel; - private JSpinner myHeapSizeSpinner; - private JLabel myVmOptionsLabel; - private RawCommandLineEditor myVmOptionsEditor; - private JBCheckBox myOptimizeCheckBox; - - public AndroidDexCompilerSettingsConfigurable(Project project) { - myConfig = AndroidDexCompilerConfiguration.getInstance(project); - myVmOptionsLabel.setLabelFor(myVmOptionsEditor); - myVmOptionsEditor.setDialogCaption(AndroidBundle.message("android.dex.compiler.vm.options.title")); - } - - @Nls - @Override - public String getDisplayName() { - return AndroidBundle.message("android.dex.compiler.configurable.display.name"); - } - - @Override - public String getHelpTopic() { - return "settings.android.dx.compiler"; - } - - @Override - public JComponent createComponent() { - return myContentPanel; - } - - @Override - public boolean isModified() { - int maxHeapSize = ((Integer)myHeapSizeSpinner.getValue()).intValue(); - return maxHeapSize != myConfig.MAX_HEAP_SIZE || - !myVmOptionsEditor.getText().equals(myConfig.VM_OPTIONS) || - myOptimizeCheckBox.isSelected() != myConfig.OPTIMIZE; - } - - @Override - public void apply() throws ConfigurationException { - myConfig.MAX_HEAP_SIZE = ((Integer)myHeapSizeSpinner.getValue()).intValue(); - myConfig.VM_OPTIONS = myVmOptionsEditor.getText(); - myConfig.OPTIMIZE = myOptimizeCheckBox.isSelected(); - } - - @Override - public void reset() { - myHeapSizeSpinner.setModel(new SpinnerNumberModel(myConfig.MAX_HEAP_SIZE, 1, 10000000, 1)); - myVmOptionsEditor.setText(myConfig.VM_OPTIONS); - myOptimizeCheckBox.setSelected(myConfig.OPTIMIZE); - } - - @Override - public void disposeUIResources() { - } - - @NotNull - @Override - public String getId() { - return "android.dex.compiler"; - } - - @Override - public Runnable enableSearch(String option) { - return null; - } - } -} diff --git a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java index 4141b5436034..a6f836557d0f 100644 --- a/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java +++ b/plugins/android/src/org/jetbrains/android/run/ExtendedDeviceChooserDialog.java @@ -22,7 +22,8 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Disposer; -import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.ColoredListCellRenderer; +import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.annotations.NonNls; @@ -87,14 +88,12 @@ public class ExtendedDeviceChooserDialog extends DialogWrapper { }; Disposer.register(myDisposable, myAvdCombo); - - myAvdCombo.getComboBox().setRenderer(new HtmlListCellRenderer() { + myAvdCombo.getComboBox().setRenderer(new ColoredListCellRenderer() { @Override - protected void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { + protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) { if (value == null) { - setText(myAvdCombo.getComboBox().isEnabled() - ? "[none]" - : "[none]"); + append("[none]", + myAvdCombo.getComboBox().isEnabled() ? SimpleTextAttributes.ERROR_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES); } } }); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntBuildFileNodeDescriptor.java b/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntBuildFileNodeDescriptor.java index 045841f81e11..6e109130a410 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntBuildFileNodeDescriptor.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntBuildFileNodeDescriptor.java @@ -47,7 +47,7 @@ final class AntBuildFileNodeDescriptor extends AntNodeDescriptor { } public boolean update() { - CompositeAppearance oldAppearence = myAppearance; + CompositeAppearance oldAppearance = myAppearance; myAppearance = new CompositeAppearance(); myAppearance.getEnding().addText(myBuildFile.getPresentableName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); final AntBuildModelBase buildModel = myBuildFile.getModelIfRegistered(); @@ -56,7 +56,7 @@ final class AntBuildFileNodeDescriptor extends AntNodeDescriptor { } setIcon(AllIcons.Ant.Build); myName = myBuildFile.getPresentableName(); - return !Comparing.equal(myAppearance, oldAppearence); + return !Comparing.equal(myAppearance, oldAppearance); } public void customize(@NotNull SimpleColoredComponent component) { diff --git a/plugins/groovy/jetgroovy.iml b/plugins/groovy/jetgroovy.iml index 606328d89bf5..bb64ecbe2d34 100644 --- a/plugins/groovy/jetgroovy.iml +++ b/plugins/groovy/jetgroovy.iml @@ -35,8 +35,6 @@ - - diff --git a/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/after.groovy.template new file mode 100644 index 000000000000..480978ef6ab2 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/after.groovy.template @@ -0,0 +1 @@ +def getName() {name} \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/before.groovy.template new file mode 100644 index 000000000000..f4c46019e906 --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/before.groovy.template @@ -0,0 +1 @@ +def getName() {return name} \ No newline at end of file diff --git a/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/description.html b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/description.html new file mode 100644 index 000000000000..27201e0535fd --- /dev/null +++ b/plugins/groovy/resources/intentionDescriptions/RemoveUnnecessaryReturnIntention/description.html @@ -0,0 +1,5 @@ + + +This intention removes unnecessary 'return' keyword from return statement. + + \ No newline at end of file diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 7caedb96b48c..3e93d13252c4 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -401,7 +401,8 @@ - + @@ -1200,6 +1201,11 @@ intention.category.groovy/intention.category.groovy.style org.jetbrains.plugins.groovy.intentions.style.ConvertFromGeeseBracesIntention + + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle + intention.category.groovy/intention.category.groovy.style + org.jetbrains.plugins.groovy.intentions.style.RemoveUnnecessaryReturnIntention + org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle intention.category.groovy/intention.category.groovy.style @@ -1309,15 +1315,18 @@ + + + + - + getReassignedNames(final PsiElement scope) { + return CachedValuesManager.getManager(scope.getProject()).getCachedValue(scope, new CachedValueProvider>() { + @Nullable + @Override + public Result> compute() { + return Result.create(collectReassignedNames(scope), scope); + } + }); + } + + private static Set collectReassignedNames(PsiElement scope) { + final Set result = ContainerUtil.newHashSet(); + PsiTreeUtil.processElements(scope, new PsiElementProcessor() { @Override public boolean execute(@NotNull PsiElement element) { - if (element instanceof GrReferenceExpression && - var.getName().equals(((GrReferenceExpression)element).getReferenceName()) && - ((GrReferenceExpression)element).isReferenceTo(var)) { - if (PsiUtil.isLValue((GrReferenceExpression)element) || - element.getParent() instanceof GrUnaryExpression && ((GrUnaryExpression)element.getParent()).isPostfix()) { - if (hasAssignment) { - return false; + if (!(element instanceof GrReferenceExpression) || !((GrReferenceExpression)element).isQualified()) { + return true; + } + + GrReferenceExpression ref = (GrReferenceExpression)element; + if (isWriteAccess(ref)) { + String varName = ref.getReferenceName(); + if (!result.contains(varName)) { + PsiElement target = ref.resolve(); + if (target instanceof GrVariable && ((GrVariable)target).getInitializerGroovy() != null || + target instanceof GrParameter) { + result.add(varName); } - hasAssignment = true; } } return true; } }); + return result; + } + + private static boolean isWriteAccess(GrReferenceExpression element) { + return PsiUtil.isLValue(element) || + element.getParent() instanceof GrUnaryExpression && ((GrUnaryExpression)element.getParent()).isPostfix(); + } + + static boolean isReassigned(final GrVariable var) { + PsiMethod method = PsiTreeUtil.getParentOfType(var, PsiMethod.class); + PsiNamedElement scope = method == null ? var.getContainingFile() : method; + return scope != null && getReassignedNames(scope).contains(var.getName()); } @Nullable diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java index fe1848c7d26c..950801f7c875 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java @@ -130,6 +130,7 @@ public class GrMethodMayBeStaticInspection extends BaseInspection { GroovyPsiElement resolveContext = result.getCurrentFileResolveContext(); if (resolveContext != null) return; + if (element instanceof PsiClass && ((PsiClass)element).getContainingClass() == null) return; if (element instanceof PsiMember && !((PsiMember)element).hasModifierProperty(PsiModifier.STATIC)) { myMay = false; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerSettingsFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerSettingsFactory.java deleted file mode 100644 index 16b43c06ce0d..000000000000 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerSettingsFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy.compiler; - -import com.intellij.compiler.CompilerSettingsFactory; -import com.intellij.openapi.options.Configurable; -import com.intellij.openapi.project.Project; - -/** - * @author nik - */ -public class GroovyCompilerSettingsFactory implements CompilerSettingsFactory { - @Override - public Configurable create(Project project) { - return new GroovyCompilerConfigurable(project); - } -} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties index 424a55828ecb..b950eb295eb1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties @@ -177,4 +177,6 @@ gr.create.missing.switch.branches.intention.family.name=Create missing 'switch' remove.redundant.class.property.intention.name=Remove redundant .class remove.redundant.class.property.intention.family.name=Remove redundant .class convert.simple.getter.to.property.intention.name=Convert to property -convert.simple.getter.to.property.intention.family.name=Convert simple getter to property \ No newline at end of file +convert.simple.getter.to.property.intention.family.name=Convert simple getter to property +remove.unnecessary.return.intention.name=Remove 'return' keyword +remove.unnecessary.return.intention.family.name=Remove unnecessary 'return' keyword \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/RemoveUnnecessaryReturnIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/RemoveUnnecessaryReturnIntention.java new file mode 100644 index 000000000000..f02c0ce54ee3 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/RemoveUnnecessaryReturnIntention.java @@ -0,0 +1,51 @@ +/* + * 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 org.jetbrains.plugins.groovy.intentions.style; + +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.intentions.base.Intention; +import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; + +/** + * @author Max Medvedev + */ +public class RemoveUnnecessaryReturnIntention extends Intention { + @Override + protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException { + if (element instanceof GrReturnStatement && ((GrReturnStatement)element).getReturnValue() != null) { + GrExpression value = ((GrReturnStatement)element).getReturnValue(); + + ((GrReturnStatement)element).replaceWithStatement(value); + } + } + + @NotNull + @Override + protected PsiElementPredicate getElementPredicate() { + return new PsiElementPredicate() { + @Override + public boolean satisfiedBy(PsiElement element) { + return element instanceof GrReturnStatement && ((GrReturnStatement)element).getReturnValue() != null; + } + }; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java index 40e4154b8741..397989a17057 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java @@ -29,6 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Consumer; @@ -40,6 +41,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.lang.completion.handlers.AfterNewClassInsertHandler; +import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; @@ -48,9 +50,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; +import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.GroovyExpectedTypesProvider; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; -import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; @@ -220,7 +222,12 @@ public class GroovySmartCompletionContributor extends CompletionContributor { final GrExpression expression = PsiTreeUtil.getParentOfType(place, GrExpression.class); if (expression == null) return; - final Set types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression); + GrExpression placeToInferType = expression; + if (expression.getParent() instanceof GrApplicationStatement && expression.getParent().getParent() instanceof GrAssignmentExpression) { + placeToInferType = (GrExpression)expression.getParent(); + } + + final Set types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(placeToInferType); for (PsiType type : types) { if (type instanceof PsiArrayType) { final LookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place); @@ -271,9 +278,36 @@ public class GroovySmartCompletionContributor extends CompletionContributor { if (!(parent instanceof GrNewExpression)) return null; final PsiElement pparent = parent.getParent(); - if (!(pparent instanceof GrVariable)) return null; - return ((GrVariable)pparent).getDeclaredType(); + if (pparent instanceof GrVariable) { + return ((GrVariable)pparent).getDeclaredType(); + } + else if (pparent instanceof GrAssignmentExpression) { + GrAssignmentExpression assignment = (GrAssignmentExpression)pparent; + IElementType optoken = assignment.getOperationToken(); + + GrExpression lvalue = assignment.getLValue(); + GrExpression rvalue = assignment.getRValue(); + + if (parent == rvalue && optoken == GroovyTokenTypes.mASSIGN) { + return lvalue.getNominalType(); + } + } + else if (pparent instanceof GrApplicationStatement) { + PsiElement ppparent = pparent.getParent(); + if (ppparent instanceof GrAssignmentExpression) { + GrAssignmentExpression assignment = (GrAssignmentExpression)ppparent; + IElementType optoken = assignment.getOperationToken(); + + GrExpression lvalue = assignment.getLValue(); + GrExpression rvalue = assignment.getRValue(); + + if (pparent == rvalue && optoken == GroovyTokenTypes.mASSIGN) { + return lvalue.getNominalType(); + } + } + } + return null; } @Override 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 78ec639c9814..81ce946a69e8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java @@ -48,7 +48,6 @@ import com.intellij.openapi.util.Key; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiFile; import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.PsiTestUtil; @@ -184,7 +183,7 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC try { if (useJps()) { //noinspection ConstantConditions - touch(JavaPsiFacade.getInstance(getProject()).findClass(className).getContainingFile().getVirtualFile()); + touch(myFixture.getJavaFacade().findClass(className).getContainingFile().getVirtualFile()); } else { //noinspection ConstantConditions diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy index 0bb35e3f3243..6e09ae6a2c53 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy @@ -21,6 +21,7 @@ import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.completion.impl.CamelHumpMatcher import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementPresentation +import com.intellij.codeInsight.lookup.PsiTypeLookupItem import com.intellij.psi.codeStyle.CodeStyleSettingsManager import org.jetbrains.plugins.groovy.GroovyFileType import org.jetbrains.plugins.groovy.codeStyle.GroovyCodeStyleSettings @@ -1467,4 +1468,34 @@ class Inheritor extends Base { } ''') } + + void testDiamondCompletionInAssignmentCompletion() { + doSmartTest('''\ +class Foo {} + +Foo var +var = new +''', '''\ +class Foo {} + +Foo var +var = new Foo<>() +''') + } + + void testDiamondCompletionInAssignmentCompletion2() { + myFixture.with { + configureByText('_a.groovy', '''\ +class Foo {} + +Foo var +var = new Foo() +''') + complete(CompletionType.SMART) + assertEquals(1, lookupElements.length) + + assertInstanceOf(lookupElements[0], PsiTypeLookupItem) + assertTrue((lookupElements[0] as PsiTypeLookupItem).myDiamond) + } + } } \ No newline at end of file diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy index 6f3920de4994..a7ac8183e47b 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/inspections/GrMethodMayBeStaticTest.groovy @@ -70,4 +70,23 @@ class A { myFixture.enableInspections(GrMethodMayBeStaticInspection) myFixture.checkHighlighting(true, false, false) } + + void testOtherClasses() { + myFixture.with { + addFileToProject('Fooo.groovy', '''\ +class Fooo { + static def foo() {} +} +''') + configureByText('_.groovy', '''\ +class Bar { + static def abc() + def bar() { + abc() + Fooo.foo() + } +} +''') + } + } } diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java index 512fe5e493c0..1f6d426d799d 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/BaseSplitter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 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. @@ -38,7 +38,6 @@ public abstract class BaseSplitter implements Splitter { static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.inspections.BaseSplitter"); public static final int MIN_RANGE_LENGTH = 3; - public static final int MAX_RANGE_LENGTH = 50; protected static void addWord(@NotNull Consumer consumer, boolean ignore, @Nullable TextRange found) { @@ -92,7 +91,7 @@ public abstract class BaseSplitter implements Splitter { protected static boolean badSize(int from, int till) { int l = till - from; - return l <= MIN_RANGE_LENGTH || l>= MAX_RANGE_LENGTH; + return l <= MIN_RANGE_LENGTH; } @NotNull diff --git a/plugins/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java b/plugins/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java index b53f06356fcc..722d5350606f 100644 --- a/plugins/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java +++ b/plugins/spellchecker/testSrc/com/intellij/spellchecker/inspector/SplitterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -153,6 +153,12 @@ public class SplitterTest extends TestCase { String text = "/*special symbols*/"; correctListToCheck(CommentSplitter.getInstance(), text, "special", "symbols"); + text = "// comment line which spell check works: misttake"; + correctListToCheck(CommentSplitter.getInstance(), text, "comment", "line", "which", "spell", "check", "works", "misttake"); + + text = "// comment line which spell check not works: misttake"; + correctListToCheck(CommentSplitter.getInstance(), text, "comment", "line", "which", "spell", "check", "works", "misttake"); + } diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 93c161b20774..94e5f7dd7ebc 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -791,6 +791,7 @@ + diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index f2e51f14b8f3..c6cb740e58c8 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -253,9 +253,18 @@ - - + + + + + +