diff --git a/build/images/idea_CE128.png b/build/images/idea_CE128.png new file mode 100644 index 000000000000..5b04015a5588 Binary files /dev/null and b/build/images/idea_CE128.png differ diff --git a/build/images/idea_CE16.png b/build/images/idea_CE16.png new file mode 100644 index 000000000000..c0e931fc86c9 Binary files /dev/null and b/build/images/idea_CE16.png differ diff --git a/build/images/idea_CE32.png b/build/images/idea_CE32.png new file mode 100644 index 000000000000..0c94898e69fe Binary files /dev/null and b/build/images/idea_CE32.png differ diff --git a/build/images/idea_CE48.png b/build/images/idea_CE48.png new file mode 100644 index 000000000000..225733c00f1c Binary files /dev/null and b/build/images/idea_CE48.png differ diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant index 6669d456d1a4..0e087c7eacb1 100644 --- a/build/scripts/dist.gant +++ b/build/scripts/dist.gant @@ -196,6 +196,7 @@ def layoutLinux(Map args, String home, Paths paths) { fileset(dir: "$home/bin") { include(name: "*.*") } fileset(dir: "$home/bin/linux") { include(name: "*.*") } fileset(dir: "$home/bin/nix") { include(name: "*.*") } + fileset(dir: "$home/build/images") } } diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index aa04a6162433..587e5e8a14a7 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -269,6 +269,17 @@ def layoutFull(String home, String targetDirectory) { } + dir("xpath") { + dir("lib") { + jar("xpath.jar") {noResources("xpath")} + resources("xpath") + + dir("rt") { + jar("xslt-rt.jar") {module("xslt-rt")} + } + } + } + dir("Groovy") { dir("lib") { jar("Groovy.jar") { diff --git a/community-main.iml b/community-main.iml index 4957741c816a..e984246e74c7 100644 --- a/community-main.iml +++ b/community-main.iml @@ -76,6 +76,7 @@ + diff --git a/images/src/META-INF/ImagesPlugin.xml b/images/src/META-INF/ImagesPlugin.xml index 8ff4e61b7bea..989297b32af5 100644 --- a/images/src/META-INF/ImagesPlugin.xml +++ b/images/src/META-INF/ImagesPlugin.xml @@ -27,7 +27,7 @@ - diff --git a/images/src/org/intellij/images/actions/EditExternallyAction.java b/images/src/org/intellij/images/actions/EditExternallyAction.java new file mode 100644 index 000000000000..795cd0ba873e --- /dev/null +++ b/images/src/org/intellij/images/actions/EditExternallyAction.java @@ -0,0 +1,124 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.intellij.images.actions; + +import com.intellij.execution.ExecutionException; +import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.openapi.actionSystem.ActionPlaces; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.EnvironmentUtil; +import org.intellij.images.ImagesBundle; +import org.intellij.images.fileTypes.ImageFileTypeManager; +import org.intellij.images.options.Options; +import org.intellij.images.options.OptionsManager; +import org.intellij.images.options.impl.OptionsConfigurabe; + +import java.io.File; +import java.util.Map; +import java.util.Set; + +/** + * Open image file externally. + * + * @author Alexey Efimov + */ +public final class EditExternallyAction extends AnAction { + public void actionPerformed(AnActionEvent e) { + Project project = e.getData(PlatformDataKeys.PROJECT); + VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); + Options options = OptionsManager.getInstance().getOptions(); + String executablePath = options.getExternalEditorOptions().getExecutablePath(); + if (StringUtil.isEmpty(executablePath)) { + Messages.showErrorDialog(project, + ImagesBundle.message("error.empty.external.editor.path"), + ImagesBundle.message("error.title.empty.external.editor.path")); + OptionsConfigurabe.show(project); + } + else { + if (files != null) { + Map env = EnvironmentUtil.getEnviromentProperties(); + Set varNames = env.keySet(); + for (String varName : varNames) { + if (SystemInfo.isWindows) { + executablePath = StringUtil.replace(executablePath, "%" + varName + "%", env.get(varName), true); + } + else { + executablePath = StringUtil.replace(executablePath, "${" + varName + "}", env.get(varName), false); + } + } + executablePath = FileUtil.toSystemDependentName(executablePath); + File executable = new File(executablePath); + GeneralCommandLine commandLine = new GeneralCommandLine(); + commandLine.setExePath(executable.exists() ? executable.getAbsolutePath() : executablePath); + ImageFileTypeManager typeManager = ImageFileTypeManager.getInstance(); + for (VirtualFile file : files) { + if (file.isInLocalFileSystem() && typeManager.isImage(file)) { + commandLine.addParameter(VfsUtil.virtualToIoFile(file).getAbsolutePath()); + } + } + commandLine.setWorkingDirectory(new File(executablePath).getParentFile()); + + try { + commandLine.createProcess(); + } + catch (ExecutionException ex) { + Messages.showErrorDialog(project, + ex.getLocalizedMessage(), + ImagesBundle.message("error.title.launching.external.editor")); + OptionsConfigurabe.show(project); + } + } + } + } + + public void update(AnActionEvent e) { + super.update(e); + + VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); + final boolean isEnabled = isImages(files); + if (e.getPlace().equals(ActionPlaces.PROJECT_VIEW_POPUP)) { + e.getPresentation().setVisible(isEnabled); + } + else { + e.getPresentation().setEnabled(isEnabled); + } + } + + private static boolean isImages(VirtualFile[] files) { + boolean isImagesFound = false; + if (files != null) { + ImageFileTypeManager typeManager = ImageFileTypeManager.getInstance(); + for (VirtualFile file : files) { + boolean isImage = typeManager.isImage(file); + isImagesFound |= isImage; + if (!file.isInLocalFileSystem() || !isImage) { + return false; + } + } + } + return isImagesFound; + } +} diff --git a/images/src/org/intellij/images/actions/EditExternalyAction.java b/images/src/org/intellij/images/actions/EditExternalyAction.java deleted file mode 100644 index 3399c400a95d..000000000000 --- a/images/src/org/intellij/images/actions/EditExternalyAction.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** $Id$ */ - -package org.intellij.images.actions; - -import com.intellij.openapi.actionSystem.ActionPlaces; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.EnvironmentUtil; -import org.intellij.images.ImagesBundle; -import org.intellij.images.fileTypes.ImageFileTypeManager; -import org.intellij.images.options.Options; -import org.intellij.images.options.OptionsManager; -import org.intellij.images.options.impl.OptionsConfigurabe; - -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.Set; - -/** - * Open image file externaly. - * - * @author Alexey Efimov - */ -public final class EditExternalyAction extends AnAction { - public void actionPerformed(AnActionEvent e) { - Project project = e.getData(PlatformDataKeys.PROJECT); - VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); - Options options = OptionsManager.getInstance().getOptions(); - String executablePath = options.getExternalEditorOptions().getExecutablePath(); - if (StringUtil.isEmpty(executablePath)) { - Messages.showErrorDialog(project, - ImagesBundle.message("error.empty.external.editor.path"), - ImagesBundle.message("error.title.empty.external.editor.path")); - OptionsConfigurabe.show(project); - } else { - if (files != null) { - Map env = EnvironmentUtil.getEnviromentProperties(); - Set varNames = env.keySet(); - for (String varName : varNames) { - if (SystemInfo.isWindows) { - executablePath = StringUtil.replace(executablePath, "%" + varName + "%", env.get(varName), true); - } else { - executablePath = StringUtil.replace(executablePath, "${" + varName + "}", env.get(varName), false); - } - } - executablePath = FileUtil.toSystemDependentName(executablePath); - File executable = new File(executablePath); - StringBuffer commandLine = new StringBuffer(executable.exists() ? executable.getAbsolutePath() : executablePath); - ImageFileTypeManager typeManager = ImageFileTypeManager.getInstance(); - for (VirtualFile file : files) { - if (file.isInLocalFileSystem() && typeManager.isImage(file)) { - commandLine.append(" \""); - commandLine.append(VfsUtil.virtualToIoFile(file).getAbsolutePath()); - commandLine.append('\"'); - } - } - - try { - File executableFile = new File(executablePath); - Runtime.getRuntime().exec(commandLine.toString(), null, executableFile.getParentFile()); - } catch (IOException ex) { - Messages.showErrorDialog(project, - ex.getLocalizedMessage(), - ImagesBundle.message("error.title.launching.external.editor")); - OptionsConfigurabe.show(project); - } - } - } - } - - public void update(AnActionEvent e) { - super.update(e); - - VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); - final boolean isEnabled = isImages(files); - if (e.getPlace().equals(ActionPlaces.PROJECT_VIEW_POPUP)) { - e.getPresentation().setVisible(isEnabled); - } - else { - e.getPresentation().setEnabled(isEnabled); - } - } - - private static boolean isImages(VirtualFile[] files) { - boolean isImagesFound = false; - if (files != null) { - ImageFileTypeManager typeManager = ImageFileTypeManager.getInstance(); - for (VirtualFile file : files) { - boolean isImage = typeManager.isImage(file); - isImagesFound |= isImage; - if (!file.isInLocalFileSystem() || !isImage) { - return false; - } - } - } - return isImagesFound; - } -} diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java b/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java index 80dae42cb5e6..c7e1a8d20a50 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java @@ -180,7 +180,7 @@ public class BuildPropertiesImpl extends BuildProperties { } } - final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); add(new Property(PROPERTY_PROJECT_JDK_HOME, projectJdk != null ? propertyRef(getJdkHomeProperty(projectJdk.getName())) : ""), 1); add(new Property(PROPERTY_PROJECT_JDK_BIN, projectJdk != null ? propertyRef(getJdkBinProperty(projectJdk.getName())) : "")); add(new Property(PROPERTY_PROJECT_JDK_CLASSPATH, projectJdk != null ? getJdkPathId(projectJdk.getName()) : "")); 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 352d23205fdc..e75f0e7a3803 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -736,7 +736,7 @@ public class CompileDriver { boolean didSomething = false; final CompilerManager compilerManager = CompilerManager.getInstance(myProject); - GenericCompilerRunner runner = new GenericCompilerRunner(context, compilerManager, isRebuild, onlyCheckStatus); + GenericCompilerRunner runner = new GenericCompilerRunner(context, myCompilerFilter, compilerManager, isRebuild, onlyCheckStatus); try { didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus); @@ -963,6 +963,7 @@ public class CompileDriver { final DumbService dumbService = DumbService.getInstance(myProject); try { + final Set processedModules = new HashSet(); VirtualFile[] snapshot = null; final Map, Collection> chunkMap = new HashMap, Collection>(); int total = 0; @@ -1054,7 +1055,16 @@ public class CompileDriver { filesToRecompile.addAll(compiledWithErrors); dependentFiles = CacheUtils.findDependentFiles(context, compiledWithSuccess, dependencyFilter); - + if (!processedModules.isEmpty()) { + for (Iterator it = dependentFiles.iterator(); it.hasNext();) { + final VirtualFile next = it.next(); + final Module module = context.getModuleByFile(next); + if (module != null && processedModules.contains(module)) { + it.remove(); + } + } + } + if (ourDebugMode) { if (!dependentFiles.isEmpty()) { for (VirtualFile dependentFile : dependentFiles) { @@ -1102,7 +1112,7 @@ public class CompileDriver { indicator.setText(CompilerBundle.message("progress.saving.caches")); cache.resetState(); - + processedModules.addAll(currentChunk.getNodes()); indicator.popState(); } } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java b/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java index 8b7a773bc0b6..341f8a7eef1a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/GenericCompilerRunner.java @@ -52,11 +52,15 @@ public class GenericCompilerRunner { private final GenericCompiler[] myCompilers; private final Project myProject; - public GenericCompilerRunner(CompileContext context, CompilerManager compilerManager, boolean forceCompile, boolean onlyCheckStatus) { + public GenericCompilerRunner(CompileContext context, + CompilerFilter compilerFilter, + CompilerManager compilerManager, + boolean forceCompile, + boolean onlyCheckStatus) { myContext = context; myForceCompile = forceCompile; myOnlyCheckStatus = onlyCheckStatus; - myCompilers = compilerManager.getCompilers(GenericCompiler.class); + myCompilers = compilerManager.getCompilers(GenericCompiler.class, compilerFilter); myProject = myContext.getProject(); } 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 87990a318c5c..6a87175f4712 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/JavaCompilersTab.java @@ -18,6 +18,7 @@ package com.intellij.compiler.options; import com.intellij.compiler.CompilerConfiguration; import com.intellij.compiler.CompilerConfigurationImpl; import com.intellij.compiler.impl.javaCompiler.BackendCompiler; +import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.compiler.CompilerBundle; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; @@ -63,12 +64,10 @@ public class JavaCompilersTab implements SearchableConfigurable { myContentPanel.add(configurable.createComponent(), compiler.getId()); } myCompiler.setModel(new DefaultComboBoxModel(new Vector(compilers))); - myCompiler.setRenderer(new DefaultListCellRenderer(){ - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - JLabel component = (JLabel)super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - final String presentableName = value != null? ((BackendCompiler)value).getPresentableName() : ""; - component.setText(presentableName); - return component; + myCompiler.setRenderer(new ListCellRendererWrapper(myCompiler.getRenderer()) { + @Override + public void customize(final JList list, final BackendCompiler value, final int index, final boolean selected, final boolean hasFocus) { + setText(value != null ? value.getPresentableName() : ""); } }); myCompiler.addActionListener(new ActionListener() { diff --git a/java/execution/impl/src/com/intellij/execution/util/JreVersionDetector.java b/java/execution/impl/src/com/intellij/execution/util/JreVersionDetector.java index 102cb438a332..feaa6a69c22c 100644 --- a/java/execution/impl/src/com/intellij/execution/util/JreVersionDetector.java +++ b/java/execution/impl/src/com/intellij/execution/util/JreVersionDetector.java @@ -49,7 +49,7 @@ public class JreVersionDetector { return isJre50(jdk); } - final Sdk projectJdk = ProjectRootManager.getInstance(configuration.getProject()).getProjectJdk(); + final Sdk projectJdk = ProjectRootManager.getInstance(configuration.getProject()).getProjectSdk(); return isJre50(projectJdk); } } diff --git a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java index 3a55f74021bd..d6fc7c720a39 100644 --- a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java +++ b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java @@ -19,6 +19,7 @@ */ package com.intellij.ide.impl; +import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; import com.intellij.ide.util.newProjectWizard.AddModuleWizard; import com.intellij.ide.util.projectWizard.ProjectBuilder; @@ -177,7 +178,7 @@ public class NewProjectUtil { if (versionString == null) return; ProjectRootManagerEx rootManager = ProjectRootManagerEx.getInstanceEx(project); - rootManager.setProjectJdk(jdk); + rootManager.setProjectSdk(jdk); LanguageLevel level = LanguageLevelUtil.getDefaultLanguageLevel(versionString); LanguageLevelProjectExtension ext = LanguageLevelProjectExtension.getInstance(project); if (level.compareTo(ext.getLanguageLevel()) < 0) { @@ -188,13 +189,16 @@ public class NewProjectUtil { public static void closePreviousProject(final Project projectToClose) { Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length > 0) { - int exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.new.project"), - new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1, 0, - Messages.getQuestionIcon()); + final GeneralSettings settings = GeneralSettings.getInstance(); + int exitCode = settings.getConfirmOpenNewProject(); + if (exitCode < 0) { + exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.new.project"), + new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe")}, 1, 0, + Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption()); + } if (exitCode == 1) { // "No" option ProjectUtil.closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]); } } } - } diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java index e0be57f7cafa..de335bac90a7 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddModuleWizard.java @@ -301,7 +301,7 @@ public class AddModuleWizard extends AbstractWizard { return context.getProjectJdk(); } final Project project = context.getProject() == null ? ProjectManager.getInstance().getDefaultProject() : context.getProject(); - final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); if (projectJdk != null) { return projectJdk; } 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 3fd85200e823..adcef1334736 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 @@ -223,14 +223,14 @@ public class JdkChooserPanel extends JPanel { } public static Sdk chooseAndSetJDK(final Project project) { - final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + final Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); final Sdk jdk = showDialog(project, ProjectBundle.message("module.libraries.target.jdk.select.title"), WindowManagerEx.getInstanceEx().getFrame(project), projectJdk); if (jdk == null) { return null; } ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { - ProjectRootManager.getInstance(project).setProjectJdk(jdk); + ProjectRootManager.getInstance(project).setProjectSdk(jdk); } }); return jdk; diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java index 4681a04b372f..0b562dff41a0 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java @@ -149,7 +149,7 @@ public class ProjectJdkForModuleStep extends ModuleWizardStep { @Nullable private static Sdk getDefaultJdk() { Project defaultProject = ProjectManagerEx.getInstanceEx().getDefaultProject(); - return ProjectRootManagerEx.getInstanceEx(defaultProject).getProjectJdk(); + return ProjectRootManagerEx.getInstanceEx(defaultProject).getProjectSdk(); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdkConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdkConfigurable.java index 5567ef30be8d..f03f13b0b953 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdkConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectJdkConfigurable.java @@ -86,7 +86,7 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable { myFreeze = true; final Sdk projectJdk = myJdksModel.getProjectSdk(); myCbProjectJdk.reloadModel(new JdkComboBox.NoneJdkComboBoxItem(), myProject); - final String sdkName = projectJdk == null ? ProjectRootManager.getInstance(myProject).getProjectJdkName() : projectJdk.getName(); + final String sdkName = projectJdk == null ? ProjectRootManager.getInstance(myProject).getProjectSdkName() : projectJdk.getName(); if (sdkName != null) { final Sdk jdk = myJdksModel.findSdk(sdkName); if (jdk != null) { @@ -135,18 +135,18 @@ public class ProjectJdkConfigurable implements UnnamedConfigurable { } public boolean isModified() { - final Sdk projectJdk = ProjectRootManager.getInstance(myProject).getProjectJdk(); + final Sdk projectJdk = ProjectRootManager.getInstance(myProject).getProjectSdk(); return !Comparing.equal(projectJdk, getSelectedProjectJdk()); } public void apply() throws ConfigurationException { - ProjectRootManager.getInstance(myProject).setProjectJdk(getSelectedProjectJdk()); + ProjectRootManager.getInstance(myProject).setProjectSdk(getSelectedProjectJdk()); } public void reset() { reloadModel(); - final String sdkName = ProjectRootManager.getInstance(myProject).getProjectJdkName(); + final String sdkName = ProjectRootManager.getInstance(myProject).getProjectSdkName(); if (sdkName != null) { final Sdk jdk = myJdksModel.findSdk(sdkName); if (jdk != null) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java index 54ea7528ab27..859119b9cf22 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/UIRootConfigurationAccessor.java @@ -72,7 +72,7 @@ public class UIRootConfigurationAccessor extends RootConfigurationAccessor { @Nullable public String getProjectSdkName(final Project project) { - final String projectJdkName = ProjectRootManager.getInstance(project).getProjectJdkName(); + final String projectJdkName = ProjectRootManager.getInstance(project).getProjectSdkName(); final Sdk projectJdk = getProjectSdk(project); if (projectJdk != null) { return projectJdk.getName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/NewLibraryChooser.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/NewLibraryChooser.java index 960a5bdfb5aa..47dbf09ba63c 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/NewLibraryChooser.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/NewLibraryChooser.java @@ -25,6 +25,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.roots.ui.configuration.libraryEditor.CreateNewLibraryDialog; +import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; import javax.swing.*; @@ -61,13 +62,13 @@ class NewLibraryChooser implements ClasspathElementChooser { List tables = Arrays.asList(myRootModel.getModuleLibraryTable(), registrar.getLibraryTable(myProject), registrar.getLibraryTable()); - CreateNewLibraryDialog dialog = CreateNewLibraryDialog.createDialog(myParentComponent, myProject, tables, 1); + CreateNewLibraryDialog dialog = new CreateNewLibraryDialog(myParentComponent, myContext, new NewLibraryEditor(), tables, 1); final Module contextModule = DataKeys.MODULE_CONTEXT.getData(DataManager.getInstance().getDataContext(myParentComponent)); dialog.addFileChooserContext(LangDataKeys.MODULE_CONTEXT, contextModule); dialog.show(); myIsOk = dialog.isOK(); if (myIsOk) { - myChosenLibrary = dialog.createLibrary(myContext.getModifiableLibraryTable(dialog.getSelectedTable())); + myChosenLibrary = dialog.createLibrary(); } else { myChosenLibrary = null; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraries/CreateCustomLibraryAction.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraries/CreateCustomLibraryAction.java index 6fab61fa26ba..89e5ef6f9b26 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraries/CreateCustomLibraryAction.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraries/CreateCustomLibraryAction.java @@ -64,10 +64,10 @@ public class CreateCustomLibraryAction extends CustomLibraryActionBase { LibraryTablesRegistrar registrar = LibraryTablesRegistrar.getInstance(); final Project project = myContext.getProject(); final List tables = Arrays.asList(registrar.getLibraryTable(project), registrar.getLibraryTable()); - final CreateNewLibraryDialog dialog = new CreateNewLibraryDialog(myModuleStructureConfigurable.getTree(), project, libraryEditor, tables, 0); + final CreateNewLibraryDialog dialog = new CreateNewLibraryDialog(myModuleStructureConfigurable.getTree(), myContext, libraryEditor, tables, 0); dialog.show(); if (dialog.isOK()) { - final Library library = dialog.createLibrary(myContext.getModifiableLibraryTable(dialog.getSelectedTable())); + final Library library = dialog.createLibrary(); final ModifiableRootModel rootModel = myContext.getModulesConfigurator().getOrCreateModuleEditor(myModule).getModifiableRootModelProxy(); if (!askAndRemoveDuplicatedLibraryEntry(myCreator.getDescription(), rootModel)) { return; diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java index 3a01e7c716e5..c953df9490ed 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java @@ -17,13 +17,12 @@ package com.intellij.openapi.roots.ui.configuration.libraryEditor; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; -import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; import com.intellij.openapi.ui.ComboBox; import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -33,18 +32,14 @@ import java.util.List; * @author nik */ public class CreateNewLibraryDialog extends LibraryEditorDialogBase { + private final StructureConfigurableContext myContext; private NewLibraryEditor myLibraryEditor; private ComboBox myLibraryLevelCombobox; - public static CreateNewLibraryDialog createDialog(JComponent parent, @Nullable Project project, - @NotNull List libraryTables, - int selectedTable) { - return new CreateNewLibraryDialog(parent, project, new NewLibraryEditor(), libraryTables, selectedTable); - } - - public CreateNewLibraryDialog(@NotNull JComponent parent, @Nullable Project project, @NotNull NewLibraryEditor libraryEditor, + public CreateNewLibraryDialog(@NotNull JComponent parent, @NotNull StructureConfigurableContext context, @NotNull NewLibraryEditor libraryEditor, @NotNull List libraryTables, int selectedTable) { - super(parent, new LibraryRootsComponent(project, libraryEditor)); + super(parent, new LibraryRootsComponent(context.getProject(), libraryEditor)); + myContext = context; myLibraryEditor = libraryEditor; final DefaultComboBoxModel model = new DefaultComboBoxModel(); for (LibraryTable table : libraryTables) { @@ -65,11 +60,14 @@ public class CreateNewLibraryDialog extends LibraryEditorDialogBase { init(); } - public LibraryTable getSelectedTable() { - return (LibraryTable)myLibraryLevelCombobox.getSelectedItem(); + @NotNull @Override + protected LibraryTable.ModifiableModel getTableModifiableModel() { + final LibraryTable selectedTable = (LibraryTable)myLibraryLevelCombobox.getSelectedItem(); + return myContext.getModifiableLibraryTable(selectedTable); } - public Library createLibrary(final @NotNull LibraryTable.ModifiableModel modifiableModel) { + public Library createLibrary() { + final LibraryTable.ModifiableModel modifiableModel = getTableModifiableModel(); final Library library = modifiableModel.createLibrary(myLibraryEditor.getName()); final Library.ModifiableModel model = library.getModifiableModel(); myLibraryEditor.apply(model); @@ -85,4 +83,8 @@ public class CreateNewLibraryDialog extends LibraryEditorDialogBase { protected void addNorthComponents(FormBuilder formBuilder) { formBuilder.addLabeledComponent("Level:", myLibraryLevelCombobox); } + + protected boolean shouldCheckName(String newName) { + return true; + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java index 5c5665f4a10b..3f9b53b76455 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java @@ -20,6 +20,7 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.ui.configuration.LibraryTableModifiableModelProvider; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesModifiableModel; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.Nullable; @@ -79,4 +80,8 @@ public class EditExistingLibraryDialog extends LibraryEditorDialogBase { protected LibraryTable.ModifiableModel getTableModifiableModel() { return myTableModifiableModel; } + + protected boolean shouldCheckName(String newName) { + return !Comparing.equal(newName, getLibraryRootsComponent().getLibraryEditor().getName()); + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditorDialogBase.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditorDialogBase.java index a344d339f2f2..fa0e0dcb770d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditorDialogBase.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryEditorDialogBase.java @@ -22,7 +22,6 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.ui.configuration.libraries.LibraryEditingUtil; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; import com.intellij.util.ui.FormBuilder; import org.jetbrains.annotations.Nullable; @@ -65,12 +64,11 @@ public abstract class LibraryEditorDialogBase extends DialogWrapper { } protected boolean validateAndApply() { - final String currentName = myLibraryRootsComponent.getLibraryEditor().getName(); String newName = myNameField.getText().trim(); if (newName.length() == 0) { newName = null; } - if (!Comparing.equal(newName, currentName)) { + if (shouldCheckName(newName)) { final LibraryTable.ModifiableModel tableModifiableModel = getTableModifiableModel(); if (tableModifiableModel != null && !(tableModifiableModel instanceof ModuleLibraryTable)) { if (newName == null) { @@ -88,11 +86,17 @@ public abstract class LibraryEditorDialogBase extends DialogWrapper { return true; } + protected abstract boolean shouldCheckName(String newName); + @Nullable protected LibraryTable.ModifiableModel getTableModifiableModel() { return null; } + protected LibraryRootsComponent getLibraryRootsComponent() { + return myLibraryRootsComponent; + } + protected JComponent createNorthPanel() { FormBuilder formBuilder = new FormBuilder(); String currentName = myLibraryRootsComponent.getLibraryEditor().getName(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/JdkListConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/JdkListConfigurable.java index 86b664d45b3d..ab2fc0aaca2d 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/JdkListConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/JdkListConfigurable.java @@ -168,7 +168,7 @@ public class JdkListConfigurable extends BaseStructureConfigurable { } if (myJdksTreeModel.isModified() || modifiedJdks) myJdksTreeModel.apply(this); - myJdksTreeModel.setProjectSdk(ProjectRootManager.getInstance(myProject).getProjectJdk()); + myJdksTreeModel.setProjectSdk(ProjectRootManager.getInstance(myProject).getProjectSdk()); } public boolean isModified() { diff --git a/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java b/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java index 0959dab65992..78dcfe8985fa 100644 --- a/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java +++ b/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java @@ -124,7 +124,7 @@ public abstract class ProjectOpenProcessorBase extends ProjectOpenProcessor { wizardContext.setProjectFileDirectory(virtualFile.getParent().getPath()); Project defaultProject = ProjectManager.getInstance().getDefaultProject(); - Sdk jdk = ProjectRootManager.getInstance(defaultProject).getProjectJdk(); + Sdk jdk = ProjectRootManager.getInstance(defaultProject).getProjectSdk(); if (jdk == null) { jdk = ProjectJdkTable.getInstance().findMostRecentSdkOfType(JavaSdk.getInstance()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java index 66553f60c997..9cf11d9e68c3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java @@ -110,7 +110,7 @@ public class IncreaseLanguageLevelFix implements IntentionAction { @Nullable private static Sdk getRelevantJdk(final Project project, @Nullable Module module) { - Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); Sdk moduleJdk = module == null ? null : ModuleRootManager.getInstance(module).getSdk(); return moduleJdk == null ? projectJdk : moduleJdk; } diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java index d48f6da93786..c739d62cbf07 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java @@ -120,7 +120,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext if (isBadSdk(project, modules)) { System.err.println(InspectionsBundle.message("inspection.no.jdk.error.message")); System.err.println( - InspectionsBundle.message("offline.inspections.jdk.not.found", ProjectRootManager.getInstance(project).getProjectJdkName())); + InspectionsBundle.message("offline.inspections.jdk.not.found", ProjectRootManager.getInstance(project).getProjectSdkName())); return false; } for (Module module : modules) { @@ -152,7 +152,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext private static boolean isBadSdk(final Project project, final Module[] modules) { boolean anyModuleAcceptsSdk = false; boolean anyModuleUsesProjectSdk = false; - Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectJdk(); + Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectSdk(); for (Module module : modules) { if (ModuleRootManager.getInstance(module).isSdkInherited()) { anyModuleUsesProjectSdk = true; diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java index 61d8fe8e56d1..5642a0cde178 100644 --- a/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java @@ -15,15 +15,14 @@ */ package com.intellij.codeInspection.internal; -import com.intellij.codeInspection.BaseJavaLocalInspectionTool; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -import javax.swing.DefaultListCellRenderer; +import javax.swing.*; -public class GtkPreferredJComboBoxRendererInspection extends BaseJavaLocalInspectionTool { +public class GtkPreferredJComboBoxRendererInspection extends InternalInspection { private static final String RENDERER_CLASS_NAME = DefaultListCellRenderer.class.getName(); private static final String MESSAGE = "Please use ListCellRendererWrapper instead to prevent artifacts under GTK+ Look and Feel."; diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java new file mode 100644 index 000000000000..ef7124f6101a --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java @@ -0,0 +1,52 @@ +/* + * 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.codeInspection.internal; + +import com.intellij.codeInspection.BaseJavaLocalInspectionTool; +import com.intellij.codeInspection.LocalInspectionToolSession; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.ui.components.JBList; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +public abstract class InternalInspection extends BaseJavaLocalInspectionTool { + @Nls + @NotNull + @Override + public String getGroupDisplayName() { + return InternalInspectionToolsProvider.GROUP_NAME; + } + + public boolean isEnabledByDefault() { + return true; + } + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, + boolean isOnTheFly, + LocalInspectionToolSession session) { + if (JavaPsiFacade.getInstance(holder.getProject()).findClass(JBList.class.getName(), + GlobalSearchScope.allScope(holder.getProject())) == null) { + return new PsiElementVisitor() { + }; + } + return super.buildVisitor(holder, isOnTheFly, session); + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java index e06b26509aae..8d8e510e20b3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java @@ -15,7 +15,6 @@ */ package com.intellij.codeInspection.internal; -import com.intellij.codeInspection.BaseJavaLocalInspectionTool; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.application.QueryExecutorBase; @@ -32,7 +31,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Map; -public class UndesirableClassUsageInspection extends BaseJavaLocalInspectionTool { +public class UndesirableClassUsageInspection extends InternalInspection { private static final Map CLASSES = new THashMap(); static { @@ -43,13 +42,6 @@ public class UndesirableClassUsageInspection extends BaseJavaLocalInspectionTool CLASSES.put(QueryExecutor.class.getName(), QueryExecutorBase.class.getName()); } - @Nls - @NotNull - @Override - public String getGroupDisplayName() { - return InternalInspectionToolsProvider.GROUP_NAME; - } - @Nls @NotNull @Override @@ -63,10 +55,6 @@ public class UndesirableClassUsageInspection extends BaseJavaLocalInspectionTool return "UndesirableClassUsage"; } - public boolean isEnabledByDefault() { - return true; - } - @NotNull public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { return new JavaElementVisitor() { diff --git a/java/java-impl/src/com/intellij/lang/java/JavaParserDefinition.java b/java/java-impl/src/com/intellij/lang/java/JavaParserDefinition.java index ea1bfcf09b5b..843d1d396445 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaParserDefinition.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaParserDefinition.java @@ -40,7 +40,7 @@ import org.jetbrains.annotations.NotNull; * @author max */ public class JavaParserDefinition implements ParserDefinition { - public static boolean USE_NEW_PARSER = false; + public static boolean USE_NEW_PARSER = true; @NotNull public Lexer createLexer(final Project project) { diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java index 73db68d9c3d5..d2c94200f5c5 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java @@ -931,10 +931,20 @@ public class JavaCodeStyleManagerImpl extends JavaCodeStyleManager { } @NotNull - public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo, PsiElement place, boolean lookForward) { + public SuggestedNameInfo suggestUniqueVariableName(@NotNull final SuggestedNameInfo baseNameInfo, + PsiElement place, + boolean ignorePlaceName, + boolean lookForward) { final String[] names = baseNameInfo.names; final LinkedHashSet uniqueNames = new LinkedHashSet(names.length); for (String name : names) { + if (ignorePlaceName && place instanceof PsiNamedElement) { + final String placeName = ((PsiNamedElement)place).getName(); + if (Comparing.strEqual(placeName, name)) { + uniqueNames.add(name); + continue; + } + } uniqueNames.add(suggestUniqueVariableName(name, place, lookForward)); } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java index a1ca04bcbb73..57edcb31b47b 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureHandler.java @@ -46,6 +46,12 @@ public class JavaChangeSignatureHandler implements ChangeSignatureHandler { private static void invokeOnElement(Project project, Editor editor, PsiElement element) { if (element instanceof PsiMethod) { + final ChangeSignatureGestureDetector detector = ChangeSignatureGestureDetector.getInstance(project); + final PsiIdentifier nameIdentifier = ((PsiMethod)element).getNameIdentifier(); + if (nameIdentifier != null && detector.isChangeSignatureAvailable(nameIdentifier)) { + detector.changeSignature(element.getContainingFile()); + return; + } invoke((PsiMethod) element, project, editor); } else if (element instanceof PsiClass) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index b1fdfebdcc98..2bd2bb57b300 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -462,6 +462,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme final IntroduceVariableSettings settings = getSettings(project, editor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, choice); if (!settings.isOK()) return; + final SuggestedNameInfo suggestedName = getSuggestedName(typeSelectorManager.getDefaultType(), expr); final Runnable runnable = introduce(project, expr, editor, anchorStatement, tempContainer, occurrences, anchorStatementIfAll, settings, variable); CommandProcessor.getInstance().executeCommand( @@ -473,7 +474,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme PsiVariable elementToRename = variable.get().getElement(); if (elementToRename != null) { editor.getCaretModel().moveToOffset(elementToRename.getTextOffset()); - new VariableInplaceRenamer(elementToRename, editor).performInplaceRename(false); + new VariableInplaceRenamer(elementToRename, editor).performInplaceRename(false, new LinkedHashSet(Arrays.asList(suggestedName.names))); } } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java index d281d4a9c073..9ce3d058fb46 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableDialog.java @@ -170,11 +170,7 @@ class IntroduceVariableDialog extends DialogWrapper implements IntroduceVariable myNameSuggestionsManager = new NameSuggestionsManager(myTypeSelector, myNameField, new NameSuggestionsGenerator() { public SuggestedNameInfo getSuggestedNameInfo(PsiType type) { - final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject); - final SuggestedNameInfo nameInfo = codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, myExpression, type); - final String[] strings = JavaCompletionUtil.completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, nameInfo); - final SuggestedNameInfo.Delegate delegate = new SuggestedNameInfo.Delegate(strings, nameInfo); - return codeStyleManager.suggestUniqueVariableName(delegate, myExpression, true); + return IntroduceVariableBase.getSuggestedName(type, myExpression); } }); myNameSuggestionsManager.setLabelsFor(type, namePrompt); diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java index 8b472d7ee4f7..b04911d0d26c 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaNameSuggestionProvider.java @@ -38,7 +38,7 @@ public class JavaNameSuggestionProvider implements NameSuggestionProvider { String initialName = UsageViewUtil.getShortName(element); SuggestedNameInfo info = suggestNamesForElement(element); if (info != null) { - info = JavaCodeStyleManager.getInstance(element.getProject()).suggestUniqueVariableName(info, element, true); + info = JavaCodeStyleManager.getInstance(element.getProject()).suggestUniqueVariableName(info, element, true, true); } String parameterName = null; diff --git a/java/java-tests/testData/codeInsight/invertIfCondition/afterSCR2542.java b/java/java-tests/testData/codeInsight/invertIfCondition/afterSCR2542.java index 3a9ca8c41b6f..17bec6b8b332 100644 --- a/java/java-tests/testData/codeInsight/invertIfCondition/afterSCR2542.java +++ b/java/java-tests/testData/codeInsight/invertIfCondition/afterSCR2542.java @@ -4,7 +4,7 @@ class TestInvertIf { void invertIf(Object object) { if (object != "adf") { System.out.println("1"); - } // comment + } // comment else { System.out.println("2"); } diff --git a/java/java-tests/testSrc/com/intellij/roots/InheritedJdkTest.java b/java/java-tests/testSrc/com/intellij/roots/InheritedJdkTest.java index 9f5b1ec53efc..06b4794a65ac 100644 --- a/java/java-tests/testSrc/com/intellij/roots/InheritedJdkTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/InheritedJdkTest.java @@ -34,7 +34,7 @@ public class InheritedJdkTest extends ModuleTestCase { @Override public void run() { final ProjectRootManagerEx rootManagerEx = ProjectRootManagerEx.getInstanceEx(myProject); - rootManagerEx.setProjectJdkName(jdk.getName()); + rootManagerEx.setProjectSdkName(jdk.getName()); final ModifiableRootModel rootModel = rootManager.getModifiableModel(); rootModel.inheritSdk(); rootModel.commit(); @@ -102,7 +102,7 @@ public class InheritedJdkTest extends ModuleTestCase { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - projectRootManager.setProjectJdk(mockJdk); + projectRootManager.setProjectSdk(mockJdk); } }); @@ -112,7 +112,7 @@ public class InheritedJdkTest extends ModuleTestCase { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - projectRootManager.setProjectJdkName("jdk1"); + projectRootManager.setProjectSdkName("jdk1"); } }); diff --git a/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java b/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java index 2fe2009ee2f8..51b728df3e6c 100644 --- a/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/RootsChangedTest.java @@ -99,7 +99,7 @@ public class RootsChangedTest extends ModuleTestCase { ProjectJdkTable.getInstance().addJdk(jdk); assertEventsCount(0); - ProjectRootManager.getInstance(myProject).setProjectJdk(jdkBBB); + ProjectRootManager.getInstance(myProject).setProjectSdk(jdkBBB); assertEventsCount(0); final ModifiableRootModel rootModelA = ModuleRootManager.getInstance(moduleA).getModifiableModel(); @@ -109,7 +109,7 @@ public class RootsChangedTest extends ModuleTestCase { ProjectRootManager.getInstance(myProject).multiCommit(new ModifiableRootModel[]{rootModelA, rootModelB}); assertEventsCount(1); - ProjectRootManager.getInstance(myProject).setProjectJdk(jdk); + ProjectRootManager.getInstance(myProject).setProjectSdk(jdk); assertEventsCount(1); final SdkModificator sdkModificator = jdk.getSdkModificator(); diff --git a/java/openapi/src/com/intellij/psi/GenericsUtil.java b/java/openapi/src/com/intellij/psi/GenericsUtil.java index 585f9692aec9..412e11a52c85 100644 --- a/java/openapi/src/com/intellij/psi/GenericsUtil.java +++ b/java/openapi/src/com/intellij/psi/GenericsUtil.java @@ -15,8 +15,8 @@ */ package com.intellij.psi; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiUtil; diff --git a/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java b/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java index 7d4122eef3ca..712e64f30ebd 100644 --- a/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java +++ b/java/openapi/src/com/intellij/psi/codeStyle/JavaCodeStyleManager.java @@ -148,7 +148,26 @@ public abstract class JavaCodeStyleManager { * @param lookForward if true, the existing variables are searched in both directions; if false - only backward * @return the generated unique name, */ - @NotNull public abstract SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, PsiElement place, boolean lookForward); + @NotNull + public SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, + PsiElement place, + boolean lookForward) { + return suggestUniqueVariableName(baseNameInfo, place, false, lookForward); + } + + /** + * Suggests a unique name for the variable used at the specified location. + * + * + * @param baseNameInfo the base name info for the variable. + * @param place the location where the variable will be used. + * @param ignorePlaceName if true and place is PsiNamedElement, place.getName() would be still treated as unique name + * @param lookForward if true, the existing variables are searched in both directions; if false - only backward @return the generated unique name, + */ + @NotNull public abstract SuggestedNameInfo suggestUniqueVariableName(@NotNull SuggestedNameInfo baseNameInfo, + PsiElement place, + boolean ignorePlaceName, + boolean lookForward); /** * Replaces all references to Java classes in the contents of the specified element, @@ -172,4 +191,4 @@ public abstract class JavaCodeStyleManager { @Nullable public abstract Collection findRedundantImports(PsiJavaFile file); -} \ No newline at end of file +} diff --git a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java b/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java index e8d6aff54b8a..37136fe71c9c 100644 --- a/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java +++ b/platform/lang-api/src/com/intellij/codeInspection/LocalInspectionTool.java @@ -146,5 +146,10 @@ public abstract class LocalInspectionTool extends InspectionProfileEntry { public void inspectionStarted(LocalInspectionToolSession session) {} + public void inspectionFinished(LocalInspectionToolSession session, ProblemsHolder problemsHolder) { + inspectionFinished(session); + } + + @Deprecated() public void inspectionFinished(LocalInspectionToolSession session) {} } diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java index 84061770853a..e5daad1340c0 100644 --- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java +++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java @@ -56,7 +56,7 @@ public class WizardContext { public WizardContext(Project project) { myProject = project; if (myProject != null){ - myProjectJdk = ProjectRootManager.getInstance(myProject).getProjectJdk(); + myProjectJdk = ProjectRootManager.getInstance(myProject).getProjectSdk(); } } diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java index 956330b4a056..ba8b609dacad 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ModuleRootModel.java @@ -65,8 +65,8 @@ public interface ModuleRootModel { * Returns true if JDK for this module is inherited from a project. * * @return true if the JDK is inherited, false otherwise - * @see ProjectRootManager#getProjectJdk() - * @see ProjectRootManager#setProjectJdk(com.intellij.openapi.projectRoots.Sdk) + * @see ProjectRootManager#getProjectSdk() + * @see ProjectRootManager#setProjectSdk(com.intellij.openapi.projectRoots.Sdk) */ boolean isSdkInherited(); diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootManager.java b/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootManager.java index 61349d15b38f..4021f63a481b 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootManager.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ProjectRootManager.java @@ -124,28 +124,28 @@ public abstract class ProjectRootManager implements ModificationTracker { * to any existing JDK instance. */ @Nullable - public abstract Sdk getProjectJdk(); + public abstract Sdk getProjectSdk(); /** * Returns the name of the JDK selected for the project. * * @return the JDK name. */ - public abstract String getProjectJdkName(); + public abstract String getProjectSdkName(); /** * Sets the JDK to be used for the project. * * @param jdk the JDK instance. */ - public abstract void setProjectJdk(@Nullable Sdk jdk); + public abstract void setProjectSdk(@Nullable Sdk jdk); /** * Sets the name of the JDK to be used for the project. * * @param name the name of the JDK. */ - public abstract void setProjectJdkName(String name); + public abstract void setProjectSdkName(String name); /** * Commits the change to the lists of roots for the specified modules. diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ui/util/OrderEntryCellAppearanceUtils.java b/platform/lang-api/src/com/intellij/openapi/roots/ui/util/OrderEntryCellAppearanceUtils.java index a59c95fe9b36..37d4766a6c2a 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ui/util/OrderEntryCellAppearanceUtils.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ui/util/OrderEntryCellAppearanceUtils.java @@ -177,14 +177,14 @@ public class OrderEntryCellAppearanceUtils { public static CellAppearance forProjectJdk(final Project project) { final ProjectRootManager projectRootManager = ProjectRootManager.getInstance(project); - final Sdk projectJdk = projectRootManager.getProjectJdk(); + final Sdk projectJdk = projectRootManager.getProjectSdk(); final CellAppearance appearance; if (projectJdk != null) { appearance = forJdk(projectJdk, false, false); } else { // probably invalid JDK - final String projectJdkName = projectRootManager.getProjectJdkName(); + final String projectJdkName = projectRootManager.getProjectSdkName(); if (projectJdkName != null) { appearance = SimpleTextCellAppearance.invalid(ProjectBundle.message("jdk.combo.box.invalid.item", projectJdkName), CellAppearanceUtils.INVALID_ICON); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 109433c646cd..f1a607a6f829 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -199,7 +199,6 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { LookupImpl lookup = (LookupImpl)LookupManager.getInstance(editor.getProject()).createLookup(editor, LookupElement.EMPTY_ARRAY, "", LookupArranger.DEFAULT); if (editor.isOneLineMode()) { - lookup.setForceShowAsPopup(true); lookup.setCancelOnClickOutside(true); lookup.setCancelOnOtherWindowOpen(true); lookup.setResizable(false); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java index fdbc741cf588..de826e017f2e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java @@ -31,8 +31,7 @@ public class ComboEditorCompletionContributor extends CompletionContributor{ @Override public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) { - final CompletionProcess process = CompletionService.getCompletionService().getCurrentCompletion(); - if (process != null && process.isAutopopupCompletion()) { + if (parameters.getInvocationCount() == 0) { return; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index 355f14a22bbf..80fc1cd5d096 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -30,7 +30,6 @@ import com.intellij.psi.statistics.StatisticsManager; import gnu.trove.THashMap; import gnu.trove.TObjectHashingStrategy; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; @@ -48,13 +47,13 @@ public class CompletionLookupArranger extends LookupArranger { } @Override - public void sortItems(List items) { - Collections.sort(items, new Comparator() { + public Comparator getItemComparator() { + return new Comparator() { public int compare(LookupElement o1, LookupElement o2) { //noinspection unchecked return getSortingWeight(o1).compareTo(getSortingWeight(o2)); } - }); + }; } public void itemSelected(LookupElement item, final Lookup lookup) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index 573549ce4d06..c67416c58dda 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -76,7 +76,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private final LookupImpl myLookup; private final MergingUpdateQueue myQueue; private boolean myDisposed; - private boolean myInitialized; + private boolean myShownLookup; private int myCount; private final Update myUpdate = new Update("update") { public void run() { @@ -124,6 +124,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement myLookup = lookup; myLookup.setArranger(new CompletionLookupArranger(parameters)); + myShownLookup = lookup.isShown(); myLookup.addLookupListener(myLookupListener); myLookup.setCalculating(true); @@ -133,7 +134,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement ApplicationManager.getApplication().assertIsDispatchThread(); registerItself(); - if (!ApplicationManager.getApplication().isUnitTestMode()) { + if (!ApplicationManager.getApplication().isUnitTestMode() && !lookup.isShown()) { scheduleAdvertising(); } @@ -194,7 +195,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement if (isOutdated()) { return; } - if (isAutopopupCompletion() && !myInitialized) { + if (isAutopopupCompletion() && !myShownLookup) { return; } if (!isBackgrounded()) { @@ -307,8 +308,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement ApplicationManager.getApplication().assertIsDispatchThread(); if (isOutdated()) return; - if (!myInitialized) { - myInitialized = true; + if (!myShownLookup) { + myShownLookup = true; if (StringUtil.isEmpty(myLookup.getAdvertisementText()) && !isAutopopupCompletion()) { final String text = DefaultCompletionContributor.getDefaultAdvertisementText(myParameters); @@ -536,10 +537,6 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement return aBoolean.booleanValue(); } - public boolean isInitialized() { - return myInitialized; - } - public void restorePrefix() { setMergeCommand(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java index 2e4014642037..66794598e707 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java @@ -128,7 +128,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP MarkupModel model = myDocument.getMarkupModel(myProject); UpdateHighlightersUtil.cleanFileLevelHighlights(myProject, Pass.UPDATE_ALL,myFile); final EditorColorsScheme colorsScheme = getColorsScheme(); - UpdateHighlightersUtil.setHighlightersInRange(range, myHighlights, colorsScheme, (MarkupModelEx)model, Pass.UPDATE_ALL, myDocument, myProject); + UpdateHighlightersUtil.setHighlightersInRange(myProject, myDocument, range, colorsScheme, myHighlights, (MarkupModelEx)model, Pass.UPDATE_ALL); } }; @@ -192,16 +192,8 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP public void run() { if (!addInjectedPsiHighlights(injectedInside, progress, Collections.synchronizedSet(result))) throw new ProcessCanceledException(); - // set editor's color scheme - //final EditorColorsScheme colorsScheme = getColorsScheme(); - //if (colorsScheme != null) { - // for (HighlightInfo info : result) { - // info.setCustomColorScheme(colorsScheme); - // } - //} - if (!outside.isEmpty() || !injectedOutside.isEmpty()) { - if (!inside.isEmpty()) { // do not apply when there were no elements to highlight + if (!inside.isEmpty() || !injectedInside.isEmpty()) { // do not apply when there were no elements to highlight // clear infos found in visible area to avoid applying them twice final List toApply = new ArrayList(result.size()); for (HighlightInfo info : result) { @@ -219,18 +211,19 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { - if (progress.isCanceled()) return; + if (myProject.isDisposed()) return; MarkupModel markupModel = myDocument.getMarkupModel(myProject); ProperTextRange range = myPriorityRange.intersection(new TextRange(myStartOffset, myEndOffset)); final EditorColorsScheme colorsScheme = getColorsScheme(); - UpdateHighlightersUtil.setHighlightersInRange(range, toApply, colorsScheme, (MarkupModelEx)markupModel, Pass.UPDATE_ALL, myDocument, myProject); + UpdateHighlightersUtil.setHighlightersInRange(myProject, myDocument, range, colorsScheme, toApply, + (MarkupModelEx)markupModel, Pass.UPDATE_ALL); } }); UIUtil.invokeLaterIfNeeded(new Runnable() { @Override public void run() { - if (progress.isCanceled() || myEditor == null) return; + if (myProject.isDisposed() || myEditor == null) return; new ShowAutoImportPass(myProject, myFile, myEditor).applyInformationToEditor(); } }); @@ -268,7 +261,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP } */ - UpdateHighlightersUtil.setHighlightersToEditorOutsideRange(myProject, myDocument, toApply, getColorsScheme(), + UpdateHighlightersUtil.setHighlightersOutsideRange(myProject, myDocument, toApply, getColorsScheme(), myStartOffset, myEndOffset, myPriorityRange, Pass.UPDATE_ALL); } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 15b8a6573c24..0e94a219fc36 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -269,22 +269,23 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List> init) { boolean result = JobUtil.invokeConcurrentlyUnderMyProgress(init, new Processor>() { @Override - public boolean process(Trinity i) { - LocalInspectionTool tool = i.first; + public boolean process(Trinity trinity) { + LocalInspectionTool tool = trinity.first; indicator.checkCanceled(); ApplicationManager.getApplication().assertReadAccessAllowed(); - ProblemsHolder holder = i.second; - PsiElementVisitor elementVisitor = i.third; - for (PsiElement element : elements) { + ProblemsHolder holder = trinity.second; + PsiElementVisitor elementVisitor = trinity.third; + for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { + PsiElement element = elements.get(i); indicator.checkCanceled(); element.accept(elementVisitor); } advanceProgress(1); - tool.inspectionFinished(session); + tool.inspectionFinished(session, holder); if (holder.hasResults()) { appendDescriptors(myFile, holder.getResults(), tool); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java index fdbec9a8b6d5..41705b151739 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java @@ -115,26 +115,6 @@ public class UpdateHighlightersUtil { } } - public static void setHighlightersToEditor(@NotNull Project project, - @NotNull Document document, - int startOffset, - int endOffset, - @NotNull Collection highlights, - @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - int group) { - setHighlightersToEditor(project, document, Collections.singletonMap(new TextRange(startOffset, endOffset), highlights), colorsScheme, group); - } - - @Deprecated - public static void setHighlightersToEditor(Project project, - Document document, - int startOffset, - int endOffset, - Collection highlights, int group) { - setHighlightersToEditor(project, document, startOffset, endOffset, highlights, null, group); - - } - static boolean hasInfo(Collection infos, int start, int end, String desc) { if (infos == null) return false; for (HighlightInfo info : infos) { @@ -177,13 +157,13 @@ public class UpdateHighlightersUtil { } static void addHighlighterToEditorIncrementally(@NotNull Project project, - @NotNull Document document, - @NotNull PsiFile file, - int startOffset, - int endOffset, - @NotNull final HighlightInfo info, + @NotNull Document document, + @NotNull PsiFile file, + int startOffset, + int endOffset, + @NotNull final HighlightInfo info, @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - final int group) { + final int group) { ApplicationManager.getApplication().assertIsDispatchThread(); if (info.isFileLevelAnnotation || info.getGutterIconRenderer() != null) return; @@ -204,100 +184,68 @@ public class UpdateHighlightersUtil { createOrReuseHighlighterFor(info, colorsScheme, document, group, file, (MarkupModelEx)markup, null, null, SeverityRegistrar.getInstance(project)); - DaemonCodeAnalyzerImpl.addHighlight(markup, project, info); clearWhiteSpaceOptimizationFlag(document); assertMarkupConsistent(markup, project); } - @Deprecated - static void setHighlightersToEditor(@NotNull final Project project, - @NotNull final Document document, - @NotNull final Map> infos, - final int group) { - // For backward compatibility with TeamCity plugin, duplicates searcher. - setHighlightersToEditor(project, document, infos, null, group); - } - - static void setHighlightersToEditor(@NotNull Project project, - @NotNull Document document, - @NotNull Map> infos, - @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - final int group) { + public static void setHighlightersToEditor(@NotNull Project project, + @NotNull Document document, + int startOffset, + int endOffset, + @NotNull Collection highlights, + @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used + int group) { + TextRange range = new TextRange(startOffset, endOffset); ApplicationManager.getApplication().assertIsDispatchThread(); PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); cleanFileLevelHighlights(project, group, psiFile); - final List ranges = new ArrayList(infos.keySet()); - Collections.sort(ranges, BY_START_OFFSET); - //merge intersecting - for (int i = 1; i < ranges.size(); i++) { - TextRange range = ranges.get(i); - TextRange prev = ranges.get(i-1); - if (prev.intersects(range)) { - ranges.remove(i); - TextRange union = prev.union(range); - - Collection collection = infos.get(prev); - collection.addAll(infos.get(range)); - infos.remove(prev); - infos.remove(range); - infos.put(union, collection); - ranges.set(i - 1, union); - i--; - } - } - MarkupModel markup = document.getMarkupModel(project); assertMarkupConsistent(markup, project); - for (Map.Entry> entry : infos.entrySet()) { - TextRange range = entry.getKey(); - Collection highlights = entry.getValue(); - setHighlightersInRange(range, highlights, colorsScheme, (MarkupModelEx)markup, group, document, project); - } + setHighlightersInRange(project, document, range, colorsScheme, highlights, (MarkupModelEx)markup, group); + } + + @Deprecated //for teamcity + public static void setHighlightersToEditor(@NotNull Project project, + @NotNull Document document, + int startOffset, + int endOffset, + @NotNull Collection highlights, + int group) { + setHighlightersToEditor(project, document, startOffset, endOffset, highlights, null, group); } // set highlights inside startOffset,endOffset but outside range - static void setHighlightersToEditorOutsideRange(@NotNull Project project, - @NotNull Document document, - @NotNull Collection infos, + static void setHighlightersOutsideRange(@NotNull final Project project, + @NotNull final Document document, + @NotNull Collection infos, @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - int startOffset, int endOffset, - @NotNull ProperTextRange range, - final int group) { + int startOffset, int endOffset, + @NotNull final ProperTextRange range, + final int group) { ApplicationManager.getApplication().assertIsDispatchThread(); - PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); + final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); cleanFileLevelHighlights(project, group, psiFile); - MarkupModel markup = document.getMarkupModel(project); + final MarkupModel markup = document.getMarkupModel(project); assertMarkupConsistent(markup, project); - setHighlightersOutsideRange(startOffset, endOffset, range, infos, colorsScheme, (MarkupModelEx)markup, group, document, project); - } - - static void setHighlightersInRange(final TextRange range, - Collection highlightsCo, - @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - final MarkupModelEx markup, - final int group, - final Document document, - final Project project) { - final List highlights = new ArrayList(highlightsCo); + final List highlights = new ArrayList(infos); final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project); final HighlightersRecycler infosToRemove = new HighlightersRecycler(); - DaemonCodeAnalyzerImpl.processHighlights(document, project, null, range.getStartOffset(), range.getEndOffset(), new Processor() { + DaemonCodeAnalyzerImpl.processHighlights(document, project, null, startOffset, endOffset, new Processor() { @Override public boolean process(HighlightInfo info) { if (info.group == group) { RangeHighlighter highlighter = info.highlighter; - int endOffset = highlighter.getEndOffset(); - int startOffset = highlighter.getStartOffset(); - boolean willBeRemoved = endOffset == document.getTextLength() && range.getEndOffset() == document.getTextLength() - || range.contains(startOffset) - || range.containsRange(startOffset, endOffset); + int hiStart = highlighter.getStartOffset(); + int hiEnd = highlighter.getEndOffset(); + boolean willBeRemoved = hiEnd == document.getTextLength() && range.getEndOffset() == document.getTextLength() + || !range.containsRange(hiStart, hiEnd); if (willBeRemoved) { infosToRemove.recycleHighlighter(highlighter); info.highlighter = null; @@ -309,7 +257,6 @@ public class UpdateHighlightersUtil { Collections.sort(highlights, BY_START_OFFSET_NODUPS); final Map ranges2markersCache = new THashMap(10); - final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document); final boolean[] changed = {false}; RangeMarkerTree.sweep(new RangeMarkerTree.Generator(){ @Override @@ -330,10 +277,8 @@ public class UpdateHighlightersUtil { if (isWarningCoveredByError(info, overlappingIntervals, severityRegistrar)) { return true; } - if (info.getStartOffset() >= range.getStartOffset() && info.getEndOffset() <= range.getEndOffset()) { - createOrReuseHighlighterFor(info, colorsScheme, document, group, psiFile, markup, infosToRemove, - ranges2markersCache, - severityRegistrar); + if (info.getStartOffset() < range.getStartOffset() || info.getEndOffset() > range.getEndOffset()) { + createOrReuseHighlighterFor(info, colorsScheme, document, group, psiFile, (MarkupModelEx)markup, infosToRemove, ranges2markersCache, severityRegistrar); changed[0] = true; } return true; @@ -350,27 +295,27 @@ public class UpdateHighlightersUtil { assertMarkupConsistent(markup, project); } - private static void setHighlightersOutsideRange(final int startOffset, final int endOffset, final TextRange range, - Collection highlightsCo, - @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used - final MarkupModelEx markup, - final int group, - final Document document, - final Project project) { + static void setHighlightersInRange(@NotNull final Project project, + @NotNull final Document document, + @NotNull final TextRange range, + @Nullable final EditorColorsScheme colorsScheme, // if null global scheme will be used + @NotNull Collection highlightsCo, + @NotNull final MarkupModelEx markup, + final int group) { + ApplicationManager.getApplication().assertIsDispatchThread(); final List highlights = new ArrayList(highlightsCo); final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project); final HighlightersRecycler infosToRemove = new HighlightersRecycler(); - DaemonCodeAnalyzerImpl.processHighlights(document, project, null, startOffset, endOffset, new Processor() { + DaemonCodeAnalyzerImpl.processHighlights(document, project, null, range.getStartOffset(), range.getEndOffset(), new Processor() { @Override public boolean process(HighlightInfo info) { if (info.group == group) { RangeHighlighter highlighter = info.highlighter; - int endOffset = highlighter.getEndOffset(); - int startOffset = highlighter.getStartOffset(); - boolean willBeRemoved = endOffset == document.getTextLength() && range.getEndOffset() != document.getTextLength() - || !range.contains(startOffset) - && !range.containsRange(startOffset, endOffset); + int hiEnd = highlighter.getEndOffset(); + int hiStart = highlighter.getStartOffset(); + boolean willBeRemoved = hiEnd == document.getTextLength() && range.getEndOffset() == document.getTextLength() + || range.intersects(hiStart, hiEnd); if (willBeRemoved) { infosToRemove.recycleHighlighter(highlighter); info.highlighter = null; @@ -403,10 +348,8 @@ public class UpdateHighlightersUtil { if (isWarningCoveredByError(info, overlappingIntervals, severityRegistrar)) { return true; } - if (info.getStartOffset() < range.getStartOffset() || info.getEndOffset() > range.getEndOffset()) { - createOrReuseHighlighterFor(info, colorsScheme, document, group, psiFile, markup, infosToRemove, - ranges2markersCache, - severityRegistrar); + if (info.getStartOffset() >= range.getStartOffset() && info.getEndOffset() <= range.getEndOffset()) { + createOrReuseHighlighterFor(info, colorsScheme, document, group, psiFile, markup, infosToRemove, ranges2markersCache, severityRegistrar); changed[0] = true; } return true; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index b64f97136848..1635c1477f0b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -35,8 +35,10 @@ import com.intellij.openapi.fileEditor.FileEditorManagerEvent; import com.intellij.openapi.fileEditor.FileEditorManagerListener; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; import com.intellij.psi.PsiFile; import com.intellij.util.messages.MessageBusConnection; +import org.jetbrains.annotations.Nullable; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -45,9 +47,8 @@ import java.beans.PropertyChangeListener; * @author peter */ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { + private static final Key STATE_KEY = Key.create("AutopopupSTATE_KEY"); public static boolean ourTestingAutopopup = false; - private boolean myAutopopupShown; - private boolean myGuard; @Override public Result beforeCharTyped(char c, @@ -55,13 +56,14 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { Editor editor, PsiFile file, FileType fileType) { - if (myAutopopupShown && LookupManager.getActiveLookup(editor) == null) { - myGuard = true; + final AutoPopupState state = getAutoPopupState(editor); + if (state != null && LookupManager.getActiveLookup(editor) == null) { + state.changeGuard = true; try { EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(c), true); } finally { - myGuard = false; + state.changeGuard = false; } return Result.STOP; } @@ -78,7 +80,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { return Result.CONTINUE; } - if (myAutopopupShown || LookupManager.getActiveLookup(editor) != null) { + if (getAutoPopupState(editor) != null || LookupManager.getActiveLookup(editor) != null) { return Result.CONTINUE; } @@ -98,21 +100,25 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { new CodeCompletionHandlerBase(CompletionType.BASIC, false, false).invoke(project, editor); - myAutopopupShown = true; - trackUserActivity(project, editor); + final AutoPopupState state = new AutoPopupState(project, editor); + editor.putUserData(STATE_KEY, state); final Lookup lookup = LookupManager.getActiveLookup(editor); if (lookup != null) { lookup.addLookupListener(new LookupAdapter() { @Override public void itemSelected(LookupEvent event) { - myAutopopupShown = false; + final AutoPopupState state = getAutoPopupState(editor); + if (state != null) { + state.stopAutoPopup(); + } } @Override public void lookupCanceled(LookupEvent event) { - if (event.isCanceledExplicitly()) { - myAutopopupShown = false; + final AutoPopupState state = getAutoPopupState(editor); + if (event.isCanceledExplicitly() && state != null) { + state.stopAutoPopup(); } } }); @@ -127,82 +133,99 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { return Result.STOP; } - private void trackUserActivity(Project project, final Editor editor) { - final MessageBusConnection connection = project.getMessageBus().connect(); - connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() { - @Override - public void selectionChanged(FileEditorManagerEvent event) { - if (finishAutopopupCompletion(editor, false)) { - connection.disconnect(); - } - } - }); - - editor.addEditorMouseListener(new EditorMouseAdapter() { - @Override - public void mouseClicked(EditorMouseEvent e) { - if (finishAutopopupCompletion(editor, false)) { - editor.removeEditorMouseListener(this); - } - } - }); - - editor.getCaretModel().addCaretListener(new CaretListener() { - @Override - public void caretPositionChanged(CaretEvent e) { - if (finishAutopopupCompletion(editor, false)) { - editor.getCaretModel().removeCaretListener(this); - } - } - }); - - editor.getSelectionModel().addSelectionListener(new SelectionListener() { - @Override - public void selectionChanged(SelectionEvent e) { - if (finishAutopopupCompletion(editor, false)) { - editor.getSelectionModel().removeSelectionListener(this); - } - } - }); - - editor.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - public void documentChanged(DocumentEvent e) { - if (finishAutopopupCompletion(editor, false)) { - editor.getDocument().removeDocumentListener(this); - } - } - }); - - final LookupManager lookupManager = LookupManager.getInstance(project); - lookupManager.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getNewValue() != null && finishAutopopupCompletion(editor, true)) { - lookupManager.removePropertyChangeListener(this); - } - } - }); + @Nullable + private static AutoPopupState getAutoPopupState(Editor editor) { + return editor.getUserData(STATE_KEY); } - private boolean finishAutopopupCompletion(Editor editor, boolean neglectLookup) { - if (!myAutopopupShown) { - return true; //to disconnect all the listeners - } - - if (myGuard) { - return false; + private static void finishAutopopupCompletion(Editor editor, boolean neglectLookup) { + final AutoPopupState state = getAutoPopupState(editor); + if (state == null || state.changeGuard) { + return; } if (!neglectLookup && LookupManager.getActiveLookup(editor) != null) { //the events during visible lookup period are handled separately - return false; + return; } - myAutopopupShown = false; final CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); if (currentCompletion != null) { currentCompletion.closeAndFinish(true); } - return true; + state.stopAutoPopup(); + } + + + private static class AutoPopupState { + final Editor editor; + final Project project; + final MessageBusConnection connection; + final EditorMouseAdapter mouseListener; + final CaretListener caretListener; + final DocumentAdapter documentListener; + final PropertyChangeListener lookupListener; + boolean changeGuard = false; + + private AutoPopupState(final Project project, final Editor editor) { + this.editor = editor; + this.project = project; + connection = project.getMessageBus().connect(); + connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() { + @Override + public void selectionChanged(FileEditorManagerEvent event) { + finishAutopopupCompletion(editor, false); + } + }); + + mouseListener = new EditorMouseAdapter() { + @Override + public void mouseClicked(EditorMouseEvent e) { + finishAutopopupCompletion(editor, false); + } + }; + + caretListener = new CaretListener() { + @Override + public void caretPositionChanged(CaretEvent e) { + finishAutopopupCompletion(editor, false); + } + }; + editor.getSelectionModel().addSelectionListener(new SelectionListener() { + @Override + public void selectionChanged(SelectionEvent e) { + finishAutopopupCompletion(editor, false); + } + }); + documentListener = new DocumentAdapter() { + @Override + public void documentChanged(DocumentEvent e) { + finishAutopopupCompletion(editor, false); + } + }; + lookupListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getNewValue() != null) { + finishAutopopupCompletion(editor, true); + } + } + }; + + editor.addEditorMouseListener(mouseListener); + editor.getCaretModel().addCaretListener(caretListener); + editor.getDocument().addDocumentListener(documentListener); + LookupManager.getInstance(project).addPropertyChangeListener(lookupListener); + } + + void stopAutoPopup() { + connection.disconnect(); + editor.removeEditorMouseListener(mouseListener); + editor.getCaretModel().removeCaretListener(caretListener); + editor.getDocument().removeDocumentListener(documentListener); + LookupManager.getInstance(project).removePropertyChangeListener(lookupListener); + + editor.putUserData(STATE_KEY, null); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java index 821cef57d228..a87f14160604 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java @@ -321,7 +321,7 @@ class IntentionListStep implements ListPopupStep final IntentionAction action = value.getAction(); - Object iconable = null; + Object iconable = action; //custom icon if (action instanceof QuickFixWrapper) { iconable = ((QuickFixWrapper)action).getFix(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java index 55a03d437329..03578fca1dec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java @@ -16,6 +16,9 @@ package com.intellij.codeInsight.lookup; +import org.jetbrains.annotations.Nullable; + +import java.util.Comparator; import java.util.List; /** @@ -28,9 +31,6 @@ public abstract class LookupArranger { return 0; } - @Override - public void sortItems(List items) { - } }; public abstract Comparable getRelevance(LookupElement element); @@ -42,5 +42,8 @@ public abstract class LookupArranger { return 0; } - public abstract void sortItems(List items); + @Nullable + public Comparator getItemComparator() { + return null; //don't sort + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java index dd23bb802af0..836cbdba1b6c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java @@ -38,15 +38,6 @@ public class BackspaceHandler extends EditorActionHandler { return; } - boolean toRestart = false; - final String prefix = lookup.getAdditionalPrefix(); - if (prefix.length() > 0) { - lookup.setAdditionalPrefix(prefix.substring(0, prefix.length() - 1)); - } - else { - toRestart = lookup.getLookupStart() < editor.getCaretModel().getOffset(); - } - lookup.performGuardedChange(new Runnable() { @Override public void run() { @@ -54,11 +45,13 @@ public class BackspaceHandler extends EditorActionHandler { } }); + final String prefix = lookup.getAdditionalPrefix(); if (prefix.length() > 0) { + lookup.setAdditionalPrefix(prefix.substring(0, prefix.length() - 1)); return; } - if (toRestart) { + if (lookup.getLookupStart() < editor.getCaretModel().getOffset()) { final CompletionProcess process = CompletionService.getCompletionService().getCurrentCompletion(); if (process instanceof CompletionProgressIndicator) { ((CompletionProgressIndicator)process).restartCompletion(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index ea9adda1263e..cfec8f4dd080 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -33,6 +33,7 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; @@ -82,12 +83,9 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private final LookupCellRenderer myCellRenderer; private Boolean myPositionedAbove = null; - private CaretListener myEditorCaretListener; - private SelectionListener myEditorSelectionListener; - private EditorMouseListener myEditorMouseListener; - private final ArrayList myListeners = new ArrayList(); + private boolean myShown = false; private boolean myDisposed = false; private boolean myHidden = false; private LookupElement myPreselectedItem = EMPTY_LOOKUP_ITEM; @@ -103,7 +101,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private static final int LOOKUP_HEIGHT = Integer.getInteger("idea.lookup.height", 11).intValue(); private boolean myReused; private boolean myChangeGuard; - private LookupModel myModel = new LookupModel(this); + private LookupModel myModel = new LookupModel(); public LookupImpl(Project project, Editor editor, @NotNull LookupArranger arranger){ super(new JPanel(new BorderLayout())); @@ -139,10 +137,13 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { updateListHeight(model); setArranger(arranger); + + addListeners(); } public void setArranger(LookupArranger arranger) { myArranger = arranger; + myModel.setArranger(arranger); } public boolean isFocused() { @@ -265,29 +266,15 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { if (!ApplicationManager.getApplication().isUnitTestMode()) { ApplicationManager.getApplication().assertIsDispatchThread(); } - final List items = myModel.getSortedItems(); - SortedMap> itemsMap = new TreeMap>(); - int minPrefixLength = items.isEmpty() ? 0 : Integer.MAX_VALUE; - for (final LookupElement item : items) { - minPrefixLength = Math.min(item.getPrefixMatcher().getPrefix().length(), minPrefixLength); - - final Comparable relevance = myArranger.getRelevance(item); - List list = itemsMap.get(relevance); - if (list == null) { - itemsMap.put(relevance, list = new ArrayList()); - } - list.add(item); - } if (myReused) { myModel.collectGarbage(); myReused = false; } - if (myMinPrefixLength != minPrefixLength) { - myLookupStartMarker = null; - } - myMinPrefixLength = minPrefixLength; + final Pair,List>> snapshot = myModel.getModelSnapshot(); + final List items = snapshot.first; + checkMinPrefixLengthChanges(items); LookupElement oldSelected = mySelectionTouched ? (LookupElement)myList.getSelectedValue() : null; String oldInvariant = mySelectionInvariant; @@ -302,7 +289,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { Set firstItems = new THashSet(); hasExactPrefixes = addExactPrefixItems(model, firstItems, items); - addMostRelevantItems(model, firstItems, itemsMap.values()); + addMostRelevantItems(model, firstItems, snapshot.second); hasPreselectedItem = addPreselectedItem(model, firstItems, preselectedItem); myPreferredItemsCount = firstItems.size(); @@ -334,6 +321,18 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } } + private void checkMinPrefixLengthChanges(List items) { + int minPrefixLength = items.isEmpty() ? 0 : Integer.MAX_VALUE; + for (final LookupElement item : items) { + minPrefixLength = Math.min(item.getPrefixMatcher().getPrefix().length(), minPrefixLength); + } + + if (myMinPrefixLength != minPrefixLength) { + myLookupStartMarker = null; + } + myMinPrefixLength = minPrefixLength; + } + private void restoreSelection(@Nullable LookupElement oldSelected, boolean choosePreselectedItem, @Nullable String oldInvariant) { if (oldSelected != null) { if (oldSelected.isValid() && ListScrollingUtil.selectItem(myList, oldSelected)) { @@ -549,13 +548,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { return myLookupStartMarker.getStartOffset(); } - @Override - protected void beforeShow() { - if (isRealPopup()) { - getComponent().setBorder(null); - } - } - public void performGuardedChange(Runnable change) { assert !myChangeGuard; myChangeGuard = true; @@ -567,10 +559,28 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } } + public boolean isShown() { + return myShown; + } + public void show(){ ApplicationManager.getApplication().assertIsDispatchThread(); - assert !myDisposed; + LOG.assertTrue(!myDisposed); + LOG.assertTrue(!myShown); + myShown = true; + if (ApplicationManager.getApplication().isUnitTestMode()) return; + + getComponent().setBorder(null); + + Point p = calculatePosition(); + HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl(); + hintManager.showEditorHint(this, myEditor, p, HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.UPDATE_BY_SCROLLING, 0, false); + + myShownStamp = System.currentTimeMillis(); + } + + private void addListeners() { myEditor.getDocument().addDocumentListener(new DocumentAdapter() { public void documentChanged(DocumentEvent e) { if (!myChangeGuard) { @@ -579,29 +589,41 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } }, this); - myEditorCaretListener = new CaretListener() { + final CaretListener caretListener = new CaretListener() { public void caretPositionChanged(CaretEvent e){ - caretOrSelectionChanged(); + if (!myChangeGuard) { + hide(); + } } }; - myEditorSelectionListener = new SelectionListener() { + final SelectionListener selectionListener = new SelectionListener() { public void selectionChanged(final SelectionEvent e) { - caretOrSelectionChanged(); + if (!myChangeGuard) { + hide(); + } } }; - myEditor.getCaretModel().addCaretListener(myEditorCaretListener); - myEditor.getSelectionModel().addSelectionListener(myEditorSelectionListener); - - myEditorMouseListener = new EditorMouseAdapter() { + final EditorMouseListener mouseListener = new EditorMouseAdapter() { public void mouseClicked(EditorMouseEvent e){ e.consume(); hide(); } }; - myEditor.addEditorMouseListener(myEditorMouseListener); + + myEditor.getCaretModel().addCaretListener(caretListener); + myEditor.getSelectionModel().addSelectionListener(selectionListener); + myEditor.addEditorMouseListener(mouseListener); + Disposer.register(this, new Disposable() { + @Override + public void dispose() { + myEditor.getCaretModel().removeCaretListener(caretListener); + myEditor.getSelectionModel().removeSelectionListener(selectionListener); + myEditor.removeEditorMouseListener(mouseListener); + } + }); myList.addListSelectionListener(new ListSelectionListener() { - private LookupElement oldItem = null; + private LookupElement oldItem = null; public void valueChanged(ListSelectionEvent e){ LookupElement item = getCurrentItem(); @@ -621,7 +643,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { final int i = myList.locationToIndex(point); if (i >= 0) { final LookupElement selected = (LookupElement)myList.getModel().getElementAt(i); - if (selected != null && + if (selected != null && e.getClickCount() == 1 && point.x >= myList.getCellBounds(i, i).width - PopupIcons.EMPTY_ICON.getIconWidth() && ShowLookupActionsHandler.showItemActions(LookupImpl.this, selected)) { @@ -638,20 +660,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } } }); - - if (ApplicationManager.getApplication().isUnitTestMode()) return; - - Point p = calculatePosition(); - HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl(); - hintManager.showEditorHint(this, myEditor, p, HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.UPDATE_BY_SCROLLING, 0, false); - - myShownStamp = System.currentTimeMillis(); - } - - private void caretOrSelectionChanged() { - if (!myChangeGuard) { - hide(); - } } private int calcLookupStart() { @@ -920,16 +928,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { assert !myDisposed; Disposer.dispose(myProcessIcon); - if (myEditorCaretListener != null) { - myEditor.getCaretModel().removeCaretListener(myEditorCaretListener); - myEditor.getSelectionModel().removeSelectionListener(myEditorSelectionListener); - myEditorCaretListener = null; - myEditorSelectionListener = null; - } - if (myEditorMouseListener != null) { - myEditor.removeEditorMouseListener(myEditorMouseListener); - myEditorMouseListener = null; - } + myDisposed = true; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupModel.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupModel.java index c51a6ef90403..ff29cb6a6d12 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupModel.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupModel.java @@ -15,13 +15,18 @@ */ package com.intellij.codeInsight.lookup.impl; +import com.intellij.codeInsight.lookup.LookupArranger; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementAction; import com.intellij.codeInsight.lookup.LookupElementPresentation; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.SortedList; import gnu.trove.THashMap; +import gnu.trove.THashSet; import gnu.trove.TObjectHashingStrategy; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import java.util.*; @@ -30,16 +35,20 @@ import java.util.*; * @author peter */ public class LookupModel { + private static final Comparator COMMUNISM = new Comparator() { + @SuppressWarnings({"ComparatorMethodParameterNotUsed"}) + @Override + public int compare(LookupElement o1, LookupElement o2) { + return 0; + } + }; private final Object lock = new Object(); @SuppressWarnings({"unchecked"}) private final Map> myItemActions = new THashMap>(TObjectHashingStrategy.IDENTITY); @SuppressWarnings({"unchecked"}) private final Map myItemPresentations = new THashMap(TObjectHashingStrategy.IDENTITY); private final List myItems = new ArrayList(); - @Nullable private List mySortedItems; - private final LookupImpl myLookup; - - public LookupModel(LookupImpl lookup) { - myLookup = lookup; - } + private SortedList mySortedItems; + private TreeMap> myRelevanceGroups; + private LookupArranger myArranger; @TestOnly public List getItems() { @@ -49,14 +58,22 @@ public class LookupModel { public void clearItems() { synchronized (lock) { myItems.clear(); - mySortedItems = null; + mySortedItems.clear(); + myRelevanceGroups.clear(); } } public void addItem(LookupElement item) { synchronized (lock) { myItems.add(item); - mySortedItems = null; + mySortedItems.add(item); + + final Comparable relevance = myArranger.getRelevance(item); + SortedList group = myRelevanceGroups.get(relevance); + if (group == null) { + myRelevanceGroups.put(relevance, group = new SortedList(mySortedItems.getComparator())); + } + group.add(item); } } @@ -87,36 +104,54 @@ public class LookupModel { } } - @NotNull - public List getSortedItems() { + public Pair, List>> getModelSnapshot() { synchronized (lock) { - List sortedItems = mySortedItems; - if (sortedItems == null) { - myLookup.getArranger().sortItems(sortedItems = new ArrayList(myItems)); - mySortedItems = sortedItems; - } - return sortedItems; + final List sorted = new ArrayList(mySortedItems); + final List> relevanceGroups = ContainerUtil.map(myRelevanceGroups.values(), new Function, List>() { + @Override + public List fun(SortedList lookupElements) { + return new ArrayList(lookupElements); + } + }); + return Pair.create(sorted, relevanceGroups); } } - public void collectGarbage() { synchronized (lock) { - myItemActions.keySet().retainAll(myItems); - myItemPresentations.keySet().retainAll(myItems); + Set itemSet = new THashSet(myItems, TObjectHashingStrategy.IDENTITY); + myItemActions.keySet().retainAll(itemSet); + myItemPresentations.keySet().retainAll(itemSet); } } - void retainMatchingItems(String newPrefix) { + void retainMatchingItems(final String newPrefix) { synchronized (lock) { - for (Iterator iterator = myItems.iterator(); iterator.hasNext();) { - LookupElement item = iterator.next(); - if (!item.setPrefixMatcher(item.getPrefixMatcher().cloneWithPrefix(newPrefix))) { - iterator.remove(); - mySortedItems = null; + final List newItems = ContainerUtil.findAll(myItems, new Condition() { + @Override + public boolean value(LookupElement item) { + return item.isValid() && item.setPrefixMatcher(item.getPrefixMatcher().cloneWithPrefix(newPrefix)); } + }); + + if (newItems.size() == myItems.size()) { + return; + } + + clearItems(); + for (LookupElement newItem : newItems) { + addItem(newItem); } } } + public void setArranger(final LookupArranger arranger) { + synchronized (lock) { + myArranger = arranger; + + final Comparator comparator = arranger.getItemComparator(); + mySortedItems = new SortedList(comparator == null ? COMMUNISM : comparator); + myRelevanceGroups = new TreeMap>(); + } + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java index e9c8e99a69e4..eff071ab3b50 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java @@ -58,7 +58,6 @@ public class TypedHandler implements TypedActionHandler { } }); if (result == CharFilter.Result.ADD_TO_PREFIX) { - lookup.setAdditionalPrefix(lookup.getAdditionalPrefix() + charTyped); Document document = editor.getDocument(); long modificationStamp = document.getModificationStamp(); @@ -67,6 +66,7 @@ public class TypedHandler implements TypedActionHandler { EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(charTyped), true); } }); + lookup.setAdditionalPrefix(lookup.getAdditionalPrefix() + charTyped); AutoHardWrapHandler.getInstance().wrapLineIfNecessary(editor, dataContext, modificationStamp); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index e79090729741..b8365ad8aa7e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -125,7 +125,17 @@ public class TemplateState implements Disposable { public void beforeCommandFinished(CommandEvent event) { if (started) { - afterChangedUpdate(); + Runnable runnable = new Runnable() { + public void run() { + afterChangedUpdate(); + } + }; + final LookupImpl lookup = myEditor != null ? (LookupImpl)LookupManager.getActiveLookup(myEditor) : null; + if (lookup != null) { + lookup.performGuardedChange(runnable); + } else { + runnable.run(); + } } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java index 0f9633076d0b..25729c1dbcff 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/LocalInspectionToolWrapper.java @@ -73,7 +73,7 @@ public final class LocalInspectionToolWrapper extends DescriptorProviderInspecti } }); - myTool.inspectionFinished(session); + myTool.inspectionFinished(session, holder); addProblemDescriptors(holder.getResults(), filterSuppressed); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineProblemDescriptorNode.java b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineProblemDescriptorNode.java index 0e287686e611..0c3ff80f0d6b 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineProblemDescriptorNode.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/offlineViewer/OfflineProblemDescriptorNode.java @@ -85,7 +85,7 @@ public class OfflineProblemDescriptorNode extends ProblemDescriptionNode { for (PsiElement el : elementsInRange) { el.accept(visitor); } - localInspectionTool.inspectionFinished(session); + localInspectionTool.inspectionFinished(session, holder); if (holder.hasResults()) { final List list = holder.getResults(); final int idx = offlineProblemDescriptor.getProblemIndex(); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java index e36fefd13e0f..9f801349cc63 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ProjectRunConfigurationManager.java @@ -127,6 +127,9 @@ public class ProjectRunConfigurationManager implements ProjectComponent, Persist } } } + + // IDEA-60004: configs may never be sorted before write, so call it manually after shared configs read + myManager.getSortedConfigurations(); } public void writeExternal(Element element) throws WriteExternalException { diff --git a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java index 4c69bfccff8f..a0a56ba13ab2 100644 --- a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java +++ b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java @@ -201,7 +201,7 @@ public class PsiCopyPasteManager { return getDataAsText(); } if (DataFlavor.javaFileListFlavor.equals(flavor)) { - ApplicationManager.getApplication().runReadAction(new Computable>() { + return ApplicationManager.getApplication().runReadAction(new Computable>() { @Override public List compute() { return asFileList(myDataProxy.getElements()); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java index f1e6fd233bad..6842dec2b59f 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoClassAction.java @@ -18,9 +18,7 @@ package com.intellij.ide.actions; import com.intellij.codeInsight.navigation.NavigationUtil; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.ide.util.gotoByName.ChooseByNamePopup; -import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; -import com.intellij.ide.util.gotoByName.GotoClassModel2; +import com.intellij.ide.util.gotoByName.*; import com.intellij.navigation.ChooseByNameRegistry; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -48,13 +46,16 @@ public class GotoClassAction extends GotoActionBase implements DumbAware { FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.class"); PsiDocumentManager.getInstance(project).commitAllDocuments(); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, new GotoClassModel2(project), getPsiContext(e)); + final GotoClassModel2 model = new GotoClassModel2(project); + final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e)); + final ChooseByNameFilter filterUI = new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), project); popup.invoke(new ChooseByNamePopupComponent.Callback() { public void onClose() { if (GotoClassAction.class.equals(myInAction)) { myInAction = null; } + filterUI.close(); } public void elementChosen(Object element) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java index 2fef0eea8c47..cf88f30a8c31 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoFileAction.java @@ -17,11 +17,9 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.ide.util.ElementsChooser; -import com.intellij.ide.util.gotoByName.ChooseByNamePopup; -import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; -import com.intellij.ide.util.gotoByName.GotoFileModel; -import com.intellij.openapi.actionSystem.*; +import com.intellij.ide.util.gotoByName.*; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.fileEditor.OpenFileDescriptor; @@ -29,21 +27,11 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.DumbService; 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.JBPopupListener; -import com.intellij.openapi.ui.popup.LightweightWindowEvent; -import com.intellij.openapi.util.IconLoader; import com.intellij.psi.PsiFile; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -63,7 +51,7 @@ public class GotoFileAction extends GotoActionBase implements DumbAware { final Project project = e.getData(PlatformDataKeys.PROJECT); final GotoFileModel gotoFileModel = new GotoFileModel(project); final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, gotoFileModel, getPsiContext(e)); - final FilterUI filterUI = new FilterUI(popup, gotoFileModel, project); + final ChooseByNameFilter filterUI = new GotoFileFilter(popup, gotoFileModel, project); popup.invoke(new ChooseByNamePopupComponent.Callback() { public void onClose() { if (GotoFileAction.class.equals(myInAction)) { @@ -88,227 +76,61 @@ public class GotoFileAction extends GotoActionBase implements DumbAware { }, ModalityState.current(), true); } - /** - * This class contains UI related to filtering functionality. - */ - private static class FilterUI { - /** - * an icon to use - */ - private static final Icon FILTER_ICON = IconLoader.getIcon("/icons/inspector/useFilter.png"); - /** - * a parent popup - */ - final ChooseByNamePopup myParentPopup; - /** - * action toolbar - */ - final ActionToolbar myToolbar; - /** - * a file type chooser, only one instance is used - */ - final ElementsChooser myChooser; - /** - * A panel that contains chooser - */ - final JPanel myChooserPanel; - /** - * a file type popup, the value is non-null if popup is active - */ - JBPopup myPopup; - /** - * a project to use. The project is used for dimension service. - */ - final Project myProject; - - /** - * A constuctor - * - * @param popup a parent popup - * @param gotoFileModel a model for popup - * @param project a context project - */ - FilterUI(final ChooseByNamePopup popup, final GotoFileModel gotoFileModel, final Project project) { - myParentPopup = popup; - DefaultActionGroup actionGroup = new DefaultActionGroup("go.to.file.filter", false); - ToggleAction action = new ToggleAction("Filter", "Filter files by type", FILTER_ICON) { - public boolean isSelected(final AnActionEvent e) { - return myPopup != null; - } - - public void setSelected(final AnActionEvent e, final boolean state) { - if (state) { - createPopup(); - } - else { - close(); - } - } - }; - actionGroup.add(action); - myToolbar = ActionManager.getInstance().createActionToolbar("gotfile.filter", actionGroup, true); - myToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY); - myToolbar.updateActionsImmediately(); - myToolbar.getComponent().setFocusable(false); - myToolbar.getComponent().setBorder(null); - myProject = project; - myChooser = createFileTypeChooser(gotoFileModel); - myChooserPanel = createChooserPanel(); - popup.setToolArea(myToolbar.getComponent()); + protected static class GotoFileFilter extends ChooseByNameFilter { + GotoFileFilter(final ChooseByNamePopup popup, GotoFileModel model, final Project project) { + super(popup, model, GotoFileConfiguration.getInstance(project), project); } - /** - * @return a panel with chooser and buttons - */ - private JPanel createChooserPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); - panel.add(myChooser); - JPanel buttons = new JPanel(); - JButton all = new JButton("All"); - all.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - myChooser.setAllElementsMarked(true); - } - }); - buttons.add(all); - JButton none = new JButton("None"); - none.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - myChooser.setAllElementsMarked(false); - } - }); - buttons.add(none); - JButton invert = new JButton("Invert"); - invert.addActionListener(new ActionListener() { - public void actionPerformed(final ActionEvent e) { - final int count = myChooser.getElementCount(); - for (int i = 0; i < count; i++) { - FileType type = myChooser.getElementAt(i); - myChooser.setElementMarked(type, !myChooser.isElementMarked(type)); - } - } - }); - buttons.add(invert); - panel.add(buttons); - return panel; - } - - /** - * Create a file type chooser - * - * @param gotoFileModel a model to update - * @return a created file chooser - */ - private ElementsChooser createFileTypeChooser(final GotoFileModel gotoFileModel) { + protected List getAllFilterValues() { List elements = new ArrayList(); ContainerUtil.addAll(elements, FileTypeManager.getInstance().getRegisteredFileTypes()); Collections.sort(elements, FileTypeComparator.INSTANCE); - final ElementsChooser chooser = new ElementsChooser(elements, true) { - @Override - protected String getItemText(@NotNull final FileType value) { - return value.getName(); - } - - @Override - protected Icon getItemIcon(final FileType value) { - return value.getIcon(); - } - }; - chooser.setFocusable(false); - final GotoFileConfiguration config = GotoFileConfiguration.getInstance(myProject); - final int count = chooser.getElementCount(); - for (int i = 0; i < count; i++) { - FileType type = chooser.getElementAt(i); - if (!DumbService.getInstance(myProject).isDumb() && !config.isFileTypeVisible(type)) { - chooser.setElementMarked(type, false); - } - } - updateModel(gotoFileModel, chooser); - chooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener() { - public void elementMarkChanged(final FileType element, final boolean isMarked) { - config.setFileTypeVisible(element, isMarked); - updateModel(gotoFileModel, chooser); - } - }); - return chooser; + return elements; } - /** - * Update model basing on the chooser state - * - * @param gotoFileModel a model - * @param chooser a file type chooser - */ - private void updateModel(final GotoFileModel gotoFileModel, ElementsChooser chooser) { - final List markedElements = chooser.getMarkedElements(); - gotoFileModel.setFileTypes(markedElements.toArray(new FileType[markedElements.size()])); - myParentPopup.rebuildList(); + protected String textForFilterValue(FileType value) { + return value.getName(); } - - /** - * Create and show popup - */ - private void createPopup() { - if (myPopup != null) { - return; - } - myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myChooserPanel, myChooser).setModalContext(false).setFocusable(false) - .setResizable(true).setCancelOnClickOutside(false).setMinSize(new Dimension(200, 200)) - .setDimensionServiceKey(myProject, "GotoFile_FileTypePopup", false).createPopup(); - myPopup.addListener(new JBPopupListener.Adapter() { - public void onClosed(LightweightWindowEvent event) { - myPopup = null; - } - }); - myPopup.showUnderneathOf(myToolbar.getComponent()); + protected Icon iconForFilterValue(FileType value) { + return value.getIcon(); } + } + + /** + * A file type comparator. The comparison rules are applied in the following order. + *
    + *
  1. Unknown file type is greatest.
  2. + *
  3. Text files are less then binary ones.
  4. + *
  5. File type with greater name is greater (case is ignored).
  6. + *
+ */ + static class FileTypeComparator implements Comparator { + /** + * an instance of comparator + */ + static final Comparator INSTANCE = new FileTypeComparator(); /** - * close the file type filter + * {@inheritDoc} */ - public void close() { - if (myPopup != null) { - myPopup.dispose(); + public int compare(final FileType o1, final FileType o2) { + if (o1 == o2) { + return 0; } - } - - /** - * A file type comparator. The comparison rules are applied in the following order. - *
    - *
  1. Unknown file type is greatest.
  2. - *
  3. Text files are less then binary ones.
  4. - *
  5. File type with greater name is greater (case is ignored).
  6. - *
- */ - static class FileTypeComparator implements Comparator { - /** - * an instance of comparator - */ - static final Comparator INSTANCE = new FileTypeComparator(); - - /** - * {@inheritDoc} - */ - public int compare(final FileType o1, final FileType o2) { - if (o1 == o2) { - return 0; - } - if (o1 == FileTypes.UNKNOWN) { - return 1; - } - if (o2 == FileTypes.UNKNOWN) { - return -1; - } - if (o1.isBinary() && !o2.isBinary()) { - return 1; - } - if (!o1.isBinary() && o2.isBinary()) { - return -1; - } - return o1.getName().compareToIgnoreCase(o2.getName()); + if (o1 == FileTypes.UNKNOWN) { + return 1; } + if (o2 == FileTypes.UNKNOWN) { + return -1; + } + if (o1.isBinary() && !o2.isBinary()) { + return 1; + } + if (!o1.isBinary() && o2.isBinary()) { + return -1; + } + return o1.getName().compareToIgnoreCase(o2.getName()); } } } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java index 347da16a37a4..26a68ae23cb3 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoSymbolAction.java @@ -17,9 +17,7 @@ package com.intellij.ide.actions; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.ide.util.gotoByName.ChooseByNamePopup; -import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent; -import com.intellij.ide.util.gotoByName.GotoSymbolModel2; +import com.intellij.ide.util.gotoByName.*; import com.intellij.navigation.NavigationItem; import com.intellij.navigation.ChooseByNameRegistry; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -37,14 +35,18 @@ public class GotoSymbolAction extends GotoActionBase { PsiDocumentManager.getInstance(project).commitAllDocuments(); - final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, new GotoSymbolModel2(project), getPsiContext(e)); + final GotoSymbolModel2 model = new GotoSymbolModel2(project); + final ChooseByNamePopup popup = ChooseByNamePopup.createPopup(project, model, getPsiContext(e)); + final ChooseByNameFilter filterUI = new ChooseByNameLanguageFilter(popup, model, GotoClassSymbolConfiguration.getInstance(project), + project); popup.invoke(new ChooseByNamePopupComponent.Callback() { - public void onClose () - { - if (GotoSymbolAction.class.equals (myInAction)) { + public void onClose() { + if (GotoSymbolAction.class.equals(myInAction)) { myInAction = null; } + filterUI.close(); } + public void elementChosen(Object element) { ((NavigationItem)element).navigate(true); } diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextProvider.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextProvider.java index 1233012bf2ef..2368c0646a2f 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextProvider.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextProvider.java @@ -18,6 +18,7 @@ package com.intellij.ide.scriptingContext; import com.intellij.lang.Language; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.roots.libraries.LibraryType; import org.jetbrains.annotations.NotNull; /** @@ -31,6 +32,8 @@ public abstract class LangScriptingContextProvider { @NotNull public abstract Language getLanguage(); + public abstract LibraryType getLibraryType(); + public abstract boolean acceptsExtension(String fileExt); @NotNull diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java index ab50911de9e5..c2082143650b 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java @@ -16,6 +16,7 @@ package com.intellij.ide.scriptingContext.ui; import com.intellij.ide.scriptingContext.LangScriptingContextProvider; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; @@ -44,7 +45,7 @@ public class ScriptingLibrariesPanel { public ScriptingLibrariesPanel(LangScriptingContextProvider provider, Project project, LibraryTable libTable) { myProvider = provider; - myLibTableModel = new ScriptingLibraryTableModel(libTable); + myLibTableModel = new ScriptingLibraryTableModel(libTable, provider.getLibraryType()); myLibraryTable.setModel(myLibTableModel); myAddLibraryButton.addActionListener(new ActionListener(){ @Override @@ -56,7 +57,7 @@ public class ScriptingLibrariesPanel { @Override public void actionPerformed(ActionEvent e) { if (mySelectedLibName != null) { - myLibTableModel.removeLibrary(mySelectedLibName); + removeLibrary(mySelectedLibName); } } }); @@ -85,11 +86,20 @@ public class ScriptingLibrariesPanel { return myTopPanel; } + private void removeLibrary(final String libName) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + myLibTableModel.removeLibrary(libName); + } + }); + } + private void addLibrary() { EditLibraryDialog editLibDialog = new EditLibraryDialog("New Library", myProvider, myProject); editLibDialog.show(); if (editLibDialog.isOK()) { - myLibTableModel.createLibrary(editLibDialog.getLibName(), editLibDialog.getFiles()); + myLibTableModel.createLibrary(editLibDialog.getLibName(), myProvider.getLibraryType(), editLibDialog.getFiles()); } } @@ -121,8 +131,8 @@ public class ScriptingLibrariesPanel { EditLibraryDialog editLibDialog = new EditLibraryDialog("Edit Library", myProvider, myProject, lib); editLibDialog.show(); if (editLibDialog.isOK()) { - myLibTableModel.removeLibrary(lib.getName()); - myLibTableModel.createLibrary(editLibDialog.getLibName(), editLibDialog.getFiles()); + removeLibrary(lib.getName()); + myLibTableModel.createLibrary(editLibDialog.getLibName(), myProvider.getLibraryType(), editLibDialog.getFiles()); } } } diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryTableModel.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryTableModel.java index 524b664586fe..ca61faa6a216 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryTableModel.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryTableModel.java @@ -15,9 +15,12 @@ */ package com.intellij.ide.scriptingContext.ui; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.impl.libraries.LibraryTableBase; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryType; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Nullable; @@ -31,26 +34,29 @@ public class ScriptingLibraryTableModel extends AbstractTableModel { private static final int LIB_NAME_COL = 0; - private LibraryTable myLibTable; - private LibraryTable.ModifiableModel myLibTableModel; - private boolean myTableChanged; + //private LibraryTable myLibTable; + private TypedLibraryTableWrapper myTableWrapper; + private LibraryTableBase.ModifiableModelEx myLibTableModel; + private LibraryType myLibraryType; - public ScriptingLibraryTableModel(LibraryTable libTable) { - myLibTable = libTable; - myLibTableModel = libTable.getModifiableModel(); - myTableChanged = false; + public ScriptingLibraryTableModel(LibraryTable libTable, LibraryType libraryType) { + LibraryTable.ModifiableModel model = libTable.getModifiableModel(); + if (model instanceof LibraryTableBase.ModifiableModelEx) { + myTableWrapper = new TypedLibraryTableWrapper(libTable, libraryType); + myLibTableModel = (LibraryTableBase.ModifiableModelEx)model; + myLibraryType = libraryType; + } } public void resetTable(LibraryTable libTable) { - myLibTable = libTable; - myTableChanged = false; + myTableWrapper = new TypedLibraryTableWrapper(libTable, myLibraryType); fireTableDataChanged(); } @Override public int getRowCount() { - if (myLibTable != null) { - return myLibTable.getLibraries().length; + if (myTableWrapper != null) { + return myTableWrapper.getLibCount(); } return 0; } @@ -62,8 +68,10 @@ public class ScriptingLibraryTableModel extends AbstractTableModel { @Override public Object getValueAt(int rowIndex, int columnIndex) { + Library lib = myTableWrapper.getLibraryAt(rowIndex); + assert lib != null; if (columnIndex == LIB_NAME_COL) { - return myLibTable.getLibraries()[rowIndex].getName(); + return lib.getName(); } return "?"; } @@ -76,44 +84,48 @@ public class ScriptingLibraryTableModel extends AbstractTableModel { return "?"; } - public void createLibrary(String name, VirtualFile[] files) { - Library lib = myLibTable.createLibrary(name); - Library.ModifiableModel libModel = lib.getModifiableModel(); - for (VirtualFile file : files) { - libModel.addRoot(file, OrderRootType.CLASSES); - } - libModel.commit(); - myLibTableModel.commit(); - fireLibTableChanged(); + public void createLibrary(final String name, final LibraryType libType, final VirtualFile[] files) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + Library lib = myLibTableModel.createLibrary(name, libType); + Library.ModifiableModel libModel = lib.getModifiableModel(); + for (VirtualFile file : files) { + libModel.addRoot(file, OrderRootType.CLASSES); + } + libModel.commit(); + myLibTableModel.commit(); + fireLibTableChanged(); + } + }); } @Nullable public Library getLibrary(String name) { - return myLibTable == null ? null : myLibTable.getLibraryByName(name); + return myTableWrapper == null ? null : myTableWrapper.getLibraryByName(name); } public void removeLibrary(String name) { - Library libToRemove = myLibTable.getLibraryByName(name); + Library libToRemove = myTableWrapper.getLibraryByName(name); if (libToRemove != null) { - myLibTable.removeLibrary(libToRemove); + myTableWrapper.removeLibrary(libToRemove); fireLibTableChanged(); } } public void fireLibTableChanged() { - myTableChanged = true; + myTableWrapper.update(); fireTableDataChanged(); } @Nullable public String getLibNameAt(int row) { - Library[] libs = myLibTable.getLibraries(); - if (row < 0 || row > libs.length - 1) return null; - return libs[row].getName(); + Library lib = myTableWrapper.getLibraryAt(row); + return lib != null ? lib.getName() : null; } public boolean isChanged() { - return myTableChanged; + return myTableWrapper.isUpdated(); } } diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/TypedLibraryTableWrapper.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/TypedLibraryTableWrapper.java new file mode 100644 index 000000000000..94976a97856e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/TypedLibraryTableWrapper.java @@ -0,0 +1,90 @@ +/* + * 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.ide.scriptingContext.ui; + +import com.intellij.openapi.roots.impl.libraries.LibraryEx; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryType; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Rustam Vishnyakov + */ +public class TypedLibraryTableWrapper { + + private LibraryTable myLibraryTable; + private LibraryType myLibraryType; + private Library[] myLibs; + private boolean myIsUpdated; + + public TypedLibraryTableWrapper(LibraryTable libraryTable, LibraryType libraryType) { + myLibraryTable = libraryTable; + myLibraryType = libraryType; + myLibs = getLibraries(); + myIsUpdated = false; + } + + private Library[] getLibraries() { + List libs = new ArrayList(); + for (Library library : myLibraryTable.getLibraries()) { + if (library instanceof LibraryEx) { + LibraryType libraryType = ((LibraryEx)library).getType(); + if (libraryType != null && libraryType.equals(myLibraryType)) { + libs.add(library); + } + } + } + return libs.toArray(new Library[libs.size()]); + } + + public void update() { + myLibs = getLibraries(); + myIsUpdated = true; + } + + public int getLibCount() { + return myLibs.length; + } + + @Nullable + public Library getLibraryAt(int index) { + if (index >= 0 && index < myLibs.length) { + return myLibs[index]; + } + return null; + } + + @Nullable + public Library getLibraryByName(String name) { + Library library = myLibraryTable.getLibraryByName(name); + if (library instanceof LibraryEx && ((LibraryEx)library).getType().equals(myLibraryType)) { + return library; + } + return null; + } + + public void removeLibrary(Library libToRemove) { + myLibraryTable.removeLibrary(libToRemove); + } + + public boolean isUpdated() { + return myIsUpdated; + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java index 697f617f61a5..3e15f4b0eb3d 100644 --- a/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java +++ b/platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java @@ -19,7 +19,6 @@ package com.intellij.ide.structureView.newStructureView; import com.intellij.ide.CopyPasteDelegator; import com.intellij.ide.DataManager; import com.intellij.ide.PsiCopyPasteManager; -import com.intellij.ide.actions.ContextHelpAction; import com.intellij.ide.structureView.*; import com.intellij.ide.structureView.impl.StructureViewFactoryImpl; import com.intellij.ide.structureView.impl.StructureViewState; @@ -50,6 +49,8 @@ import com.intellij.ui.AutoScrollToSourceHandler; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.treeStructure.Tree; +import com.intellij.ui.treeStructure.actions.CollapseAllAction; +import com.intellij.ui.treeStructure.actions.ExpandAllAction; import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; import com.intellij.util.EditSourceOnDoubleClickHandler; @@ -384,14 +385,14 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre result.add(new TreeActionWrapper(filter, this)); } + result.add(new ExpandAllAction(getTree())); + result.add(new CollapseAllAction(getTree())); if (showScrollToFromSourceActions()) { result.addSeparator(); result.add(myAutoScrollToSourceHandler.createToggleAction()); result.add(myAutoScrollFromSourceHandler.createToggleAction()); } - result.addSeparator(); - result.add(new ContextHelpAction(getHelpID())); return result; } @@ -707,7 +708,7 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre public void doUpdate() { assert ApplicationManager.getApplication().isUnitTestMode(); - ((StructureTreeBuilder)myAbstractTreeBuilder).addRootToUpdate(); + myAbstractTreeBuilder.addRootToUpdate(); } //todo [kirillk] dirty hack for discovering invalid psi elements, to delegate it to a proper place after 8.1 diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java new file mode 100644 index 000000000000..fe5feb4ff8de --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilter.java @@ -0,0 +1,232 @@ +/* + * 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.ide.util.gotoByName; + +import com.intellij.ide.util.ElementsChooser; +import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.project.DumbService; +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.JBPopupListener; +import com.intellij.openapi.ui.popup.LightweightWindowEvent; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.IconLoader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * This class contains UI related to filtering functionality. + */ +public abstract class ChooseByNameFilter { + /** + * an icon to use + */ + private static final Icon FILTER_ICON = IconLoader.getIcon("/icons/inspector/useFilter.png"); + /** + * a parent popup + */ + final ChooseByNamePopup myParentPopup; + /** + * action toolbar + */ + final ActionToolbar myToolbar; + /** + * a file type chooser, only one instance is used + */ + final ElementsChooser myChooser; + /** + * A panel that contains chooser + */ + final JPanel myChooserPanel; + /** + * a file type popup, the value is non-null if popup is active + */ + JBPopup myPopup; + /** + * a project to use. The project is used for dimension service. + */ + final Project myProject; + + /** + * A constuctor + * + * @param popup a parent popup + * @param model a model for popup + * @param filterConfiguration storage for selected filter values + * @param project a context project + */ + public ChooseByNameFilter(final ChooseByNamePopup popup, FilteringGotoByModel model, ChooseByNameFilterConfiguration filterConfiguration, + final Project project) { + myParentPopup = popup; + DefaultActionGroup actionGroup = new DefaultActionGroup("go.to.file.filter", false); + ToggleAction action = new ToggleAction("Filter", "Filter files by type", FILTER_ICON) { + public boolean isSelected(final AnActionEvent e) { + return myPopup != null; + } + + public void setSelected(final AnActionEvent e, final boolean state) { + if (state) { + createPopup(); + } + else { + close(); + } + } + }; + actionGroup.add(action); + myToolbar = ActionManager.getInstance().createActionToolbar("gotfile.filter", actionGroup, true); + myToolbar.setLayoutPolicy(ActionToolbar.NOWRAP_LAYOUT_POLICY); + myToolbar.updateActionsImmediately(); + myToolbar.getComponent().setFocusable(false); + myToolbar.getComponent().setBorder(null); + myProject = project; + myChooser = createChooser(model, filterConfiguration); + myChooserPanel = createChooserPanel(); + popup.setToolArea(myToolbar.getComponent()); + } + + /** + * @return a panel with chooser and buttons + */ + private JPanel createChooserPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.add(myChooser); + JPanel buttons = new JPanel(); + JButton all = new JButton("All"); + all.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + myChooser.setAllElementsMarked(true); + } + }); + buttons.add(all); + JButton none = new JButton("None"); + none.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + myChooser.setAllElementsMarked(false); + } + }); + buttons.add(none); + JButton invert = new JButton("Invert"); + invert.addActionListener(new ActionListener() { + public void actionPerformed(final ActionEvent e) { + final int count = myChooser.getElementCount(); + for (int i = 0; i < count; i++) { + T type = myChooser.getElementAt(i); + myChooser.setElementMarked(type, !myChooser.isElementMarked(type)); + } + } + }); + buttons.add(invert); + panel.add(buttons); + return panel; + } + + /** + * Create a file type chooser + * + * + * @param model a model to update + * @param filterConfiguration + * @return a created file chooser + */ + protected ElementsChooser createChooser(final FilteringGotoByModel model, final ChooseByNameFilterConfiguration filterConfiguration) { + List elements = new ArrayList(getAllFilterValues()); + final ElementsChooser chooser = new ElementsChooser(elements, true) { + @Override + protected String getItemText(@NotNull final T value) { + return textForFilterValue(value); + } + + @Override + protected Icon getItemIcon(final T value) { + return iconForFilterValue(value); + } + }; + chooser.setFocusable(false); + final int count = chooser.getElementCount(); + for (int i = 0; i < count; i++) { + T type = chooser.getElementAt(i); + if (!DumbService.getInstance(myProject).isDumb() && !filterConfiguration.isFileTypeVisible(type)) { + chooser.setElementMarked(type, false); + } + } + updateModel(model, chooser); + chooser.addElementsMarkListener(new ElementsChooser.ElementsMarkListener() { + public void elementMarkChanged(final T element, final boolean isMarked) { + filterConfiguration.setVisible(element, isMarked); + updateModel(model, chooser); + } + }); + return chooser; + + } + + protected abstract String textForFilterValue(T value); + + @Nullable + protected abstract Icon iconForFilterValue(T value); + + protected abstract Collection getAllFilterValues(); + + /** + * Update model basing on the chooser state + * + * @param gotoFileModel a model + * @param chooser a file type chooser + */ + protected void updateModel(final FilteringGotoByModel gotoFileModel, ElementsChooser chooser) { + final List markedElements = chooser.getMarkedElements(); + gotoFileModel.setFilterItems(markedElements); + myParentPopup.rebuildList(); + } + + /** + * Create and show popup + */ + private void createPopup() { + if (myPopup != null) { + return; + } + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(myChooserPanel, myChooser).setModalContext(false).setFocusable(false) + .setResizable(true).setCancelOnClickOutside(false).setMinSize(new Dimension(200, 200)) + .setDimensionServiceKey(myProject, "GotoFile_FileTypePopup", false).createPopup(); + myPopup.addListener(new JBPopupListener.Adapter() { + public void onClosed(LightweightWindowEvent event) { + myPopup = null; + } + }); + myPopup.showUnderneathOf(myToolbar.getComponent()); + } + + /** + * close the file type filter + */ + public void close() { + if (myPopup != null) { + Disposer.dispose(myPopup); + } + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileConfiguration.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilterConfiguration.java similarity index 57% rename from platform/lang-impl/src/com/intellij/ide/actions/GotoFileConfiguration.java rename to platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilterConfiguration.java index 41e17dd377c3..bb5f5ef4f92f 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/GotoFileConfiguration.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameFilterConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -13,15 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package com.intellij.ide.actions; +package com.intellij.ide.util.gotoByName; import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.project.Project; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Tag; @@ -29,33 +23,26 @@ import java.util.LinkedHashSet; import java.util.Set; /** - * Configuration for file type filtering popup in "Go to | File" action. - * - * @author Constantine.Plotnikov + * @author yole */ -@State( - name = "GotoFileConfiguration", - storages = {@Storage( - id = "other", - file = "$WORKSPACE_FILE$")}) -public class GotoFileConfiguration implements PersistentStateComponent { +public abstract class ChooseByNameFilterConfiguration implements PersistentStateComponent { /** * state object for the configuration */ - private FileTypes fileTypes = new FileTypes(); + private Items items = new Items(); /** * {@inheritDoc} */ - public FileTypes getState() { - return fileTypes; + public Items getState() { + return items; } /** * {@inheritDoc} */ - public void loadState(final FileTypes state) { - fileTypes = state; + public void loadState(final Items state) { + items = state; } /** @@ -64,39 +51,31 @@ public class GotoFileConfiguration implements PersistentStateComponent { + public ChooseByNameLanguageFilter(final ChooseByNamePopup popup, + FilteringGotoByModel languageFilteringGotoByModel, + ChooseByNameFilterConfiguration languageChooseByNameFilterConfiguration, + final Project project) { + super(popup, languageFilteringGotoByModel, languageChooseByNameFilterConfiguration, project); + } + + @Override + protected String textForFilterValue(Language value) { + return value.getDisplayName(); + } + + @Nullable + @Override + protected Icon iconForFilterValue(Language value) { + final LanguageFileType fileType = value.getAssociatedFileType(); + return fileType != null ? fileType.getIcon() : null; + } + + @Override + protected Collection getAllFilterValues() { + final Collection registeredLanguages = Language.getRegisteredLanguages(); + List accepted = new ArrayList(); + for (Language language : registeredLanguages) { + if (language != Language.ANY && !(language instanceof DependentLanguage)) { + accepted.add(language); + } + } + Collections.sort(accepted, new Comparator() { + @Override + public int compare(Language o1, Language o2) { + return o1.getDisplayName().compareTo(o2.getDisplayName()); + } + }); + return accepted; + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java index 2e609988b096..e9e711223840 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ContributorsBasedGotoByModel.java @@ -136,8 +136,9 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel } /** - * This method allows exetending classes to introduce additional filtering criteria to model - * beyoud pattern and project/non-project files. The default implementation just returns true. + * This method allows extending classes to introduce additional filtering criteria to model + * beyond pattern and project/non-project files. The default implementation just returns true. + * * @param item an item to filter * @return true if the item is acceptable according to additional filtering criteria. */ diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FilteringGotoByModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FilteringGotoByModel.java new file mode 100644 index 000000000000..a5f6d4ea9df8 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/FilteringGotoByModel.java @@ -0,0 +1,67 @@ +/* + * 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.ide.util.gotoByName; + +import com.intellij.navigation.ChooseByNameContributor; +import com.intellij.navigation.NavigationItem; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * @author yole + */ +public abstract class FilteringGotoByModel extends ContributorsBasedGotoByModel { + /** current file types */ + private Set myFilterItems; + + protected FilteringGotoByModel(Project project, ChooseByNameContributor[] contributors) { + super(project, contributors); + } + + /** + * Set file types + * @param filterItems a file types to set + */ + public synchronized void setFilterItems(Collection filterItems) { + // get and set method are called from different threads + myFilterItems = new HashSet(filterItems); + } + + /** + * @return get file types + */ + protected synchronized Collection getFilterItems() { + // get and set method are called from different threads + return myFilterItems; + } + + @Override + protected boolean acceptItem(final NavigationItem item) { + T filterValue = filterValueFor(item); + if (filterValue != null) { + final Collection types = getFilterItems(); + return types == null || types.contains(filterValue); + } + return true; + } + + @Nullable + protected abstract T filterValueFor(NavigationItem item); +} diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java index 90f6d20e5db3..ba00a54753f3 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassModel2.java @@ -17,20 +17,27 @@ package com.intellij.ide.util.gotoByName; import com.intellij.ide.IdeBundle; import com.intellij.ide.util.PropertiesComponent; +import com.intellij.lang.Language; import com.intellij.navigation.ChooseByNameContributor; import com.intellij.navigation.ChooseByNameRegistry; import com.intellij.navigation.GotoClassContributor; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class GotoClassModel2 extends ContributorsBasedGotoByModel { +public class GotoClassModel2 extends FilteringGotoByModel { public GotoClassModel2(Project project) { super(project, ChooseByNameRegistry.getInstance().getClassModelContributors()); } + @Override + protected Language filterValueFor(NavigationItem item) { + return item instanceof PsiElement ? ((PsiElement) item).getLanguage() : null; + } + @Nullable public String getPromptText() { return IdeBundle.message("prompt.gotoclass.enter.class.name"); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassSymbolConfiguration.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassSymbolConfiguration.java new file mode 100644 index 000000000000..e6ca7cd1e29e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoClassSymbolConfiguration.java @@ -0,0 +1,41 @@ +/* + * 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.ide.util.gotoByName; + +import com.intellij.lang.Language; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.project.Project; + +/** + * @author yole + */ +@State( + name = "GotoFileConfiguration", + storages = {@Storage( + id = "other", + file = "$WORKSPACE_FILE$")}) +public class GotoClassSymbolConfiguration extends ChooseByNameFilterConfiguration { + public static GotoClassSymbolConfiguration getInstance(Project project) { + return ServiceManager.getService(project, GotoClassSymbolConfiguration.class); + } + + @Override + protected String nameForElement(Language type) { + return type.getID(); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileConfiguration.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileConfiguration.java new file mode 100644 index 000000000000..2e543dc148aa --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2009 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.intellij.ide.util.gotoByName; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; + +/** + * Configuration for file type filtering popup in "Go to | File" action. + * + * @author Constantine.Plotnikov + */ +@State( + name = "GotoFileConfiguration", + storages = {@Storage( + id = "other", + file = "$WORKSPACE_FILE$")}) +public class GotoFileConfiguration extends ChooseByNameFilterConfiguration { + /** + * Get configuration instance + * + * @param project a project instance + * @return a configuration instance + */ + public static GotoFileConfiguration getInstance(Project project) { + return ServiceManager.getService(project, GotoFileConfiguration.class); + } + + @Override + protected String nameForElement(FileType type) { + return type.getName(); + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java index b0f23436c123..da5e00d7a55d 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoFileModel.java @@ -31,45 +31,24 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.Collection; /** * Model for "Go to | File" action */ -public class GotoFileModel extends ContributorsBasedGotoByModel{ +public class GotoFileModel extends FilteringGotoByModel { private final int myMaxSize; - /** current file types */ - private HashSet myFileTypes; public GotoFileModel(Project project) { super(project, Extensions.getExtensions(ChooseByNameContributor.FILE_EP_NAME)); myMaxSize = WindowManagerEx.getInstanceEx().getFrame(project).getSize().width; } - /** - * Set file types - * @param fileTypes a file types to set - */ - public synchronized void setFileTypes(FileType[] fileTypes) { - // get and set method are called from different threads - myFileTypes = new HashSet(Arrays.asList(fileTypes)); - } - - /** - * @return get file types - */ - private synchronized Set getFileTypes() { - // get and set method are called from different threads - return myFileTypes; - } - @Override protected boolean acceptItem(final NavigationItem item) { if (item instanceof PsiFile) { final PsiFile file = (PsiFile)item; - final Set types = getFileTypes(); + final Collection types = getFilterItems(); // if language substitutors are used, PsiFile.getFileType() can be different from // PsiFile.getVirtualFile().getFileType() if (types != null) { @@ -85,6 +64,12 @@ public class GotoFileModel extends ContributorsBasedGotoByModel{ } } + @Nullable + @Override + protected FileType filterValueFor(NavigationItem item) { + return item instanceof PsiFile ? ((PsiFile) item).getFileType() : null; + } + public String getPromptText() { return IdeBundle.message("prompt.gotofile.enter.file.name"); } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoSymbolModel2.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoSymbolModel2.java index f7244901207d..1fe4708146f3 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoSymbolModel2.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoSymbolModel2.java @@ -16,18 +16,25 @@ package com.intellij.ide.util.gotoByName; import com.intellij.ide.IdeBundle; +import com.intellij.lang.Language; import com.intellij.navigation.ChooseByNameRegistry; +import com.intellij.navigation.NavigationItem; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.psi.PsiElement; import com.intellij.psi.presentation.java.SymbolPresentationUtil; import org.jetbrains.annotations.NotNull; -public class GotoSymbolModel2 extends ContributorsBasedGotoByModel { +public class GotoSymbolModel2 extends FilteringGotoByModel { public GotoSymbolModel2(Project project) { super(project, ChooseByNameRegistry.getInstance().getSymbolModelContributors()); } + @Override + protected Language filterValueFor(NavigationItem item) { + return item instanceof PsiElement ? ((PsiElement) item).getLanguage() : null; + } + public String getPromptText() { return IdeBundle.message("prompt.gotosymbol.enter.symbol.name"); } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/ex/PathUtilEx.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/ex/PathUtilEx.java index 3d6a84fc9589..c883b5ddfd87 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/ex/PathUtilEx.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/ex/PathUtilEx.java @@ -55,7 +55,7 @@ public class PathUtilEx { } public static Sdk chooseJdk(Project project, Collection modules) { - Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); if (projectJdk != null) { return projectJdk; } diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java index 3a4b490bc5c4..a775bf1399e2 100644 --- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java +++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java @@ -159,7 +159,7 @@ public class SdkConfigurationUtil { public static void setDirectoryProjectSdk(final Project project, final Sdk sdk) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { - ProjectRootManager.getInstance(project).setProjectJdk(sdk); + ProjectRootManager.getInstance(project).setProjectSdk(sdk); final Module[] modules = ModuleManager.getInstance(project).getModules(); if (modules.length > 0) { final ModifiableRootModel model = ModuleRootManager.getInstance(modules[0]).getModifiableModel(); @@ -171,7 +171,7 @@ public class SdkConfigurationUtil { } public static void configureDirectoryProjectSdk(final Project project, final SdkType... sdkTypes) { - Sdk existingSdk = ProjectRootManager.getInstance(project).getProjectJdk(); + Sdk existingSdk = ProjectRootManager.getInstance(project).getProjectSdk(); if (existingSdk != null && ArrayUtil.contains(existingSdk.getSdkType(), sdkTypes)) { return; } @@ -185,7 +185,7 @@ public class SdkConfigurationUtil { @Nullable public static Sdk findOrCreateSdk(final SdkType... sdkTypes) { final Project defaultProject = ProjectManager.getInstance().getDefaultProject(); - final Sdk sdk = ProjectRootManager.getInstance(defaultProject).getProjectJdk(); + final Sdk sdk = ProjectRootManager.getInstance(defaultProject).getProjectSdk(); if (sdk != null) { for (SdkType type : sdkTypes) { if (sdk.getSdkType() == type) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/InheritedJdkOrderEntryImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/InheritedJdkOrderEntryImpl.java index be03ff5ca38b..05f8becf83ca 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/InheritedJdkOrderEntryImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/InheritedJdkOrderEntryImpl.java @@ -89,7 +89,7 @@ public class InheritedJdkOrderEntryImpl extends LibraryOrderEntryBaseImpl implem } protected RootProvider getRootProvider() { - final Sdk projectJdk = myProjectRootManagerImpl.getProjectJdk(); + final Sdk projectJdk = myProjectRootManagerImpl.getProjectSdk(); return projectJdk == null ? null : projectJdk.getRootProvider(); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java index 091e451f5dd1..67425f598591 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java @@ -82,8 +82,8 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj private AppListener myApplicationListener; - private String myProjectJdkName; - private String myProjectJdkType; + private String myProjectSdkName; + private String myProjectSdkType; private final List myRootsChangeUpdaters = new ArrayList(); private final List myRefreshCacheUpdaters = new ArrayList(); @@ -327,28 +327,28 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj return VfsUtil.toVirtualFileArray(result); } - public Sdk getProjectJdk() { - if (myProjectJdkName != null) { - return ProjectJdkTable.getInstance().findJdk(myProjectJdkName, myProjectJdkType); + public Sdk getProjectSdk() { + if (myProjectSdkName != null) { + return ProjectJdkTable.getInstance().findJdk(myProjectSdkName, myProjectSdkType); } else { return null; } } - public String getProjectJdkName() { - return myProjectJdkName; + public String getProjectSdkName() { + return myProjectSdkName; } - public void setProjectJdk(Sdk projectJdk) { + public void setProjectSdk(Sdk projectSdk) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - if (projectJdk != null) { - myProjectJdkName = projectJdk.getName(); - myProjectJdkType = projectJdk.getSdkType().getName(); + if (projectSdk != null) { + myProjectSdkName = projectSdk.getName(); + myProjectSdkType = projectSdk.getSdkType().getName(); } else { - myProjectJdkName = null; - myProjectJdkType = null; + myProjectSdkName = null; + myProjectSdkType = null; } mergeRootsChangesDuring(new Runnable() { public void run() { @@ -357,9 +357,9 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj }); } - public void setProjectJdkName(String name) { + public void setProjectSdkName(String name) { ApplicationManager.getApplication().assertWriteAccessAllowed(); - myProjectJdkName = name; + myProjectSdkName = name; mergeRootsChangesDuring(new Runnable() { public void run() { @@ -409,8 +409,8 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj for (ProjectExtension extension : Extensions.getExtensions(ProjectExtension.EP_NAME, myProject)) { extension.readExternal(element); } - myProjectJdkName = element.getAttributeValue(PROJECT_JDK_NAME_ATTR); - myProjectJdkType = element.getAttributeValue(PROJECT_JDK_TYPE_ATTR); + myProjectSdkName = element.getAttributeValue(PROJECT_JDK_NAME_ATTR); + myProjectSdkType = element.getAttributeValue(PROJECT_JDK_TYPE_ATTR); } public void writeExternal(Element element) throws WriteExternalException { @@ -418,11 +418,11 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj for (ProjectExtension extension : Extensions.getExtensions(ProjectExtension.EP_NAME, myProject)) { extension.writeExternal(element); } - if (myProjectJdkName != null) { - element.setAttribute(PROJECT_JDK_NAME_ATTR, myProjectJdkName); + if (myProjectSdkName != null) { + element.setAttribute(PROJECT_JDK_NAME_ATTR, myProjectSdkName); } - if (myProjectJdkType != null) { - element.setAttribute(PROJECT_JDK_TYPE_ATTR, myProjectJdkType); + if (myProjectSdkType != null) { + element.setAttribute(PROJECT_JDK_TYPE_ATTR, myProjectSdkType); } } @@ -946,11 +946,11 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Proj myDispatcher.getMulticaster().jdkNameChanged(jdk, previousName); } }); - String currentName = getProjectJdkName(); + String currentName = getProjectSdkName(); if (previousName != null && previousName.equals(currentName)) { // if already had jdk name and that name was the name of the jdk just changed - myProjectJdkName = jdk.getName(); - myProjectJdkType = jdk.getSdkType().getName(); + myProjectSdkName = jdk.getName(); + myProjectSdkType = jdk.getSdkType().getName(); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootConfigurationAccessor.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootConfigurationAccessor.java index ab33bd5434a8..3800dc91a028 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootConfigurationAccessor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootConfigurationAccessor.java @@ -42,11 +42,11 @@ public class RootConfigurationAccessor { } public Sdk getProjectSdk(Project project) { - return ProjectRootManager.getInstance(project).getProjectJdk(); + return ProjectRootManager.getInstance(project).getProjectSdk(); } @Nullable public String getProjectSdkName(final Project project) { - return ProjectRootManager.getInstance(project).getProjectJdkName(); + return ProjectRootManager.getInstance(project).getProjectSdkName(); } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingIndexableSetContributor.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingIndexableSetContributor.java index 498dddbaf9b4..9dee15633338 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingIndexableSetContributor.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingIndexableSetContributor.java @@ -15,7 +15,6 @@ */ package com.intellij.openapi.roots.libraries.scripting; -import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; @@ -46,16 +45,15 @@ public abstract class ScriptingIndexableSetContributor extends IndexableSetContr final THashSet libFiles = new THashSet(); if (project != null) { ScriptingLibraryManager manager = new ScriptingLibraryManager(project); - LibraryTable libTable = manager.getLibraryTable(); + LibraryTable libTable = manager.getLibraryTable(true); if (libTable != null) { for (Library lib : libTable.getLibraries()) { - for (VirtualFile libFile : lib.getFiles(OrderRootType.CLASSES)) { + for (VirtualFile libFile : lib.getFiles(OrderRootType.SOURCES)) { libFile.putUserData(getIndexKey(), ""); libFiles.add(libFile); } } } - manager.disposeModel(); } return libFiles; } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingLibraryManager.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingLibraryManager.java index 44ca8818e72a..9351421de615 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingLibraryManager.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/scripting/ScriptingLibraryManager.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import org.jetbrains.annotations.Nullable; /** @@ -28,22 +29,36 @@ import org.jetbrains.annotations.Nullable; */ public class ScriptingLibraryManager { + public enum LibraryLevel {GLOBAL, PROJECT} + public static final String WEB_MODULE_TYPE = "WEB_MODULE"; private ModifiableRootModel myRootModel; private Project myProject; + private LibraryLevel myLibLevel = LibraryLevel.PROJECT; public ScriptingLibraryManager(Project project) { + this(LibraryLevel.GLOBAL, project); + } + + public ScriptingLibraryManager(LibraryLevel libLevel, Project project) { myProject = project; - myRootModel = getRootModel(project); + myLibLevel = libLevel; + myRootModel = getRootModel(libLevel, project); } @Nullable - private static ModifiableRootModel getRootModel(Project project) { - for (Module module : ModuleManager.getInstance(project).getModules()) { - if (WEB_MODULE_TYPE.equals(module.getModuleType().getId())) { - return ModuleRootManager.getInstance(module).getModifiableModel(); - } + private static ModifiableRootModel getRootModel(LibraryLevel libraryLevel, Project project) { + switch (libraryLevel) { + case PROJECT: + for (Module module : ModuleManager.getInstance(project).getModules()) { + if (WEB_MODULE_TYPE.equals(module.getModuleType().getId())) { + return ModuleRootManager.getInstance(module).getModifiableModel(); + } + } + break; + case GLOBAL: + return null; } return null; } @@ -56,6 +71,10 @@ public class ScriptingLibraryManager { } public void commitModel() { + if (myLibLevel == LibraryLevel.GLOBAL) { + ModuleManager.getInstance(myProject).getModifiableModel().commit(); + return; + } if (myRootModel != null && !myRootModel.isDisposed()) { myRootModel.commit(); resetModel(); @@ -64,15 +83,32 @@ public class ScriptingLibraryManager { public void resetModel() { disposeModel(); - myRootModel = getRootModel(myProject); + myRootModel = getRootModel(myLibLevel, myProject); + } + + @Nullable + public LibraryTable getLibraryTable(boolean readOnly) { + if (!readOnly && myLibLevel == LibraryLevel.PROJECT) { + return myRootModel != null ? myRootModel.getModuleLibraryTable() : null; + } + String libLevel = null; + switch (myLibLevel) { + case PROJECT: + libLevel = LibraryTablesRegistrar.PROJECT_LEVEL; + break; + case GLOBAL: + libLevel = LibraryTablesRegistrar.APPLICATION_LEVEL; + break; + } + if (libLevel != null) { + return LibraryTablesRegistrar.getInstance().getLibraryTableByLevel(libLevel, myProject); + } + return null; } @Nullable public LibraryTable getLibraryTable() { - if (myRootModel != null) { - return myRootModel.getModuleLibraryTable(); - } - return null; + return getLibraryTable(false); } public Project getProject() { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java index 4171a12890e4..d128170b3db3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ProjectSdksModel.java @@ -91,7 +91,7 @@ public class ProjectSdksModel implements SdkModel { //can't be } } - myProjectSdk = findSdk(ProjectRootManager.getInstance(project).getProjectJdkName()); + myProjectSdk = findSdk(ProjectRootManager.getInstance(project).getProjectSdkName()); myModified = false; myInitialized = true; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index 9a091aa904c2..50eff63789a8 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -523,6 +523,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec final FileViewProvider viewProvider = getCachedViewProvider(document); if (viewProvider == null) return; if (viewProvider.getVirtualFile().getFileType().isBinary()) return; + if (viewProvider.getManager() != myPsiManager) return; final List files = viewProvider.getAllFiles(); boolean commitNecessary = false; @@ -536,7 +537,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec } textBlock.documentChanged(event); - assert file instanceof PsiFileImpl : event + "; file="+file+"; allFiles="+files+"; viewProvider="+viewProvider; + assert file instanceof PsiFileImpl || "mock.file".equals(file.getName()) && ApplicationManager.getApplication().isUnitTestMode() : event + "; file="+file+"; allFiles="+files+"; viewProvider="+viewProvider; myUncommittedDocuments.add(document); commitNecessary = true; } @@ -568,6 +569,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec } char[] fileText = psiFile.textToCharArray(); + @SuppressWarnings({"NonConstantStringShouldBeStringBuffer"}) @NonNls String error = "File '" + psiFile.getName() + "' text mismatch after reparse. " + "File length=" + fileText.length + "; Doc length=" + documentLength + "\n"; int i = 0; diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDetectorAction.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDetectorAction.java index a587700673cf..99faade340d9 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDetectorAction.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureDetectorAction.java @@ -19,16 +19,22 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Iconable; import com.intellij.psi.PsiFile; +import com.intellij.util.Icons; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + /** * User: anna * Date: Sep 6, 2010 */ -public class ChangeSignatureDetectorAction implements IntentionAction { +public class ChangeSignatureDetectorAction implements IntentionAction, Iconable { private static final Logger LOG = Logger.getInstance("#" + ChangeSignatureDetectorAction.class.getName()); + @NonNls public static final String CHANGE_SIGNATURE = "Change signature ..."; @NotNull @Override @@ -56,4 +62,9 @@ public class ChangeSignatureDetectorAction implements IntentionAction { public boolean startInWriteAction() { return false; } + + @Override + public Icon getIcon(int flags) { + return Icons.ADVICE_ICON; + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java index ee1baf8aef08..ab0c7fa92cdb 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureDetector.java @@ -20,6 +20,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorBundle; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.actions.EditorActionUtil; @@ -50,11 +51,16 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme private final PsiDocumentManager myPsiDocumentManager; private final PsiManager myPsiManager; private final FileEditorManager myFileEditorManager; + private final Project myProject; - public ChangeSignatureGestureDetector(final PsiDocumentManager psiDocumentManager, final PsiManager psiManager, final FileEditorManager fileEditorManager) { + public ChangeSignatureGestureDetector(final PsiDocumentManager psiDocumentManager, + final PsiManager psiManager, + final FileEditorManager fileEditorManager, + final Project project) { myPsiDocumentManager = psiDocumentManager; myPsiManager = psiManager; myFileEditorManager = fileEditorManager; + myProject = project; } public static ChangeSignatureGestureDetector getInstance(Project project){ @@ -100,11 +106,11 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme public void projectOpened() { myPsiManager.addPsiTreeChangeListener(this); EditorFactory.getInstance().addEditorFactoryListener(this); - Disposer.register(myPsiManager.getProject(), new Disposable() { + Disposer.register(myProject, new Disposable() { public void dispose() { myPsiManager.removePsiTreeChangeListener(ChangeSignatureGestureDetector.this); EditorFactory.getInstance().removeEditorFactoryListener(ChangeSignatureGestureDetector.this); - myListenerMap.clear(); + LOG.assertTrue(myListenerMap.isEmpty(), myListenerMap); } }); } @@ -163,12 +169,14 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme @Override public void editorCreated(EditorFactoryEvent event) { - addDocListener(event.getEditor().getDocument()); + final Editor editor = event.getEditor(); + if (editor.getProject() != myProject) return; + addDocListener(editor.getDocument()); } public void addDocListener(Document document) { final PsiFile file = myPsiDocumentManager.getPsiFile(document); - if (file != null && !myListenerMap.containsKey(file)) { + if (file != null && file.isPhysical() && !myListenerMap.containsKey(file)) { final MyDocumentChangeAdapter adapter = new MyDocumentChangeAdapter(); document.addDocumentListener(adapter); myListenerMap.put(file, adapter); @@ -182,7 +190,7 @@ public class ChangeSignatureGestureDetector extends PsiTreeChangeAdapter impleme public void removeDocListener(Document document) { final PsiFile file = myPsiDocumentManager.getPsiFile(document); - if (file != null) { + if (file != null && file.isPhysical()) { if (ArrayUtil.find(myFileEditorManager.getOpenFiles(), file.getVirtualFile()) != -1) { return; } diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureVisitor.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureVisitor.java index ca323c924b16..40bfd2fae9d0 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureVisitor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureGestureVisitor.java @@ -19,17 +19,22 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.HighlightVisitor; import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder; -import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction; import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.markup.EffectType; +import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.util.Icons; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.awt.*; /** @@ -42,11 +47,11 @@ public class ChangeSignatureGestureVisitor implements HighlightVisitor { @Override public boolean suitableForFile(PsiFile file) { - return file != null && ApplicationManagerEx.getApplicationEx().isInternal() && LanguageChangeSignatureDetectors.isSuitableForLanguage(file.getLanguage()); + return file != null && LanguageChangeSignatureDetectors.isSuitableForLanguage(file.getLanguage()); } @Override - public void visit(PsiElement element, HighlightInfoHolder holder) { + public void visit(final PsiElement element, HighlightInfoHolder holder) { final ChangeSignatureGestureDetector detector = ChangeSignatureGestureDetector.getInstance(element.getProject()); if (detector.isChangeSignatureAvailable(element)) { final TextRange range = LanguageChangeSignatureDetectors.getHighlightingRange(element); @@ -58,7 +63,8 @@ public class ChangeSignatureGestureVisitor implements HighlightVisitor { HighlightInfoType.INFORMATION, range.getStartOffset(), range.getEndOffset(), SIGNATURE_SHOULD_BE_POSSIBLY_CHANGED, SIGNATURE_SHOULD_BE_POSSIBLY_CHANGED, HighlightSeverity.INFORMATION, false, true, false); - QuickFixAction.registerQuickFixAction(info, new ChangeSignatureDetectorAction()); + final ChangeSignatureDetectorAction action = new ChangeSignatureDetectorAction(); + info.setGutterIconRenderer(new MyGutterIconRenderer(action, element)); holder.add(info); } } @@ -79,5 +85,45 @@ public class ChangeSignatureGestureVisitor implements HighlightVisitor { return 10; } + private static class MyGutterIconRenderer extends GutterIconRenderer { + private final ChangeSignatureDetectorAction myAction; + private final PsiElement myElement; + public MyGutterIconRenderer(ChangeSignatureDetectorAction action, PsiElement element) { + myAction = action; + myElement = element; + } + + @NotNull + @Override + public Icon getIcon() { + return Icons.ADVICE_ICON; + } + + @Override + public AnAction getClickAction() { + return new AnAction() { + @Override + public void actionPerformed(AnActionEvent e) { + myAction.invoke(myElement.getProject(), null, myElement.getContainingFile()); + } + }; + } + + @Override + public String getTooltipText() { + return ChangeSignatureDetectorAction.CHANGE_SIGNATURE; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof MyGutterIconRenderer)) return false; + return true; + } + + @Override + public int hashCode() { + return 0; + } + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java index 5250c26ab0ba..638a5afeef84 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenameHandler.java @@ -97,17 +97,8 @@ public class VariableInplaceRenameHandler implements RenameHandler { @Nullable public VariableInplaceRenamer doRename(final PsiElement elementToRename, final Editor editor, final DataContext dataContext) { - return doRename(elementToRename, editor, dataContext, true); - } - - @Nullable - public VariableInplaceRenamer doRename(final PsiElement elementToRename, - final Editor editor, - final DataContext dataContext, - boolean processTextOccurrences) { - VariableInplaceRenamer renamer = createRenamer(elementToRename, editor); - boolean startedRename = renamer == null ? false : renamer.performInplaceRename(processTextOccurrences); + boolean startedRename = renamer == null ? false : renamer.performInplaceRename(); if (!startedRename) { try { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index 77202526d40c..da7a487eddb9 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -94,10 +94,10 @@ public class VariableInplaceRenamer { } public boolean performInplaceRename() { - return performInplaceRename(true); + return performInplaceRename(true, null); } - public boolean performInplaceRename(boolean processTextOccurrences) { + public boolean performInplaceRename(boolean processTextOccurrences, LinkedHashSet nameSuggestions) { if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(myElementToRename)) { return false; } @@ -170,9 +170,9 @@ public class VariableInplaceRenamer { PsiElement selectedElement = getSelectedInEditorElement(nameIdentifier, refs, offset); if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, myElementToRename)) return true; - if (nameIdentifier != null) addVariable(nameIdentifier, selectedElement, builder); + if (nameIdentifier != null) addVariable(nameIdentifier, selectedElement, builder, nameSuggestions); for (PsiReference ref : refs) { - addVariable(ref, selectedElement, builder, offset); + addVariable(ref, selectedElement, builder, offset, nameSuggestions); } final PsiElement scope1 = scope; @@ -391,10 +391,14 @@ public class VariableInplaceRenamer { return range.getStartOffset() <= offset && offset <= range.getEndOffset(); } - private void addVariable(final PsiReference reference, final PsiElement selectedElement, final TemplateBuilderImpl builder, int offset) { + private void addVariable(final PsiReference reference, + final PsiElement selectedElement, + final TemplateBuilderImpl builder, + int offset, + final LinkedHashSet names) { if (reference.getElement() == selectedElement && contains(reference.getRangeInElement().shiftRight(selectedElement.getTextRange().getStartOffset()), offset)) { - Expression expression = new MyExpression(myElementToRename.getName()); + Expression expression = new MyExpression(myElementToRename.getName(), names); builder.replaceElement(reference, PRIMARY_VARIABLE_NAME, expression, true); } else { @@ -402,9 +406,12 @@ public class VariableInplaceRenamer { } } - private void addVariable(final PsiElement element, final PsiElement selectedElement, final TemplateBuilderImpl builder) { + private void addVariable(final PsiElement element, + final PsiElement selectedElement, + final TemplateBuilderImpl builder, + final LinkedHashSet names) { if (element == selectedElement) { - Expression expression = new MyExpression(myElementToRename.getName()); + Expression expression = new MyExpression(myElementToRename.getName(), names); builder.replaceElement(element, PRIMARY_VARIABLE_NAME, expression, true); } else { @@ -416,11 +423,13 @@ public class VariableInplaceRenamer { private final String myName; private final LookupElement[] myLookupItems; - private MyExpression(String name) { + private MyExpression(String name, LinkedHashSet names) { myName = name; - Set names = new HashSet(); - for(NameSuggestionProvider provider: Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) { - provider.getSuggestedNames(myElementToRename, myElementToRename, names); + if (names == null) { + names = new LinkedHashSet(); + for(NameSuggestionProvider provider: Extensions.getExtensions(NameSuggestionProvider.EP_NAME)) { + provider.getSuggestedNames(myElementToRename, myElementToRename, names); + } } myLookupItems = new LookupElement[names.size()]; final Iterator iterator = names.iterator(); diff --git a/platform/platform-api/src/com/intellij/openapi/diagnostic/ErrorReportSubmitter.java b/platform/platform-api/src/com/intellij/openapi/diagnostic/ErrorReportSubmitter.java index 520abaa99634..9c6b45a6833e 100644 --- a/platform/platform-api/src/com/intellij/openapi/diagnostic/ErrorReportSubmitter.java +++ b/platform/platform-api/src/com/intellij/openapi/diagnostic/ErrorReportSubmitter.java @@ -17,6 +17,7 @@ package com.intellij.openapi.diagnostic; import com.intellij.openapi.extensions.PluginAware; import com.intellij.openapi.extensions.PluginDescriptor; +import com.intellij.util.Consumer; import java.awt.*; @@ -57,4 +58,8 @@ public abstract class ErrorReportSubmitter implements PluginAware { * @return submission result status. */ public abstract SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent); + + public void submitAsync(IdeaLoggingEvent[] events, Component parentComponent, Consumer consumer) { + consumer.consume(submit(events, parentComponent)); + } } diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java index 4a6b17238756..4cf4e129f6ab 100644 --- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java +++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java @@ -175,8 +175,8 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith TreePath[] paths = getSelectionModel().getSelectionPaths(); if (paths != null) { for (TreePath each : paths) { - Rectangle selection = getPathBounds(each); - if (g.getClipBounds().intersects(selection) || g.getClipBounds().contains(selection)) { + final Rectangle selection = getPathBounds(each); + if (selection != null && (g.getClipBounds().intersects(selection) || g.getClipBounds().contains(selection))) { if (myBusy) { Rectangle busyIconBounds = myBusyIcon.getBounds(); if (selection.contains(busyIconBounds) || selection.intersects(busyIconBounds)) { diff --git a/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java b/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java index eb561e47b29d..50de1d415489 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java @@ -23,6 +23,7 @@ import java.util.Date; public abstract class AbstractMessage { private boolean myIsRead = false; + private boolean myIsSubmitting = false; private SubmittedReportInfo mySubmissionInfo; private String myScrID; @@ -52,6 +53,14 @@ public abstract class AbstractMessage { return mySubmissionInfo; } + public boolean isSubmitting() { + return myIsSubmitting; + } + + public void setSubmitting(boolean isSubmitting) { + myIsSubmitting = isSubmitting; + } + public boolean isSubmitted() { return mySubmissionInfo != null && (mySubmissionInfo.getStatus() == SubmittedReportInfo.SubmissionStatus.NEW_ISSUE || diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java index 1a4ad75788ed..b41d02c1397e 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java @@ -23,6 +23,9 @@ import com.intellij.errorreport.error.NoSuchEAPUserException; import com.intellij.ide.DataManager; import com.intellij.ide.plugins.IdeaPluginDescriptor; import com.intellij.idea.IdeaLogger; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; @@ -32,12 +35,10 @@ import com.intellij.openapi.diagnostic.SubmittedReportInfo; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.util.net.IOExceptionDialog; +import com.intellij.util.Consumer; import org.jetbrains.annotations.NonNls; -import javax.swing.*; import java.awt.*; -import java.io.IOException; /** * @author max @@ -52,98 +53,110 @@ public class ITNReporter extends ErrorReportSubmitter { } public SubmittedReportInfo submit(IdeaLoggingEvent[] events, Component parentComponent) { - return sendError(events[0], parentComponent); + // obsolete API + return new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED); + } + + @Override + public void submitAsync(IdeaLoggingEvent[] events, Component parentComponent, Consumer consumer) { + sendError(events [0], parentComponent, consumer); } /** * @noinspection ThrowablePrintStackTrace */ - private static SubmittedReportInfo sendError(IdeaLoggingEvent event, Component parentComponent) { + private static void sendError(IdeaLoggingEvent event, final Component parentComponent, final Consumer callback) { String newBuild = ErrorReportSender.checkNewBuild(); if (newBuild != null) { Messages.showMessageDialog(parentComponent, DiagnosticBundle.message("error.report.new.eap.build.message", newBuild), CommonBundle.getWarningTitle(), Messages.getWarningIcon()); - return new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED); + callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED)); } ErrorBean errorBean = new ErrorBean(event.getThrowable(), IdeaLogger.ourLastActionId); - int threadId = 0; - SubmittedReportInfo.SubmissionStatus submissionStatus = SubmittedReportInfo.SubmissionStatus.FAILED; + String description = ""; + doSubmit(event, parentComponent, callback, errorBean, description); + } + + private static void doSubmit(final IdeaLoggingEvent event, + final Component parentComponent, + final Consumer callback, + final ErrorBean errorBean, final String description) { final DataContext dataContext = DataManager.getInstance().getDataContext(parentComponent); Project project = PlatformDataKeys.PROJECT.getData(dataContext); - String description = ""; - do { - // prepare - try { - EAPSendErrorDialog dlg = new EAPSendErrorDialog(); - dlg.setErrorDescription(description); - dlg.show(); - - @NonNls String login = ErrorReportConfigurable.getInstance().ITN_LOGIN; - @NonNls String password = ErrorReportConfigurable.getInstance().getPlainItnPassword(); - if (login.trim().length() == 0 && password.trim().length() == 0) { - login = "idea_anonymous"; - password = "guest"; - } - - description = dlg.getErrorDescription(); - @NonNls StringBuilder descBuilder = buildDescription(event, description); - errorBean.setDescription(descBuilder.toString()); - - if (dlg.isShouldSend()) { - threadId = ErrorReportSender.sendError(project, login, password, errorBean); - previousExceptionThreadId = threadId; - wasException = true; - submissionStatus = SubmittedReportInfo.SubmissionStatus.NEW_ISSUE; - - Messages.showInfoMessage(parentComponent, - DiagnosticBundle.message("error.report.confirmation"), - ReportMessages.ERROR_REPORT); - break; - } - else { - break; - } - - } - catch (NoSuchEAPUserException e) { - if (Messages.showYesNoDialog(parentComponent, DiagnosticBundle.message("error.report.authentication.failed"), - ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) { - break; - } - } - catch (InternalEAPException e) { - if (Messages.showYesNoDialog(parentComponent, DiagnosticBundle.message("error.report.posting.failed", e.getMessage()), - ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) { - break; - } - } - catch (IOException e) { - if (!IOExceptionDialog.showErrorDialog(DiagnosticBundle.message("error.report.exception.title"), - DiagnosticBundle.message("error.report.failure.message"))) { - break; - } - } - catch (Exception e) { - if (Messages.showYesNoDialog(JOptionPane.getRootFrame(), DiagnosticBundle.message("error.report.sending.failure"), - ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) { - break; - } - } - + final EAPSendErrorDialog dlg = new EAPSendErrorDialog(); + dlg.setErrorDescription(description); + dlg.show(); + if (!dlg.isShouldSend()) { + return; } - while (true); - return new SubmittedReportInfo(submissionStatus != SubmittedReportInfo.SubmissionStatus.FAILED ? URL_HEADER + threadId : null, - String.valueOf(threadId), - submissionStatus); + @NonNls String login = ErrorReportConfigurable.getInstance().ITN_LOGIN; + @NonNls String password = ErrorReportConfigurable.getInstance().getPlainItnPassword(); + if (login.trim().length() == 0 && password.trim().length() == 0) { + login = "idea_anonymous"; + password = "guest"; + } + + errorBean.setDescription(buildDescription(event, dlg.getErrorDescription())); + + ErrorReportSender.sendError(project, login, password, errorBean, new Consumer() { + @SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod"}) + @Override + public void consume(Integer threadId) { + previousExceptionThreadId = threadId; + wasException = true; + callback.consume(new SubmittedReportInfo(URL_HEADER + threadId, String.valueOf(threadId), + SubmittedReportInfo.SubmissionStatus.NEW_ISSUE)); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + Notification notification = new Notification(ReportMessages.ERROR_REPORT, ReportMessages.ERROR_REPORT, + DiagnosticBundle.message("error.report.confirmation"), + NotificationType.INFORMATION); + Notifications.Bus.notify(notification); + } + }); + } + }, new Consumer() { + @Override + public void consume(final Exception e) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + String msg; + if (e instanceof NoSuchEAPUserException) { + msg = DiagnosticBundle.message("error.report.authentication.failed"); + } + else if (e instanceof InternalEAPException) { + msg = DiagnosticBundle.message("error.report.posting.failed", e.getMessage()); + } + else { + msg = DiagnosticBundle.message("error.report.sending.failure"); + } + if (Messages.showYesNoDialog(parentComponent, msg, + ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) { + callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED)); + } + else { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + doSubmit(event, parentComponent, callback, errorBean, dlg.getErrorDescription()); + } + }); + } + } + }); + } + }); } - private static StringBuilder buildDescription(IdeaLoggingEvent event, String description) { + private static String buildDescription(IdeaLoggingEvent event, String description) { String message = event.getMessage(); @NonNls StringBuilder descBuilder = new StringBuilder(); @@ -171,6 +184,6 @@ public class ITNReporter extends ErrorReportSubmitter { if (wasException) { descBuilder.append("There was at least one exception before this one.\n"); } - return descBuilder; + return descBuilder.toString(); } } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java index 63edca149149..2eeed8dc10d5 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java @@ -48,6 +48,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.util.Consumer; import com.intellij.util.text.DateFormatUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -182,11 +183,11 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene if (message.isSubmitted()) { final SubmittedReportInfo info = message.getSubmissionInfo(); if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.FAILED) { - txt.append(DiagnosticBundle.message("error.list.message.submission.failed")); + txt.append(" ").append(DiagnosticBundle.message("error.list.message.submission.failed")); } else { if (info.getLinkText() != null) { - txt.append(DiagnosticBundle.message("error.list.message.submitted.as.link", info.getLinkText())); + txt.append(" ").append(DiagnosticBundle.message("error.list.message.submitted.as.link", info.getLinkText())); if (info.getStatus() == SubmittedReportInfo.SubmissionStatus.DUPLICATE) { txt.append(DiagnosticBundle.message("error.list.message.duplicate")); } @@ -197,6 +198,9 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene } txt.append(". "); } + else if (message.isSubmitting()) { + txt.append(" Submitting..."); + } else if (!message.isRead()) { txt.append(" ").append(DiagnosticBundle.message("error.list.message.unread")); } @@ -445,14 +449,20 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene private class ShutdownAction extends AbstractAction { public ShutdownAction() { - super(DiagnosticBundle.message("error.list.shutdown.action")); + super(ApplicationManager.getApplication().isRestartCapable() ? "Restart" : DiagnosticBundle.message("error.list.shutdown.action")); } public void actionPerformed(ActionEvent e) { myMessagePool.setJvmIsShuttingDown(); LaterInvocator.invokeLater(new Runnable() { public void run() { - ApplicationManager.getApplication().exit(); + final Application app = ApplicationManager.getApplication(); + if (app.isRestartCapable()) { + app.restart(); + } + else { + app.exit(); + } } }, ModalityState.NON_MODAL); doOKAction(); @@ -502,7 +512,21 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene ErrorReportSubmitter submitter = getSubmitter(logMessage.getThrowable()); if (submitter != null) { - logMessage.setSubmitted(submitter.submit(getEvents(logMessage), getContentPane())); + logMessage.setSubmitting(true); + updateControls(); + submitter.submitAsync(getEvents(logMessage), getContentPane(), new Consumer() { + @Override + public void consume(SubmittedReportInfo submittedReportInfo) { + logMessage.setSubmitting(false); + logMessage.setSubmitted(submittedReportInfo); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + updateControls(); + } + }); + } + }); } } diff --git a/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java b/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java index 5ab173712b8e..333ff16c9567 100644 --- a/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java +++ b/platform/platform-impl/src/com/intellij/errorreport/ErrorReportSender.java @@ -17,24 +17,24 @@ package com.intellij.errorreport; import com.intellij.diagnostic.DiagnosticBundle; import com.intellij.errorreport.bean.ErrorBean; -import com.intellij.errorreport.error.InternalEAPException; -import com.intellij.errorreport.error.NoSuchEAPUserException; import com.intellij.errorreport.itn.ITNProxy; import com.intellij.ide.reporter.ConnectionException; import com.intellij.idea.IdeaLogger; +import com.intellij.openapi.progress.EmptyProgressIndicator; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.updateSettings.impl.BuildInfo; import com.intellij.openapi.updateSettings.impl.UpdateChannel; import com.intellij.openapi.updateSettings.impl.UpdateChecker; -import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Consumer; import com.intellij.util.net.HttpConfigurable; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.IOException; - /** * Created by IntelliJ IDEA. * User: stathik @@ -44,7 +44,9 @@ import java.io.IOException; */ public class ErrorReportSender { @NonNls public static final String PREPARE_URL = "http://www.intellij.net/"; - //public static String REPORT_URL = "http://unit-038:8080/error/report?sender=i"; + + private ErrorReportSender() { + } @Nullable public static String checkNewBuild() { @@ -64,74 +66,51 @@ public class ErrorReportSender { private String myLogin; private String myPassword; private ErrorBean errorBean; - private int myThreadId; public SendTask(final Project project, ErrorBean errorBean) { myProject = project; this.errorBean = errorBean; } - public int getThreadId () { - return myThreadId; - } - public void setCredentials(String login, String password) { myLogin = login; myPassword = password; } - public void sendReport() throws Exception { - final Ref err = new Ref(); - Runnable runnable = new Runnable() { - public void run() { + public void sendReport(final Consumer callback, final Consumer errback) { + Task.Backgroundable task = new Task.Backgroundable(myProject, DiagnosticBundle.message("title.submitting.error.report")) { + @Override + public void run(@NotNull ProgressIndicator indicator) { try { HttpConfigurable.getInstance().prepareURL(PREPARE_URL); if (!StringUtil.isEmpty(myLogin)) { - myThreadId = ITNProxy.postNewThread( + int threadId = ITNProxy.postNewThread( myLogin, myPassword, errorBean, IdeaLogger.getOurCompilationTimestamp()); + callback.consume(threadId); } } catch (Exception ex) { - err.set(ex); + errback.consume(ex); } } }; if (myProject == null) { - runnable.run(); + task.run(new EmptyProgressIndicator()); } else { - ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, - DiagnosticBundle.message("title.submitting.error.report"), - false, myProject); - } - if (!err.isNull()) { - throw err.get(); + ProgressManager.getInstance().run(task); } } } - public static int sendError(Project project, String login, String password, ErrorBean error) - throws IOException, NoSuchEAPUserException, InternalEAPException { - + public static void sendError(Project project, String login, String password, ErrorBean error, + Consumer callback, Consumer errback) { SendTask sendTask = new SendTask (project, error); sendTask.setCredentials(login, password); - - try { - sendTask.sendReport(); - return sendTask.getThreadId(); - } catch (IOException e) { - throw e; - } catch (NoSuchEAPUserException e) { - throw e; - } catch (InternalEAPException e) { - throw e; - } catch (Throwable e) { - e.printStackTrace(); - throw new RuntimeException(e); - } + sendTask.sendReport(callback, errback); } } diff --git a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsPanel.form b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsPanel.form index 0b847b8ab594..85e7ae2e640b 100644 --- a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsPanel.form +++ b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsPanel.form @@ -51,7 +51,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java index 794838e465a2..a4c7519bd154 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/RevealFileAction.java @@ -31,7 +31,7 @@ public class RevealFileAction extends AnAction { if (file != null && file.isInLocalFileSystem()) { if (SystemInfo.isMac) { - e.getPresentation().setText("Reveal in Finder"); + e.getPresentation().setText("Show in Finder"); } else { e.getPresentation().setText("Show in Explorer"); } diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectNewWindowDoNotAskOption.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectNewWindowDoNotAskOption.java new file mode 100644 index 000000000000..dd0aebc01590 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectNewWindowDoNotAskOption.java @@ -0,0 +1,42 @@ +/* + * 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.ide.impl; + +import com.intellij.CommonBundle; +import com.intellij.ide.GeneralSettings; +import com.intellij.openapi.ui.DialogWrapper; + +public class ProjectNewWindowDoNotAskOption implements DialogWrapper.DoNotAskOption { + public boolean isToBeShown() { + return true; + } + + public void setToBeShown(boolean value, int exitCode) { + GeneralSettings.getInstance().setConfirmOpenNewProject(value || exitCode == 2 ? -1 : exitCode); + } + + public boolean canBeHidden() { + return true; + } + + public boolean shouldSaveOptionsOnCancel() { + return false; + } + + public String getDoNotShowMessage() { + return CommonBundle.message("dialog.options.do.not.ask"); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index c7c32794d651..7862a170ffa7 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -29,7 +29,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.project.ex.ProjectManagerEx; -import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Disposer; @@ -151,35 +150,7 @@ public class ProjectUtil { } if (!forceOpenInNewFrame && openProjects.length > 0) { - final GeneralSettings settings = GeneralSettings.getInstance(); - int exitCode; - if (settings.getConfirmOpenNewProject() < 0) { - exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), - new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), - CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon(), new DialogWrapper.DoNotAskOption() { - public boolean isToBeShown() { - return true; - } - - public void setToBeShown(boolean value, int exitCode) { - settings.setConfirmOpenNewProject(value || exitCode == 2 ? -1 : exitCode); - } - - public boolean canBeHidden() { - return true; - } - - public boolean shouldSaveOptionsOnCancel() { - return false; - } - - public String getDoNotShowMessage() { - return CommonBundle.message("dialog.options.do.not.ask"); - } - }); - } else { - exitCode = settings.getConfirmOpenNewProject(); - } + int exitCode = confirmOpenNewProject(); if (exitCode == 1) { // "No" option if (!closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null; } @@ -210,6 +181,18 @@ public class ProjectUtil { return project; } + public static int confirmOpenNewProject() { + final GeneralSettings settings = GeneralSettings.getInstance(); + if (settings.getConfirmOpenNewProject() < 0) { + return Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), + new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), + CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon(), + new ProjectNewWindowDoNotAskOption()); + } else { + return settings.getConfirmOpenNewProject(); + } + } + private static boolean isSameProject(String path, Project p) { final IProjectStore projectStore = ((ProjectEx)p).getStateStore(); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form index 8b17306affa1..2d864aa94279 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form +++ b/platform/platform-impl/src/com/intellij/ide/ui/AppearancePanel.form @@ -3,7 +3,7 @@ - + @@ -260,6 +260,7 @@ + diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java b/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java index 14fce215abec..2e99de9e1a55 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java @@ -183,8 +183,7 @@ public class TipPanel extends JPanel { myTipPaths.add(element.getAttributeValue(ATTRIBUTE_FILE)); } final ProductivityFeaturesProvider[] providers = ApplicationManager.getApplication().getComponents(ProductivityFeaturesProvider.class); - for (int i = 0; i < providers.length; i++) { - ProductivityFeaturesProvider provider = providers[i]; + for (ProductivityFeaturesProvider provider : providers) { final FeatureDescriptor[] featureDescriptors = provider.getFeatureDescriptors(); for (int j = 0; featureDescriptors != null && j < featureDescriptors.length; j++) { FeatureDescriptor featureDescriptor = featureDescriptors[j]; @@ -192,13 +191,4 @@ public class TipPanel extends JPanel { } } } - - public void initComponent() { - - } - - public void disposeComponent() { - - } - } diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java index 04a88241f66b..da9032e072fe 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java @@ -18,6 +18,7 @@ package com.intellij.ide.util; import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.application.ApplicationInfo; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.keymap.KeymapManager; import com.intellij.openapi.keymap.KeymapUtil; @@ -62,6 +63,7 @@ public class TipUIUtil { StringBuffer text = new StringBuffer(ResourceUtil.loadText(url)); updateShortcuts(text); String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName()); + replaced = replaced.replace("&majorVersion;", ApplicationInfo.getInstance().getMajorVersion()); browser.read(new StringReader(replaced), null); final Document document = browser.getDocument(); if (document instanceof HTMLDocument) { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java index 46f9046ef782..dd0138cbd068 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java @@ -27,6 +27,7 @@ package com.intellij.openapi.application.ex; import com.intellij.openapi.application.ApplicationInfo; import java.awt.*; +import java.util.Calendar; import java.util.List; public abstract class ApplicationInfoEx extends ApplicationInfo { @@ -35,6 +36,8 @@ public abstract class ApplicationInfoEx extends ApplicationInfo { return (ApplicationInfoEx) getInstance(); } + public abstract Calendar getMajorReleaseBuildDate(); + public abstract String getLogoUrl(); public abstract Color getLogoTextColor(); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java index 019003a1259d..bc33d0767684 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java @@ -51,6 +51,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern @NonNls private String myOpaqueIconUrl = "/icon.png"; @NonNls private String myToolWindowIconUrl = "/general/toolWindowProject.png"; private Calendar myBuildDate = null; + private Calendar myMajorReleaseBuildDate = null; private String myPackageCode = null; private boolean myShowLicensee = true; private String myWelcomeScreenCaptionUrl; @@ -81,6 +82,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern @NonNls private static final String ELEMENT_BUILD = "build"; @NonNls private static final String ATTRIBUTE_NUMBER = "number"; @NonNls private static final String ATTRIBUTE_DATE = "date"; + @NonNls private static final String ATTRIBUTE_MAJOR_RELEASE_DATE = "majorReleaseDate"; @NonNls private static final String ELEMENT_LOGO = "logo"; @NonNls private static final String ATTRIBUTE_URL = "url"; @NonNls private static final String ATTRIBUTE_TEXTCOLOR = "textcolor"; @@ -128,6 +130,10 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern return myBuildDate; } + public Calendar getMajorReleaseBuildDate() { + return myMajorReleaseBuildDate != null ? myMajorReleaseBuildDate : myBuildDate; + } + @Override public BuildNumber getBuild() { return BuildNumber.fromString(myBuildNumber); @@ -314,21 +320,11 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern myBuildDate = new GregorianCalendar(); } else { - int year = 0; - int month = 0; - int day = 0; - try { - year = Integer.parseInt(dateString.substring(0, 4)); - month = Integer.parseInt(dateString.substring(4, 6)); - day = Integer.parseInt(dateString.substring(6, 8)); - } - catch (Exception ex) { - //ignore - } - if (month > 0) { - month--; - } - myBuildDate = new GregorianCalendar(year, month, day); + myBuildDate = parseDate(dateString); + } + String majorReleaseDateString = buildElement.getAttributeValue(ATTRIBUTE_MAJOR_RELEASE_DATE); + if (majorReleaseDateString != null) { + myMajorReleaseBuildDate = parseDate(majorReleaseDateString); } } @@ -446,6 +442,24 @@ public class ApplicationInfoImpl extends ApplicationInfoEx implements JDOMExtern } } + private static GregorianCalendar parseDate(String dateString) { + int year = 0; + int month = 0; + int day = 0; + try { + year = Integer.parseInt(dateString.substring(0, 4)); + month = Integer.parseInt(dateString.substring(4, 6)); + day = Integer.parseInt(dateString.substring(6, 8)); + } + catch (Exception ex) { + //ignore + } + if (month > 0) { + month--; + } + return new GregorianCalendar(year, month, day); + } + public List getPluginChooserPages() { return myPluginChooserPages; } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java index 185198aa17ee..9c3b94b20c0b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java @@ -45,8 +45,8 @@ public class DeleteLineAction extends TextComponentEditorAction { int selectionEnd = selectionModel.getSelectionEnd(); selectionModel.removeSelection(); int lineStartOffset = document.getLineStartOffset(document.getLineNumber(selectionStart)); - int lineEndOffset = document.getLineEndOffset(document.getLineNumber(selectionEnd)); - document.deleteString(lineStartOffset, lineEndOffset); + int nextLineStartOffset = Math.min(document.getTextLength(), document.getLineStartOffset(document.getLineNumber(selectionEnd) + 1)); + document.deleteString(lineStartOffset, nextLineStartOffset); return; } deleteLineAtCaret(editor); diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java index 1df82f9e8eb0..4d928f5e2d4f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java @@ -24,10 +24,7 @@ import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DocumentRunnable; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringHash; import com.intellij.openapi.util.text.StringUtil; @@ -330,16 +327,27 @@ public class SchemesManagerImpl() { + @Override + public VirtualFile compute() { + VirtualFile file = myVFSBaseDir.findChild(fileName); + try { + if (file == null) file = myVFSBaseDir.createChildData(SchemesManagerImpl.this, fileName); + if (!Arrays.equals(file.contentsToByteArray(), text)) { + file.setBinaryContent(text); + } + } + catch (IOException e) { + ex[0] = e; + } - } - if (!Arrays.equals(file.contentsToByteArray(), text)) { - file.setBinaryContent(text); - } + return file; + } + }); - return file; + if (ex[0] != null) throw ex[0]; + return _file; } private String checkFileNameIsFree(final String subpath, final String schemeName) { diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java index a6f1f8b533fc..682e73f64b0e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsEditor.java @@ -319,7 +319,11 @@ public class OptionsEditor extends JPanel implements DataProvider, Place.Navigat checkModified(oldConfigurable); checkModified(configurable); - result.setDone(); + if (myTree.myBuilder.getSelectedElements().size() == 0) { + select(configurable.getClass()).notify(result); + } else { + result.setDone(); + } } }); } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java index 7f6c662dde0a..5b015306d0d5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/newEditor/OptionsTree.java @@ -181,21 +181,26 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl myContext.fireSelected(null, OptionsTree.this); } else { - final EditorNode editorNode = myConfigurable2Node.get(configurable); - FilteringTreeStructure.Node editorUiNode = myBuilder.getVisibleNodeFor(editorNode); - if (!myBuilder.getSelectedElements().contains(editorUiNode)) { - myBuilder.select(editorUiNode, new Runnable() { - public void run() { - fireSelected(configurable, callback); + myBuilder.getReady(this).doWhenDone(new Runnable() { + @Override + public void run() { + final EditorNode editorNode = myConfigurable2Node.get(configurable); + FilteringTreeStructure.Node editorUiNode = myBuilder.getVisibleNodeFor(editorNode); + if (!myBuilder.getSelectedElements().contains(editorUiNode)) { + myBuilder.select(editorUiNode, new Runnable() { + public void run() { + fireSelected(configurable, callback); + } + }); + } else { + myBuilder.scrollSelectionToVisible(new Runnable() { + public void run() { + fireSelected(configurable, callback); + } + }, false); } - }); - } else { - myBuilder.scrollSelectionToVisible(new Runnable() { - public void run() { - fireSelected(configurable, callback); - } - }, false); - } + } + }); } } @@ -747,6 +752,11 @@ public class OptionsTree extends JPanel implements Disposable, OptionsEditorColl return myContext.isHoldingFilter(); } + @Override + public boolean isToEnsureSelectionOnFocusGained() { + return false; + } + @Override protected ActionCallback refilterNow(Object preferredSelection, boolean adjustSelection) { final List toRestore = new ArrayList(); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 5eb0d324fac8..7c0201e3a10c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -214,7 +214,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt try { ProjectImpl project = - createAndInitProject(projectName, filePath, false, isDummy, ApplicationManager.getApplication().isUnitTestMode(), + createAndInitProject(projectName, filePath, false, ApplicationManager.getApplication().isUnitTestMode(), useDefaultProjectSettings ? getDefaultProject() : null); if (LOG_PROJECT_LEAKAGE_IN_TESTS) { myProjects.put(project, null); @@ -244,11 +244,8 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt return message; } - private ProjectImpl createAndInitProject(String projectName, String filePath, boolean isDefault, boolean isDummy, boolean isOptimiseTestLoadSpeed, + private ProjectImpl createAndInitProject(String projectName, String filePath, boolean isDefault, boolean isOptimiseTestLoadSpeed, @Nullable Project template) throws IOException { - if (isDummy) { - throw new UnsupportedOperationException("Dummy project is deprecated and shall not be used anymore."); - } final ProjectImpl project = isDefault ? new DefaultProject(this, filePath, isOptimiseTestLoadSpeed, projectName) : new ProjectImpl(this, filePath, isOptimiseTestLoadSpeed, projectName); @@ -299,7 +296,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt filePath = canonicalize(filePath); ProjectImpl project = null; try { - project = createAndInitProject(null, filePath, false, false, false, null); + project = createAndInitProject(null, filePath, false, false, null); } catch (ProcessCanceledException e) { if (project != null) { @@ -332,7 +329,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt public synchronized Project getDefaultProject() { if (myDefaultProject == null) { try { - myDefaultProject = createAndInitProject(null, null, true, false, ApplicationManager.getApplication().isUnitTestMode(), null); + myDefaultProject = createAndInitProject(null, null, true, ApplicationManager.getApplication().isUnitTestMode(), null); myDefaultProjectRootElement = null; } catch (IOException e) { diff --git a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java index 196fd6b82105..7c2ef3ce2d20 100644 --- a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java +++ b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java @@ -15,8 +15,6 @@ */ package com.intellij.platform; -import com.intellij.CommonBundle; -import com.intellij.ide.IdeBundle; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; @@ -27,7 +25,6 @@ import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindowManager; @@ -76,9 +73,7 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor { Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (!forceOpenInNewFrame && openProjects.length > 0) { - int exitCode = Messages.showDialog(IdeBundle.message("prompt.open.project.in.new.frame"), IdeBundle.message("title.open.project"), - new String[]{IdeBundle.message("button.newframe"), IdeBundle.message("button.existingframe"), - CommonBundle.getCancelButtonText()}, 1, 0, Messages.getQuestionIcon()); + int exitCode = ProjectUtil.confirmOpenNewProject(); if (exitCode == 1) { // "No" option if (!ProjectUtil.closeProject(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null; } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java index 2ca398b2b819..f847483e1e7b 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java @@ -97,6 +97,8 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { invoke(chooser, "setCanChooseFiles:", myChooserDescriptor.isChooseFiles()); invoke(chooser, "setCanChooseDirectories:", myChooserDescriptor.isChooseFolders()); invoke(chooser, "setAllowsMultipleSelection:", myChooserDescriptor.isChooseMultiple()); + invoke(chooser, "setTreatsFilePackagesAsDirectories:", myChooserDescriptor.isChooseFolders()); + //invoke(chooser, "setCanCreateDirectories:", true); if (Foundation.isClassRespondsToSelector(Foundation.getClass("NSOpenPanel"), Foundation.createSelector("_setIncludeNewFolderButton:"))) { invoke(chooser, "_setIncludeNewFolderButton:", true); } @@ -108,10 +110,18 @@ public class MacFileChooserDialogImpl implements MacFileChooserDialog { invoke(chooser, "setDelegate:", self); + Object directory = null; + Object file = null; final String toSelectPath = toSelect.intValue() == 0 ? null : Foundation.toStringViaUTF8(toSelect); final VirtualFile toSelectFile = toSelectPath == null ? null : LocalFileSystem.getInstance().findFileByPath(toSelectPath); - final ID directory = toSelectFile == null ? null : toSelectFile.isDirectory() ? toSelect : null; - final ID file = toSelectFile == null ? null : !toSelectFile.isDirectory() ? toSelect : null; + if (toSelectFile != null) { + if (toSelectFile.isDirectory()) { + directory = toSelect; + } else { + directory = Foundation.cfString(toSelectFile.getParent().getPath()); + file = Foundation.cfString(toSelectFile.getName()); + } + } if (mySheetCallback != null) { final Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); diff --git a/platform/platform-resources-en/src/messages/LangBundle.properties b/platform/platform-resources-en/src/messages/LangBundle.properties index 38787b93e3d9..4ab0eca3d279 100644 --- a/platform/platform-resources-en/src/messages/LangBundle.properties +++ b/platform/platform-resources-en/src/messages/LangBundle.properties @@ -30,8 +30,7 @@ unexpected.eof=Unexpected end of file completion.no.suggestions=No suggestions completion.quick.javadoc.ad=Did you know that Quick Documentation View ({0}) works in completion lookups as well? completion.quick.implementations.ad=Did you know that Quick Definition View ({0}) works in completion lookups as well? -completion.replace.ad=Choosing item with {0} will overwrite the rest of identifier after caret -completion.dot.etc.ad=Dot, semicolon and some other keys will also close this lookup and be inserted into editor +completion.dot.etc.ad=Dot, semicolon and some other keys will also close this lookup and be inserted into editor completion.smart.enter.ad=Use {0} to syntactically correct your code after completing (balance parentheses etc.) xml.terms.tag=tag @@ -41,7 +40,6 @@ xml.terms.attribute=attribute xml.terms.attribute.value=attribute value xml.terms.variable=variable error.cannot.resolve=Cannot resolve -error.cannot.resolve.infix=or dialog.template.data.language.caption=\ Template data languages are the underlying languages in template files like those of FreeMarker/Velocity frameworks.
\ To change template data language settings IntelliJ IDEA uses for a file, directory, or an entire project,
\ @@ -53,4 +51,4 @@ template.data.language.configurable=Template Data Languages template.data.language.configurable.tree.table.title=Template data language template.data.language.override.warning.text=There are template data languages specified for the subdirectories. Override them? template.data.language.override.warning.title=Override Subdirectory Template Data Languages -quickfix.change.template.data.language.text=Change {0} template data language to... \ No newline at end of file +quickfix.change.template.data.language.text=Change {0} template data language to... diff --git a/platform/platform-resources-en/src/tips/SearchInSettings.html b/platform/platform-resources-en/src/tips/SearchInSettings.html new file mode 100644 index 000000000000..b9a158bd277a --- /dev/null +++ b/platform/platform-resources-en/src/tips/SearchInSettings.html @@ -0,0 +1,13 @@ + + + + + + +
You can quickly find a setting you need in the Settings dialog, without browsing through the numerous options. +Just type some characters that to your opinion exist in the option description, and the list of settings will reduce to the +matching ones. Select the desired entry, and see the setting that contains the entered characters highlighted: +

+
+ + diff --git a/platform/platform-resources-en/src/tips/images/issueNavigation1.png b/platform/platform-resources-en/src/tips/images/issueNavigation1.png index 9c53dccfc981..605d9acad17a 100644 Binary files a/platform/platform-resources-en/src/tips/images/issueNavigation1.png and b/platform/platform-resources-en/src/tips/images/issueNavigation1.png differ diff --git a/platform/platform-resources-en/src/tips/images/search_settings.png b/platform/platform-resources-en/src/tips/images/search_settings.png new file mode 100644 index 000000000000..a689f1452052 Binary files /dev/null and b/platform/platform-resources-en/src/tips/images/search_settings.png differ diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ff5b7a9cd749..2713d389dd7a 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -227,8 +227,10 @@ - + + diff --git a/platform/platform-resources/src/componentSets/Lang.xml b/platform/platform-resources/src/componentSets/Lang.xml index cac6b3fcd3d2..47b1ae13ef32 100644 --- a/platform/platform-resources/src/componentSets/Lang.xml +++ b/platform/platform-resources/src/componentSets/Lang.xml @@ -197,6 +197,7 @@ com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector + diff --git a/platform/platform-resources/src/idea/Keymap_Netbeans.xml b/platform/platform-resources/src/idea/Keymap_Netbeans.xml index 89b6cf4258de..4b643cda07ab 100644 --- a/platform/platform-resources/src/idea/Keymap_Netbeans.xml +++ b/platform/platform-resources/src/idea/Keymap_Netbeans.xml @@ -334,9 +334,6 @@ - - - diff --git a/platform/testFramework/src/com/intellij/testFramework/TestEditorManagerImpl.java b/platform/testFramework/src/com/intellij/testFramework/TestEditorManagerImpl.java index 08b08f3f4d08..378fa1898df7 100644 --- a/platform/testFramework/src/com/intellij/testFramework/TestEditorManagerImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/TestEditorManagerImpl.java @@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -148,12 +149,14 @@ import java.util.Map; @Override public void closeAllFiles() { final EditorFactory editorFactory = EditorFactory.getInstance(); - for (Editor editor : myVirtualFile2Editor.values()) { + Iterator it = myVirtualFile2Editor.values().iterator(); + while (it.hasNext()) { + Editor editor = it.next(); + it.remove(); if (editor != null && !editor.isDisposed()){ editorFactory.releaseEditor(editor); } } - myVirtualFile2Editor.clear(); } public Editor openTextEditorEnsureNoFocus(@NotNull OpenFileDescriptor descriptor) { @@ -278,6 +281,7 @@ import java.util.Map; @Override public void projectClosed() { + closeAllFiles(); } @Override @@ -286,10 +290,9 @@ import java.util.Map; @Override public void closeFile(@NotNull VirtualFile file) { - Editor editor = myVirtualFile2Editor.get(file); + Editor editor = myVirtualFile2Editor.remove(file); if (editor != null){ EditorFactory.getInstance().releaseEditor(editor); - myVirtualFile2Editor.remove(file); } if (file == myActiveFile) myActiveFile = null; } diff --git a/platform/util/src/com/intellij/execution/rmi/RemoteObject.java b/platform/util/src/com/intellij/execution/rmi/RemoteObject.java index 65ea38844586..76f34961a86a 100644 --- a/platform/util/src/com/intellij/execution/rmi/RemoteObject.java +++ b/platform/util/src/com/intellij/execution/rmi/RemoteObject.java @@ -113,8 +113,4 @@ public class RemoteObject implements Remote, Unreferenced { return false; } - public RuntimeException rethrowException(Throwable e) { - Throwable wrap = wrapException(e); - throw wrap instanceof RuntimeException ? (RuntimeException)wrap : new RuntimeException(wrap); - } } diff --git a/platform/util/src/com/intellij/ide/ui/ListCellRendererWrapper.java b/platform/util/src/com/intellij/ide/ui/ListCellRendererWrapper.java index ed9f4ddced4e..bf5bb390eb00 100644 --- a/platform/util/src/com/intellij/ide/ui/ListCellRendererWrapper.java +++ b/platform/util/src/com/intellij/ide/ui/ListCellRendererWrapper.java @@ -15,16 +15,15 @@ */ package com.intellij.ide.ui; -import org.jetbrains.annotations.Nullable; - import javax.swing.*; import java.awt.*; /** - * @author oleg - * @date 9/30/10 * Please use this wrapper in case you need simple cell renderer with text and icon. - * This avoids ugly UI under GTK look and feel, because in this case SynthComboBoxUI#SynthComboBoxRenderer is used instead of DefaultComboBoxRenderer + * This avoids ugly UI under GTK+ look&feel, because in this case SynthComboBoxUI#SynthComboBoxRenderer is used instead of DefaultComboBoxRenderer. + * + * @author oleg + * Date: 9/30/10 */ public abstract class ListCellRendererWrapper implements ListCellRenderer { private final ListCellRenderer myOriginalRenderer; @@ -34,7 +33,7 @@ public abstract class ListCellRendererWrapper implements ListCellRenderer { /** * Default JComboBox cell renderer should be passed here. - * @param listCellRenderer + * @param listCellRenderer Default cell renderer ({@link javax.swing.JComboBox#getRenderer()}). */ public ListCellRendererWrapper(final ListCellRenderer listCellRenderer) { this.myOriginalRenderer = listCellRenderer; @@ -46,6 +45,7 @@ public abstract class ListCellRendererWrapper implements ListCellRenderer { final boolean isSelected, final boolean cellHasFocus) { try { + //noinspection unchecked customize(list, (T)value, index, isSelected, cellHasFocus); final Component component = myOriginalRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (myIcon != null && component instanceof JLabel) { @@ -64,14 +64,15 @@ public abstract class ListCellRendererWrapper implements ListCellRenderer { /** * Implement this method to configure text and icon for given value. - * Use setIcon(icon) and setText(text) methods. - * @param list - * @param value Value to customize presentation for - * @param index - * @param selected - * @param cellHasFocus + * Use {@link #setIcon(javax.swing.Icon)} and {@link #setText(String)} methods. + * + * @param list The JList we're painting. + * @param value The value returned by list.getModel().getElementAt(index). + * @param index The cells index. + * @param selected True if the specified cell was selected. + * @param hasFocus True if the specified cell has the focus. */ - public abstract void customize(final JList list, final T value, final int index, final boolean selected, final boolean cellHasFocus); + public abstract void customize(final JList list, final T value, final int index, final boolean selected, final boolean hasFocus); public final void setIcon(final Icon icon) { myIcon = icon; diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index c6c1220ae681..75f136d73339 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -672,18 +672,22 @@ public class FileUtil { return candidate; } + @NotNull public static String toSystemDependentName(@NonNls @NotNull String aFileName) { return aFileName.replace('/', File.separatorChar).replace('\\', File.separatorChar); } + @NotNull public static String toSystemIndependentName(@NonNls @NotNull String aFileName) { return aFileName.replace('\\', '/'); } + @NotNull public static String nameToCompare(@NonNls @NotNull String name) { return (SystemInfo.isFileSystemCaseSensitive ? name : name.toLowerCase()).replace('\\', '/'); } + @NotNull public static String unquote(String urlString) { urlString = urlString.replace('/', File.separatorChar); return URLUtil.unescapePercentSequences(urlString); diff --git a/platform/util/src/com/intellij/util/containers/SortedList.java b/platform/util/src/com/intellij/util/containers/SortedList.java index f5233320daed..49bc76998949 100644 --- a/platform/util/src/com/intellij/util/containers/SortedList.java +++ b/platform/util/src/com/intellij/util/containers/SortedList.java @@ -21,74 +21,91 @@ import java.util.*; * @author peter */ public class SortedList extends AbstractList{ + private final SortedMap> myMap; private final Comparator myComparator; - private boolean mySorted; - private final List myDelegate = new ArrayList(); + private List myDelegate = null; public SortedList(final Comparator comparator) { myComparator = comparator; + myMap = new TreeMap>(comparator); + } + + public Comparator getComparator() { + return myComparator; } @Override public void add(final int index, final T element) { - mySorted = false; - myDelegate.add(index, element); + _addToMap(element); + } + + private void _addToMap(T element) { + List group = myMap.get(element); + if (group == null) { + myMap.put(element, group = new ArrayList()); + } + group.add(element); + myDelegate = null; + } + + @Override + public boolean add(T t) { + _addToMap(t); + return true; } @Override public T remove(final int index) { - return myDelegate.remove(index); + final T value = get(index); + remove(value); + return value; } @Override - public boolean remove(Object o) { - ensureSorted(); - final int i = Collections.binarySearch(myDelegate, (T)o, myComparator); - if (i >= 0) { - myDelegate.remove(i); - return true; + public boolean remove(Object value) { + final List group = myMap.remove(value); + if (group == null) return false; + + group.remove(value); + if (!group.isEmpty()) { + myMap.put(group.get(0), group); } - return false; + myDelegate = null; + return true; } public T get(final int index) { - ensureSorted(); + ensureLinearized(); return myDelegate.get(index); } - private void ensureSorted() { - if (!mySorted) { - sort(myDelegate); - mySorted = true; + private List ensureLinearized() { + if (myDelegate == null) { + myDelegate = ContainerUtil.concat(myMap.values()); } - } - - public void markDirty() { - mySorted = false; - } - - protected void sort(List delegate) { - Collections.sort(myDelegate, myComparator); + return myDelegate; } @Override public void clear() { - myDelegate.clear(); + myMap.clear(); + myDelegate = null; } @Override public Iterator iterator() { - ensureSorted(); - return super.iterator(); + ensureLinearized(); + return myDelegate.iterator(); } @Override public ListIterator listIterator() { - ensureSorted(); - return super.listIterator(); + ensureLinearized(); + return myDelegate.listIterator(); } public int size() { + ensureLinearized(); return myDelegate.size(); } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties index effab0db5cf2..af558e551fd2 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1784,3 +1784,4 @@ expected.exception.never.thrown.problem.descriptor=Expected #ref ne choose.logger.class=Choose logger class logger.class.names=Logger class names bad.exception.declared.ignore.exceptions.declared.in.tests.option=&Ignore exceptions declared in tests +allow.resource.to.be.opened.inside.a.try.block=Allow resource to be opened inside a try block diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java index bcff227fce3f..b1060aa2d2df 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/BaseInspection.java @@ -260,8 +260,8 @@ public abstract class BaseInspection extends BaseJavaLocalInspectionTool { } @Override - public void inspectionFinished(LocalInspectionToolSession session) { - super.inspectionFinished(session); + public void inspectionFinished(LocalInspectionToolSession session, ProblemsHolder problemsHolder) { + super.inspectionFinished(session, problemsHolder); if (InspectionGadgetsPlugin.TELEMETRY_ENABLED) { if (timeStamp < 0) { System.out.println("finish reported without corresponding start"); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java index 47c3be83a4e5..8db0b611e829 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/dataflow/TooBroadScopeInspection.java @@ -115,9 +115,9 @@ public class TooBroadScopeInspection extends BaseInspection ProblemDescriptor descriptor) throws IncorrectOperationException { - final PsiElement variableIdentifier = - descriptor.getPsiElement(); - if (!(variableIdentifier instanceof PsiVariable)) { + final PsiElement variableIdentifier = descriptor.getPsiElement(); + if (!(variableIdentifier instanceof PsiIdentifier)) + { return; } final PsiVariable variable = diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ChannelResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ChannelResourceInspection.java index 8558dd24fc10..2c93d0b96436 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ChannelResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ChannelResourceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,26 +21,33 @@ import com.siyeh.HardcodedMethodConstants; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ig.ui.CheckBox; import org.jetbrains.annotations.NotNull; -public class ChannelResourceInspection extends ResourceInspection{ +import javax.swing.*; +import java.awt.*; + +public class ChannelResourceInspection extends ResourceInspection { + + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; @Override @NotNull - public String getID(){ + public String getID() { return "ChannelOpenedButNotSafelyClosed"; } @Override @NotNull - public String getDisplayName(){ + public String getDisplayName() { return InspectionGadgetsBundle.message( "channel.opened.not.closed.display.name"); } @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -50,36 +57,58 @@ public class ChannelResourceInspection extends ResourceInspection{ } @Override - public BaseInspectionVisitor buildVisitor(){ + public JComponent createOptionsPanel() { + final JComponent panel = new JPanel(new GridBagLayout()); + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; + } + + @Override + public BaseInspectionVisitor buildVisitor() { return new ChannelResourceVisitor(); } - private static class ChannelResourceVisitor extends BaseInspectionVisitor{ + private class ChannelResourceVisitor extends BaseInspectionVisitor { - @Override public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression){ + @Override + public void visitMethodCallExpression( + @NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if(!isChannelFactoryMethod(expression)){ + if (!isChannelFactoryMethod(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; } final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isChannelFactoryClosedInFinally(expression)){ + if (isChannelFactoryClosedInFinally(expression)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - private static boolean isChannelFactoryClosedInFinally( + private boolean isChannelFactoryClosedInFinally( PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); @@ -98,31 +127,31 @@ public class ChannelResourceInspection extends ResourceInspection{ PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(expression, PsiTryStatement.class, true, PsiMember.class); - if(tryStatement == null){ + if (tryStatement == null) { return false; } - while (!resourceIsClosedInFinally(tryStatement, variable)) { + while (!isResourceClosedInFinally(tryStatement, variable)) { tryStatement = PsiTreeUtil.getParentOfType(tryStatement, - PsiTryStatement.class, true, PsiMember.class); - if(tryStatement == null){ + PsiTryStatement.class, true, PsiMember.class); + if (tryStatement == null) { return false; } } return true; } - private static boolean isChannelFactoryMethod( - PsiMethodCallExpression expression){ + private boolean isChannelFactoryMethod( + PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); - if(!HardcodedMethodConstants.GET_CHANNEL.equals(methodName)) { + if (!HardcodedMethodConstants.GET_CHANNEL.equals(methodName)) { return false; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if(qualifier == null) { + if (qualifier == null) { return false; } return TypeUtils.expressionHasTypeOrSubtype(qualifier, diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/HibernateResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/HibernateResourceInspection.java index b5e66653cde0..d650adfafcdf 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/HibernateResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/HibernateResourceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,26 +20,33 @@ import com.siyeh.HardcodedMethodConstants; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ig.ui.CheckBox; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.*; + public class HibernateResourceInspection extends ResourceInspection { + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; + @Override @NotNull - public String getID(){ + public String getID() { return "HibernateResourceOpenedButNotSafelyClosed"; } @Override @NotNull - public String getDisplayName(){ + public String getDisplayName() { return InspectionGadgetsBundle.message( "hibernate.resource.opened.not.closed.display.name"); } @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -50,43 +57,65 @@ public class HibernateResourceInspection extends ResourceInspection { } @Override - public BaseInspectionVisitor buildVisitor(){ + public JComponent createOptionsPanel() { + final JComponent panel = new JPanel(new GridBagLayout()); + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; + } + + @Override + public BaseInspectionVisitor buildVisitor() { return new HibernateResourceVisitor(); } - private static class HibernateResourceVisitor extends BaseInspectionVisitor{ + private class HibernateResourceVisitor extends BaseInspectionVisitor { - @Override public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression){ + @Override + public void visitMethodCallExpression( + @NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if(!isHibernateFactoryMethod(expression)){ + if (!isHibernateFactoryMethod(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; } final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - private static boolean isHibernateFactoryMethod( - PsiMethodCallExpression expression){ + private boolean isHibernateFactoryMethod( + PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); - if(!HardcodedMethodConstants.OPEN_SESSION.equals(methodName)){ + if (!HardcodedMethodConstants.OPEN_SESSION.equals(methodName)) { return false; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if(qualifier == null){ + if (qualifier == null) { return false; } return TypeUtils.expressionHasTypeOrSubtype(qualifier, diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java index d7e89c78fd6b..045686cee646 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/IOResourceInspection.java @@ -15,7 +15,9 @@ */ package com.siyeh.ig.resources; -import com.intellij.codeInspection.ui.RemoveAction; +import com.intellij.codeInspection.ui.ListTable; +import com.intellij.codeInspection.ui.ListWrappingTableModel; +import com.intellij.openapi.actionSystem.ActionToolbar; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.WriteExternalException; import com.intellij.psi.*; @@ -24,9 +26,8 @@ import com.intellij.ui.ScrollPaneFactory; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.TypeUtils; -import com.intellij.codeInspection.ui.ListTable; -import com.intellij.codeInspection.ui.ListWrappingTableModel; -import com.siyeh.ig.ui.TreeClassChooserAction; +import com.siyeh.ig.ui.CheckBox; +import com.siyeh.ig.ui.UiUtils; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -38,37 +39,45 @@ import java.util.List; public class IOResourceInspection extends ResourceInspection { + private static final String[] IO_TYPES = { + "java.io.InputStream", "java.io.OutputStream", + "java.io.Reader", "java.io.Writer", + "java.io.RandomAccessFile", "java.util.zip.ZipFile"}; + @NonNls @SuppressWarnings({"PublicField"}) public String ignoredTypesString = "java.io.ByteArrayOutputStream" + - ',' + "java.io.ByteArrayInputStream" + - ',' + "java.io.StringBufferInputStream" + - ',' + "java.io.CharArrayWriter" + - ',' + "java.io.CharArrayReader" + - ',' + "java.io.StringWriter" + - ',' + "java.io.StringReader"; + ',' + "java.io.ByteArrayInputStream" + + ',' + "java.io.StringBufferInputStream" + + ',' + "java.io.CharArrayWriter" + + ',' + "java.io.CharArrayReader" + + ',' + "java.io.StringWriter" + + ',' + "java.io.StringReader"; final List ignoredTypes = new ArrayList(); + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; + public IOResourceInspection() { parseString(ignoredTypesString, ignoredTypes); } @Override @NotNull - public String getID(){ + public String getID() { return "IOResourceOpenedButNotSafelyClosed"; } @Override @NotNull - public String getDisplayName(){ + public String getDisplayName() { return InspectionGadgetsBundle.message( "i.o.resource.opened.not.closed.display.name"); } @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -80,36 +89,43 @@ public class IOResourceInspection extends ResourceInspection { @Override public JComponent createOptionsPanel() { final JComponent panel = new JPanel(new GridBagLayout()); - final GridBagConstraints constraints = new GridBagConstraints(); - constraints.anchor = GridBagConstraints.FIRST_LINE_START; - constraints.gridx = 0; - constraints.gridy = 0; - constraints.gridheight = 2; - constraints.weightx = 1.0; - constraints.weighty = 1.0; - constraints.fill = GridBagConstraints.BOTH; + final ListTable table = new ListTable(new ListWrappingTableModel(ignoredTypes, InspectionGadgetsBundle.message( "ignored.io.resource.types"))); - final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(table); - panel.add(scrollPane, constraints); - constraints.gridx = 1; - constraints.weightx = 0.0; - constraints.weighty = 0.0; - constraints.gridheight = 1; - constraints.fill = GridBagConstraints.HORIZONTAL; - final JButton addButton = - new JButton(new TreeClassChooserAction(table, + final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(table); + + final ActionToolbar toolbar = + UiUtils.createAddRemoveTreeClassChooserToolbar(table, InspectionGadgetsBundle.message( - "choose.io.resource.type.to.ignore"), - "java.io.InputStream", "java.io.OutputStream", - "java.io.Reader", "java.io.Writer", - "java.io.RandomAccessFile")); - panel.add(addButton, constraints); + "choose.io.resource.type.to.ignore"), IO_TYPES); + + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(toolbar.getComponent(), constraints); + constraints.gridy = 1; - final JButton removeButton = new JButton(new RemoveAction(table)); - panel.add(removeButton, constraints); + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.BOTH; + panel.add(scrollPane, constraints); + + constraints.gridy = 2; + constraints.weighty = 0.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; } @@ -126,28 +142,28 @@ public class IOResourceInspection extends ResourceInspection { } @Override - public BaseInspectionVisitor buildVisitor(){ + public BaseInspectionVisitor buildVisitor() { return new IOResourceVisitor(); } - private class IOResourceVisitor extends BaseInspectionVisitor{ + private class IOResourceVisitor extends BaseInspectionVisitor { - @Override public void visitNewExpression( - @NotNull PsiNewExpression expression){ + @Override + public void visitNewExpression(@NotNull PsiNewExpression expression) { super.visitNewExpression(expression); - if(!isIOResource(expression)){ + if (!isIOResource(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; - } if (parent instanceof PsiExpressionList){ + } else if (parent instanceof PsiExpressionList) { PsiElement grandParent = parent.getParent(); - if(grandParent instanceof PsiAnonymousClass){ + if (grandParent instanceof PsiAnonymousClass) { grandParent = grandParent.getParent(); } - if(grandParent instanceof PsiNewExpression && - isIOResource((PsiNewExpression) grandParent)){ + if (grandParent instanceof PsiNewExpression && + isIOResource((PsiNewExpression) grandParent)) { return; } } @@ -157,10 +173,10 @@ public class IOResourceInspection extends ResourceInspection { if (containingBlock == null) { return; } - if(isArgumentOfResourceCreation(boundVariable, containingBlock)){ + if (isArgumentOfResourceCreation(boundVariable, containingBlock)) { return; } - if (isSafelyClosed(boundVariable, expression)) { + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } if (isResourceEscapedFromMethod(boundVariable, expression)) { @@ -171,11 +187,9 @@ public class IOResourceInspection extends ResourceInspection { } - public boolean isIOResource(PsiExpression expression){ - return TypeUtils.expressionHasTypeOrSubtype(expression, - "java.io.InputStream", "java.io.Writer", "java.io.Reader", - "java.io.RandomAccessFile", "java.io.OutputStream", "java.util.zip.ZipFile") != null && - !isIgnoredType(expression); + public boolean isIOResource(PsiExpression expression) { + return TypeUtils.expressionHasTypeOrSubtype(expression, IO_TYPES) != + null && !isIgnoredType(expression); } private boolean isIgnoredType(PsiExpression expression) { @@ -183,54 +197,55 @@ public class IOResourceInspection extends ResourceInspection { } private boolean isArgumentOfResourceCreation( - PsiVariable boundVariable, PsiElement scope){ + PsiVariable boundVariable, PsiElement scope) { final UsedAsIOResourceArgumentVisitor visitor = new UsedAsIOResourceArgumentVisitor(boundVariable); scope.accept(visitor); - return visitor.usedAsArgumentToResourceCreation(); + return visitor.isUsedAsArgumentToResourceCreation(); } private class UsedAsIOResourceArgumentVisitor - extends JavaRecursiveElementVisitor{ + extends JavaRecursiveElementVisitor { private boolean usedAsArgToResourceCreation = false; private final PsiVariable ioResource; - private UsedAsIOResourceArgumentVisitor(PsiVariable ioResource){ + private UsedAsIOResourceArgumentVisitor(PsiVariable ioResource) { this.ioResource = ioResource; } - @Override public void visitNewExpression( - @NotNull PsiNewExpression expression){ - if(usedAsArgToResourceCreation){ + @Override + public void visitNewExpression( + @NotNull PsiNewExpression expression) { + if (usedAsArgToResourceCreation) { return; } super.visitNewExpression(expression); - if(!isIOResource(expression)){ + if (!isIOResource(expression)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); - if(argumentList == null){ + if (argumentList == null) { return; } final PsiExpression[] arguments = argumentList.getExpressions(); - if(arguments.length == 0){ + if (arguments.length == 0) { return; } final PsiExpression argument = arguments[0]; - if(argument == null || - !(argument instanceof PsiReferenceExpression)){ + if (argument == null || + !(argument instanceof PsiReferenceExpression)) { return; } - final PsiElement referent = - ((PsiReference) argument).resolve(); - if(referent == null || !referent.equals(ioResource)){ + final PsiReference reference = (PsiReference) argument; + final PsiElement target = reference.resolve(); + if (target == null || !target.equals(ioResource)) { return; } usedAsArgToResourceCreation = true; } - public boolean usedAsArgumentToResourceCreation(){ + public boolean isUsedAsArgumentToResourceCreation() { return usedAsArgToResourceCreation; } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java index c4f4e1f02010..ef4ef65f921d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JDBCResourceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,62 +19,70 @@ import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; +import com.siyeh.ig.ui.CheckBox; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.*; import java.util.HashSet; import java.util.Set; -public class JDBCResourceInspection extends ResourceInspection{ +public class JDBCResourceInspection extends ResourceInspection { private static final String[] creationMethodClassName = - new String[]{ - "java.sql.Driver", - "java.sql.DriverManager", - "javax.sql.DataSource", - "java.sql.Connection", - "java.sql.Connection", - "java.sql.Connection", - "java.sql.Statement", - "java.sql.Statement", - "java.sql.Statement", + { + "java.sql.Driver", + "java.sql.DriverManager", + "javax.sql.DataSource", + "java.sql.Connection", + "java.sql.Connection", + "java.sql.Connection", + "java.sql.Statement", + "java.sql.Statement", + "java.sql.Statement", }; - @NonNls private static final String[] creationMethodName = - new String[]{ - "connect", - "getConnection", - "getConnection", - "createStatement", - "prepareStatement", - "prepareCall", - "executeQuery", - "getResultSet", - "getGeneratedKeys" + @NonNls + private static final String[] creationMethodName = + { + "connect", + "getConnection", + "getConnection", + "createStatement", + "prepareStatement", + "prepareCall", + "executeQuery", + "getResultSet", + "getGeneratedKeys" }; - /** - * @noinspection StaticCollection - */ + @SuppressWarnings({"StaticCollection"}) private static final Set creationMethodNameSet = new HashSet(9); + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; + static { - ContainerUtil.addAll(creationMethodNameSet, creationMethodName); + ContainerUtil.addAll(creationMethodNameSet, creationMethodName); } + @Override @NotNull - public String getID(){ + public String getID() { return "JDBCResourceOpenedButNotSafelyClosed"; } + @Override @NotNull - public String getDisplayName(){ + public String getDisplayName() { return InspectionGadgetsBundle.message( "jdbc.resource.opened.not.closed.display.name"); } + @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -83,60 +91,83 @@ public class JDBCResourceInspection extends ResourceInspection{ "jdbc.resource.opened.not.closed.problem.descriptor", text); } - public BaseInspectionVisitor buildVisitor(){ + @Override + public JComponent createOptionsPanel() { + final JComponent panel = new JPanel(new GridBagLayout()); + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; + } + + @Override + public BaseInspectionVisitor buildVisitor() { return new JDBCResourceVisitor(); } - private static class JDBCResourceVisitor extends BaseInspectionVisitor{ + private class JDBCResourceVisitor extends BaseInspectionVisitor { - @Override public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression){ + @Override + public void visitMethodCallExpression( + @NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if(!isJDBCResourceCreation(expression)){ + if (!isJDBCResourceCreation(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; } final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - private static boolean isJDBCResourceCreation( - PsiMethodCallExpression expression){ + private boolean isJDBCResourceCreation( + PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String name = methodExpression.getReferenceName(); - if(name == null){ + if (name == null) { return false; } - if(!creationMethodNameSet.contains(name)){ + if (!creationMethodNameSet.contains(name)) { return false; } final PsiMethod method = expression.resolveMethod(); - if(method == null){ + if (method == null) { return false; } - for(int i = 0; i < creationMethodName.length; i++){ - if(!name.equals(creationMethodName[i])){ + for (int i = 0; i < creationMethodName.length; i++) { + if (!name.equals(creationMethodName[i])) { continue; } final PsiClass containingClass = method.getContainingClass(); - if(containingClass == null){ + if (containingClass == null) { return false; } final String className = containingClass.getQualifiedName(); - if(className == null){ + if (className == null) { return false; } - if(className.equals(creationMethodClassName[i])){ + if (className.equals(creationMethodClassName[i])) { return true; } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JNDIResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JNDIResourceInspection.java index 1d5d3d491780..d79432ab2b52 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JNDIResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/JNDIResourceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,24 +19,34 @@ import com.intellij.psi.*; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ig.ui.CheckBox; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.*; + public class JNDIResourceInspection extends ResourceInspection { + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; + + @Override @NotNull - public String getID(){ + public String getID() { return "JNDIResourceOpenedButNotSafelyClosed"; } + @Override @NotNull - public String getDisplayName(){ + public String getDisplayName() { return InspectionGadgetsBundle.message( "jndi.resource.opened.not.closed.display.name"); } + @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -45,41 +55,46 @@ public class JNDIResourceInspection extends ResourceInspection { "resource.opened.not.closed.problem.descriptor", text); } - public BaseInspectionVisitor buildVisitor(){ + @Override + public JComponent createOptionsPanel() { + final JComponent panel = new JPanel(new GridBagLayout()); + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; + } + + @Override + public BaseInspectionVisitor buildVisitor() { return new JNDIResourceVisitor(); } - private static class JNDIResourceVisitor extends BaseInspectionVisitor{ + private class JNDIResourceVisitor extends BaseInspectionVisitor { - @NonNls private static final String LIST = "list"; - @NonNls private static final String LIST_BINDING = "listBindings"; - @NonNls private static final String GET_ALL = "getAll"; + @NonNls + private static final String LIST = "list"; + @NonNls + private static final String LIST_BINDING = "listBindings"; + @NonNls + private static final String GET_ALL = "getAll"; - @Override public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression){ + @Override + public void visitMethodCallExpression( + @NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if(!isJNDIFactoryMethod(expression)){ - return; - } - final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ - return; - } - final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ - return; - } - if(isResourceEscapedFromMethod(boundVariable, expression)){ - return; - } - registerError(expression, expression); - } - - - @Override public void visitNewExpression( - @NotNull PsiNewExpression expression){ - super.visitNewExpression(expression); - if(!isJNDIResource(expression)){ + if (!isJNDIFactoryMethod(expression)) { return; } final PsiElement parent = getExpressionParent(expression); @@ -87,22 +102,44 @@ public class JNDIResourceInspection extends ResourceInspection { return; } final PsiVariable boundVariable = getVariable(parent); - if (isSafelyClosed(boundVariable, expression)) { + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - private static boolean isJNDIResource(PsiNewExpression expression){ - return TypeUtils.expressionHasTypeOrSubtype(expression, - "javax.naming.InitialContext"); + + @Override + public void visitNewExpression( + @NotNull PsiNewExpression expression) { + super.visitNewExpression(expression); + if (!isJNDIResource(expression)) { + return; + } + final PsiElement parent = getExpressionParent(expression); + if (parent instanceof PsiReturnStatement) { + return; + } + final PsiVariable boundVariable = getVariable(parent); + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { + return; + } + if (isResourceEscapedFromMethod(boundVariable, expression)) { + return; + } + registerError(expression, expression); } - private static boolean isJNDIFactoryMethod( - PsiMethodCallExpression expression){ + private boolean isJNDIResource(PsiNewExpression expression) { + return TypeUtils.expressionHasTypeOrSubtype(expression, + "javax.naming.InitialContext"); + } + + private boolean isJNDIFactoryMethod( + PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ResourceInspection.java index cfd7641fd1d5..b5ed6b87fba5 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/ResourceInspection.java @@ -59,7 +59,8 @@ public abstract class ResourceInspection extends BaseInspection { } protected static boolean isSafelyClosed(@Nullable PsiVariable variable, - PsiElement context) { + PsiElement context, + boolean insideTryAllowed) { if (variable == null) { return false; } @@ -71,6 +72,23 @@ public abstract class ResourceInspection extends BaseInspection { PsiStatement nextStatement = PsiTreeUtil.getNextSiblingOfType(statement, PsiStatement.class); + if (insideTryAllowed) { + PsiStatement parentStatement = + PsiTreeUtil.getParentOfType(statement, PsiStatement.class); + while (parentStatement != null && + !(parentStatement instanceof PsiTryStatement)) { + parentStatement = + PsiTreeUtil.getParentOfType(statement, + PsiStatement.class); + } + if (parentStatement != null) { + final PsiTryStatement tryStatement = + (PsiTryStatement) parentStatement; + if (isResourceClosedInFinally(tryStatement, variable)) { + return true; + } + } + } while (nextStatement == null) { statement = PsiTreeUtil.getParentOfType(statement, PsiStatement.class, true); @@ -90,10 +108,10 @@ public abstract class ResourceInspection extends BaseInspection { return isResourceClose(nextStatement, variable); } final PsiTryStatement tryStatement = (PsiTryStatement) nextStatement; - return resourceIsClosedInFinally(tryStatement, variable); + return isResourceClosedInFinally(tryStatement, variable); } - protected static boolean resourceIsClosedInFinally( + protected static boolean isResourceClosedInFinally( @NotNull PsiTryStatement tryStatement, @NotNull PsiVariable variable) { final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock(); @@ -126,16 +144,16 @@ public abstract class ResourceInspection extends BaseInspection { } protected static boolean isResourceEscapedFromMethod( - PsiVariable boundVariable, PsiElement context){ + PsiVariable boundVariable, PsiElement context) { // poor man dataflow final PsiMethod method = PsiTreeUtil.getParentOfType(context, PsiMethod.class, true, PsiMember.class); - if(method == null){ + if (method == null) { return false; } final PsiCodeBlock body = method.getBody(); - if(body == null){ + if (body == null) { return false; } final EscapeVisitor visitor = new EscapeVisitor(boundVariable); @@ -274,40 +292,43 @@ public abstract class ResourceInspection extends BaseInspection { } } - private static class EscapeVisitor extends JavaRecursiveElementVisitor{ + private static class EscapeVisitor extends JavaRecursiveElementVisitor { private final PsiVariable boundVariable; private boolean escaped = false; - public EscapeVisitor(PsiVariable boundVariable){ + public EscapeVisitor(PsiVariable boundVariable) { this.boundVariable = boundVariable; } - @Override public void visitAnonymousClass(PsiAnonymousClass aClass){} + @Override + public void visitAnonymousClass(PsiAnonymousClass aClass) { + } @Override - public void visitElement(PsiElement element){ - if(escaped){ + public void visitElement(PsiElement element) { + if (escaped) { return; } super.visitElement(element); } - @Override public void visitReturnStatement( - PsiReturnStatement statement){ + @Override + public void visitReturnStatement( + PsiReturnStatement statement) { PsiExpression value = statement.getReturnValue(); value = PsiUtil.deparenthesizeExpression(value); - if (value instanceof PsiReferenceExpression){ + if (value instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression) value; final PsiElement target = referenceExpression.resolve(); - if(target == boundVariable){ + if (target != null && target.equals(boundVariable)) { escaped = true; } } } - public boolean isEscaped(){ + public boolean isEscaped() { return escaped; } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/SocketResourceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/SocketResourceInspection.java index 6c475f33b604..273825c1431c 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/resources/SocketResourceInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/resources/SocketResourceInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,27 +19,34 @@ import com.intellij.psi.*; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.TypeUtils; +import com.siyeh.ig.ui.CheckBox; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.*; + public class SocketResourceInspection extends ResourceInspection { - @Override - @NotNull - public String getID(){ - return "SocketOpenedButNotSafelyClosed"; - } + @SuppressWarnings({"PublicField"}) + public boolean insideTryAllowed = false; @Override @NotNull - public String getDisplayName(){ + public String getID() { + return "SocketOpenedButNotSafelyClosed"; + } + + @Override + @NotNull + public String getDisplayName() { return InspectionGadgetsBundle.message( "socket.opened.not.closed.display.name"); } @Override @NotNull - public String buildErrorString(Object... infos){ + public String buildErrorString(Object... infos) { final PsiExpression expression = (PsiExpression) infos[0]; final PsiType type = expression.getType(); assert type != null; @@ -49,71 +56,95 @@ public class SocketResourceInspection extends ResourceInspection { } @Override - public BaseInspectionVisitor buildVisitor(){ + public JComponent createOptionsPanel() { + final JComponent panel = new JPanel(new GridBagLayout()); + final CheckBox checkBox = new CheckBox( + InspectionGadgetsBundle.message( + "allow.resource.to.be.opened.inside.a.try.block"), + this, "insideTryAllowed"); + + final GridBagConstraints constraints = new GridBagConstraints(); + constraints.anchor = GridBagConstraints.FIRST_LINE_START; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.insets.left = 4; + constraints.insets.right = 4; + constraints.weightx = 1.0; + constraints.weighty = 1.0; + constraints.fill = GridBagConstraints.HORIZONTAL; + panel.add(checkBox, constraints); + return panel; + } + + + @Override + public BaseInspectionVisitor buildVisitor() { return new SocketResourceVisitor(); } - private static class SocketResourceVisitor extends BaseInspectionVisitor{ + private class SocketResourceVisitor extends BaseInspectionVisitor { - @Override public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression expression){ + @Override + public void visitMethodCallExpression( + @NotNull PsiMethodCallExpression expression) { super.visitMethodCallExpression(expression); - if(!isSocketFactoryMethod(expression)){ + if (!isSocketFactoryMethod(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; } final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - @Override public void visitNewExpression( - @NotNull PsiNewExpression expression){ + @Override + public void visitNewExpression( + @NotNull PsiNewExpression expression) { super.visitNewExpression(expression); - if(!isSocketResource(expression)){ + if (!isSocketResource(expression)) { return; } final PsiElement parent = getExpressionParent(expression); - if(parent instanceof PsiReturnStatement){ + if (parent instanceof PsiReturnStatement) { return; } final PsiVariable boundVariable = getVariable(parent); - if(isSafelyClosed(boundVariable, expression)){ + if (isSafelyClosed(boundVariable, expression, insideTryAllowed)) { return; } - if(isResourceEscapedFromMethod(boundVariable, expression)){ + if (isResourceEscapedFromMethod(boundVariable, expression)) { return; } registerError(expression, expression); } - private static boolean isSocketResource(PsiNewExpression expression){ + private boolean isSocketResource(PsiNewExpression expression) { return TypeUtils.expressionHasTypeOrSubtype(expression, "java.net.Socket", "java.net.DatagramSocket", "java.net.ServerSocket") != null; } - private static boolean isSocketFactoryMethod( - PsiMethodCallExpression expression){ + private boolean isSocketFactoryMethod( + PsiMethodCallExpression expression) { final PsiReferenceExpression methodExpression = expression.getMethodExpression(); @NonNls final String methodName = methodExpression.getReferenceName(); - if(!"accept".equals(methodName)) { + if (!"accept".equals(methodName)) { return false; } final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if(qualifier == null) { + if (qualifier == null) { return false; } return TypeUtils.expressionHasTypeOrSubtype(qualifier, diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ChannelResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ChannelResource.html index 678bc60f37c2..a48dcbaa166f 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/ChannelResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ChannelResource.html @@ -7,5 +7,9 @@ front of a try block and closed in the corre if an exception is thrown before the resource is closed. Channel resources reported by this inspection include any instances created by calling getChannel() on a file or socket resource. +

+Use the checkbox below to specify if a Channel is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a Channel +in front of a try block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/HibernateResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/HibernateResource.html index 216f4dd7f4ec..3178ada063ff 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/HibernateResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/HibernateResource.html @@ -6,5 +6,9 @@ This inspection reports any Hibernate resource which is not opened in a finally block. Such resources may be inadvertently leaked if an exception is thrown before the resource is closed. Hibernate resources reported by this inspection include any instances of org.hibernate.Session. +

+Use the checkbox below to specify if a Hibernate resource is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a resource +in front of a try block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html index 9f5327ca381e..69dc6ac92b4b 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/IOResource.html @@ -11,5 +11,11 @@ by this inspection include any instances of java.io.Inp java.io.Writer and java.io.RandomAccessFile. I/O resources which are wrapped by other I/O resources are not reported, as the wrapped resource will be closed by the wrapping resource. +

+Use the table below to specify which I/O resources should be ignored by this inspection. +Specify I/O resource classes here which do not need to be closed. +Use the checkbox below to specify if a I/O resource is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a resource in front of a try +block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html index 8da64b6be2a7..80a24fc9db7e 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JDBCResource.html @@ -9,5 +9,9 @@ by this inspection include any instances of java.sql.Co java.sql.PreparedStatement, java.sql.CallableStatement, and java.sql.ResultSet. +

+Use the checkbox below to specify if a JDBC resource is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a resource +in front of a try block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/JNDIResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/JNDIResource.html index 351b02541bfd..494cfbbeb25d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/JNDIResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/JNDIResource.html @@ -7,5 +7,9 @@ block and closed in the corresponding finallyjavax.naming.InitialContext, and javax.naming.NamingEnumeration. +

+Use the checkbox below to specify if a JNDI Resource is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a resource +in front of a try block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SocketResource.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SocketResource.html index 133dcfa6ec3a..d5bdf1bb269e 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/SocketResource.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SocketResource.html @@ -8,5 +8,9 @@ be inadvertently leaked if an exception is thrown before the resource is closed. by this inspection include any instances of java.net.Socket, java.net.DatagramSocket, and java.net.ServerSocket. +

+Use the checkbox below to specify if a Socket is allowed to be opened inside a try +block. This style is less desirable because it is more verbose than opening a Socket +in front of a try block. Powered by InspectionGadgets \ No newline at end of file diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java index 04ba4406530b..1b14caf3978a 100644 --- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java +++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/quickedit/QuickEditAction.java @@ -263,10 +263,10 @@ public class QuickEditAction implements IntentionAction, LowPriorityAction { } boolean first = true; for (Pair markers : myMarkers.values()) { - if (first) { + //if (first) { markers.first.setGreedyToLeft(true); markers.second.setGreedyToLeft(true); - } + //} markers.first.setGreedyToRight(true); markers.second.setGreedyToRight(true); first = false; diff --git a/plugins/android/resources/messages/AndroidBundle.properties b/plugins/android/resources/messages/AndroidBundle.properties index 86048f0fe326..add62b866e3b 100644 --- a/plugins/android/resources/messages/AndroidBundle.properties +++ b/plugins/android/resources/messages/AndroidBundle.properties @@ -202,4 +202,6 @@ android.inspections.group.name=Android android.inspections.dom.name=Android Resources Validation android.inspections.unknown.attribute.name=Unknown Android XML attribute android.inspections.unknown.attribute.message=Unknown attribute {0} -android.facet.settings.generate.unsigned.apk=Generate unsigned APK \ No newline at end of file +android.facet.settings.generate.unsigned.apk=Generate unsigned APK +android.compile.messages.generating.r.java=Generating R.java... +android.actions.regenerate.r.java.file.title=Force regenerate R.java file \ No newline at end of file diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index 23c1eb056f64..45f9cc538b7a 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -53,6 +53,10 @@ + + + + JUnit diff --git a/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java b/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java new file mode 100644 index 000000000000..bdc149876b41 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/actions/AndroidRegenerateRJavaFileAction.java @@ -0,0 +1,122 @@ +/* + * 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.actions; + +import com.intellij.facet.ProjectFacetManager; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataKeys; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import org.jetbrains.android.compiler.AndroidAptCompiler; +import org.jetbrains.android.compiler.AndroidCompileUtil; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.util.AndroidBundle; +import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidRegenerateRJavaFileAction extends AnAction { + public AndroidRegenerateRJavaFileAction() { + super(AndroidBundle.message("android.actions.regenerate.r.java.file.title"), null, AndroidUtils.ANDROID_ICON); + } + + @Override + public void update(AnActionEvent e) { + final Module module = e.getData(DataKeys.MODULE); + final Project project = e.getData(DataKeys.PROJECT); + e.getPresentation().setEnabled(isAvailable(module, project)); + } + + private static boolean isAvailable(Module module, Project project) { + if (module != null) { + AndroidFacet facet = AndroidFacet.getInstance(module); + if (facet != null) { + return AndroidAptCompiler.isToCompileModule(module, facet.getConfiguration()); + } + } + else if (project != null) { + List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID); + for (AndroidFacet facet : facets) { + if (AndroidAptCompiler.isToCompileModule(facet.getModule(), facet.getConfiguration())) { + return true; + } + } + } + return false; + } + + @Override + public void actionPerformed(AnActionEvent e) { + final Module module = e.getData(DataKeys.MODULE); + final Project project = e.getData(DataKeys.PROJECT); + ApplicationManager.getApplication().saveAll(); + ProgressManager.getInstance().run( + new Task.Backgroundable(project, AndroidBundle.message("android.compile.messages.generating.r.java"), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + doRun(indicator, module, project); + } + }); + } + + private static void doRun(ProgressIndicator indicator, Module module, Project project) { + if (module != null) { + if (indicator.isCanceled()) { + return; + } + AndroidCompileUtil.generate(module, new AndroidAptCompiler(), false); + return; + } + assert project != null; + List facets = ProjectFacetManager.getInstance(project).getFacets(AndroidFacet.ID); + List modulesToProcess = new ArrayList(); + for (AndroidFacet facet : facets) { + if (indicator.isCanceled()) { + return; + } + module = facet.getModule(); + if (AndroidAptCompiler.isToCompileModule(module, facet.getConfiguration())) { + modulesToProcess.add(module); + } + } + if (modulesToProcess.size() == 0) { + return; + } + if (modulesToProcess.size() == 1) { + AndroidCompileUtil.generate(modulesToProcess.get(0), new AndroidAptCompiler(), false); + return; + } + double step = 1.0 / modulesToProcess.size(); + double progress = 0.0; + indicator.setText(AndroidBundle.message("android.compile.messages.generating.r.java")); + indicator.setFraction(progress); + for (int i = 0, n = modulesToProcess.size(); i < n; i++) { + AndroidCompileUtil.generate(modulesToProcess.get(i), new AndroidAptCompiler(), false); + progress = i < n - 1 ? progress + step : 1.0; + indicator.setFraction(progress); + } + } +} diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java index bbf642a1bff8..34f689051ec4 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java @@ -34,6 +34,7 @@ import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.maven.AndroidMavenUtil; +import org.jetbrains.android.util.AndroidBundle; import org.jetbrains.android.util.AndroidUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -73,7 +74,7 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler { public GenerationItem[] generate(final CompileContext context, final GenerationItem[] items, VirtualFile outputRootDirectory) { if (items != null && items.length > 0) { - context.getProgressIndicator().setText("Generating " + AndroidUtils.R_JAVA_FILENAME + "..."); + context.getProgressIndicator().setText(AndroidBundle.message("android.compile.messages.generating.r.java")); Computable computation = new Computable() { public GenerationItem[] compute() { if (context.getProject().isDisposed()) { diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompiler.java index a527276651ce..c6b224f751e6 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidDexCompiler.java @@ -129,13 +129,15 @@ public class AndroidDexCompiler implements ClassPostProcessingCompiler { AndroidFacetConfiguration configuration = facet.getConfiguration(); AndroidPlatform platform = configuration.getAndroidPlatform(); if (platform != null) { - Set dependencies = AndroidRootUtil.getExternalLibrariesAndModules(module, outputDir, platform.getLibrary()); - List files = new ArrayList(); - files.add(outputDir); - files.addAll(dependencies); + Set files = new HashSet(); + addModuleOutputDir(files, outputDir); + files.addAll(AndroidRootUtil.getExternalLibraries(module, platform.getLibrary())); + for (VirtualFile file : AndroidRootUtil.getDependentModules(module, outputDir)) { + addModuleOutputDir(files, file); + } VirtualFile outputDirForTests = extension.getCompilerOutputPathForTests(); if (outputDirForTests != null) { - files.add(outputDirForTests); + addModuleOutputDir(files, outputDirForTests); } IAndroidTarget target = configuration.getAndroidTarget(); if (target != null) { @@ -149,6 +151,15 @@ public class AndroidDexCompiler implements ClassPostProcessingCompiler { } return items.toArray(new ProcessingItem[items.size()]); } + + private static void addModuleOutputDir(Set files, VirtualFile dir) { + // only include files inside packages + for (VirtualFile child : dir.getChildren()) { + if (child.isDirectory()) { + files.add(child); + } + } + } } private static void collectClassFilesInLibraryModules(AndroidFacet facet, Collection result) { diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java index 8c5f26045974..38b7f9dfeeba 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java @@ -19,13 +19,16 @@ import com.intellij.compiler.impl.CompilerUtil; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.*; +import com.intellij.openapi.compiler.ex.CompileContextEx; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.android.compiler.tools.AndroidMavenExecutor; import org.jetbrains.android.dom.manifest.Manifest; import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.maven.AndroidMavenProvider; import org.jetbrains.android.maven.AndroidMavenUtil; import org.jetbrains.android.util.AndroidUtils; @@ -70,12 +73,20 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { } }; GenerationItem[] generationItems = computation.compute(); + List generatedVFiles = new ArrayList(); for (GenerationItem item : generationItems) { File generatedFile = ((MyGenerationItem)item).myGeneratedFile; if (generatedFile != null) { CompilerUtil.refreshIOFile(generatedFile); + VirtualFile generatedVFile = LocalFileSystem.getInstance().findFileByIoFile(generatedFile); + if (generatedVFile != null) { + generatedVFiles.add(generatedVFile); + } } } + if (context instanceof CompileContextEx) { + ((CompileContextEx)context).markGenerated(generatedVFiles); + } return generationItems; } return EMPTY_GENERATION_ITEM_ARRAY; @@ -147,10 +158,11 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { } } - private static class MyValidityState implements ValidityState { + private static class MyValidityState extends ResourcesValidityState { private final long[] myMavenArtifactsTimespamps; private MyValidityState(Module module) { + super(module); AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider(); assert mavenProvider != null; List files = mavenProvider.getMavenDependencyArtifactFiles(module); @@ -160,7 +172,13 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { } } + @Override + protected VirtualFile getResourcesDir(Module module, AndroidFacet facet) { + return AndroidRootUtil.getResourceDir(module); + } + public MyValidityState(DataInput is) throws IOException { + super(is); int c = is.readInt(); myMavenArtifactsTimespamps = new long[c]; for (int i = 0; i < c; i++) { @@ -170,6 +188,9 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { @Override public boolean equalsTo(ValidityState otherState) { + if (!super.equalsTo(otherState)) { + return false; + } if (!(otherState instanceof MyValidityState)) { return false; } @@ -178,6 +199,7 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { @Override public void save(DataOutput out) throws IOException { + super.save(out); out.writeInt(myMavenArtifactsTimespamps.length); for (long timespamp : myMavenArtifactsTimespamps) { out.writeLong(timespamp); diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java index 2101e2ee65e2..d9e63ab2d994 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidPackagingCompiler.java @@ -52,20 +52,11 @@ public class AndroidPackagingCompiler implements PackagingCompiler { @NotNull private static VirtualFile[] getExternalJars(@NotNull Module module, - @NotNull VirtualFile moduleOutputDir, @NotNull AndroidFacetConfiguration configuration) { AndroidPlatform platform = configuration.getAndroidPlatform(); if (platform != null) { - Set externalLibsAndModules = - AndroidRootUtil.getExternalLibrariesAndModules(module, moduleOutputDir, platform.getLibrary()); - List result = new ArrayList(); - for (VirtualFile file : externalLibsAndModules) { - // ignore modules' compiler output folders - if (!file.isDirectory()) { - result.add(file); - } - } - return result.toArray(new VirtualFile[result.size()]); + List externalLibsAndModules = AndroidRootUtil.getExternalLibraries(module, platform.getLibrary()); + return externalLibsAndModules.toArray(new VirtualFile[externalLibsAndModules.size()]); } return VirtualFile.EMPTY_ARRAY; } @@ -107,7 +98,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler { AndroidFacetConfiguration configuration = facet.getConfiguration(); VirtualFile outputDir = context.getModuleOutputDirectory(module); if (outputDir != null) { - VirtualFile[] externalJars = getExternalJars(module, outputDir, configuration); + VirtualFile[] externalJars = getExternalJars(module, configuration); String resPackage = AndroidResourcesPackagingCompiler.getOutputPath(module, outputDir); String outputPath = new File(outputDir.getPath(), module.getName() + ".apk").getPath(); String classesDexPath = new File(outputDir.getPath(), AndroidUtils.CLASSES_FILE_NAME).getPath(); @@ -323,7 +314,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler { ArrayList nativeLibs = new ArrayList(); for (VirtualFile nativeLibFolder : nativeLibFolders) { for (VirtualFile child : nativeLibFolder.getChildren()) { - AndroidApkBuilder.collectNativeLibraries(nativeLibFolder, child, nativeLibs); + AndroidApkBuilder.collectNativeLibraries(child, nativeLibs); } } for (VirtualFile nativeLib : nativeLibs) { diff --git a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java index 74d48b0f2c25..9b3d734d3385 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java +++ b/plugins/android/src/org/jetbrains/android/compiler/ResourcesValidityState.java @@ -23,6 +23,7 @@ import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.util.AndroidUtils; +import org.jetbrains.annotations.Nullable; import java.io.DataInput; import java.io.DataOutput; @@ -52,7 +53,7 @@ public class ResourcesValidityState implements ValidityState { if (manifestFile != null) { myResourceTimestamps.put(manifestFile.getPath(), manifestFile.getTimeStamp()); } - VirtualFile resourcesDir = AndroidAptCompiler.getResourceDirForApkCompiler(module, facet); + VirtualFile resourcesDir = getResourcesDir(module, facet); if (resourcesDir != null) { collectFiles(resourcesDir); } @@ -61,7 +62,7 @@ public class ResourcesValidityState implements ValidityState { if (depManifest != null) { myResourceTimestamps.put(depManifest.getPath(), depManifest.getTimeStamp()); } - VirtualFile depResDir = AndroidAptCompiler.getResourceDirForApkCompiler(depFacet.getModule(), depFacet); + VirtualFile depResDir = getResourcesDir(depFacet.getModule(), depFacet); if (depResDir != null) { collectFiles(depResDir); } @@ -72,6 +73,11 @@ public class ResourcesValidityState implements ValidityState { } } + @Nullable + protected VirtualFile getResourcesDir(Module module, AndroidFacet facet) { + return AndroidAptCompiler.getResourceDirForApkCompiler(module, facet); + } + private void collectFiles(VirtualFile resourcesDir) { for (VirtualFile child : resourcesDir.getChildren()) { if (child.isDirectory()) { diff --git a/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java b/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java index 6386895577b8..9f9b8145a864 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java +++ b/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidApkBuilder.java @@ -213,11 +213,11 @@ public class AndroidApkBuilder { private static void writeNativeLibraries(SignedJarBuilder builder, VirtualFile nativeLibsFolder, VirtualFile child) throws IOException { ArrayList list = new ArrayList(); - collectNativeLibraries(nativeLibsFolder, child, list); - String relativePath = VfsUtil.getRelativePath(child, nativeLibsFolder, File.separatorChar); - String libsDirPathInApk = FileUtil.toSystemIndependentName(SdkConstants.FD_APK_NATIVE_LIBS + File.separator + relativePath); + collectNativeLibraries(child, list); for (VirtualFile file : list) { - builder.writeFile(toIoFile(file), libsDirPathInApk); + String relativePath = VfsUtil.getRelativePath(file, nativeLibsFolder, File.separatorChar); + String path = FileUtil.toSystemIndependentName(SdkConstants.FD_APK_NATIVE_LIBS + File.separator + relativePath); + builder.writeFile(toIoFile(file), path); } } @@ -228,7 +228,7 @@ public class AndroidApkBuilder { return result; } - public static void collectNativeLibraries(@NotNull VirtualFile libsDir, @NotNull VirtualFile file, @NotNull List result) { + public static void collectNativeLibraries(@NotNull VirtualFile file, @NotNull List result) { if (!file.isDirectory()) { String ext = file.getExtension(); if (AndroidUtils.EXT_NATIVE_LIB.equalsIgnoreCase(ext)) { @@ -237,7 +237,7 @@ public class AndroidApkBuilder { } else if (JavaResourceFilter.checkFolderForPackaging(file.getName())) { for (VirtualFile child : file.getChildren()) { - collectNativeLibraries(libsDir, child, result); + collectNativeLibraries(child, result); } } } diff --git a/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidDx.java b/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidDx.java index a756f66f74a7..d914da45490d 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidDx.java +++ b/plugins/android/src/org/jetbrains/android/compiler/tools/AndroidDx.java @@ -18,6 +18,7 @@ package org.jetbrains.android.compiler.tools; import com.android.sdklib.IAndroidTarget; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.CommandLineBuilder; +import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.configurations.JavaParameters; import com.intellij.execution.configurations.ParametersList; import com.intellij.execution.process.OSProcessHandler; @@ -74,13 +75,16 @@ public final class AndroidDx { parameters.setMainClass(DEX_MAIN); ParametersList params = parameters.getProgramParametersList(); //params.add("--verbose"); + params.add("--no-strict"); params.add("--output=" + outFile); params.addAll(compileTargets); parameters.getVMParametersList().add("-Xmx1024M"); parameters.getClassPath().add(dxJar); Process process = null; try { - process = CommandLineBuilder.createFromJavaParameters(parameters, true).createProcess(); + GeneralCommandLine commandLine = CommandLineBuilder.createFromJavaParameters(parameters, true); + LOG.info(commandLine.getCommandLineString()); + process = commandLine.createProcess(); } catch (ExecutionException e) { messages.get(CompilerMessageCategory.ERROR).add("ExecutionException: " + e.getMessage()); diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java index 9a7538944e0e..b8b69ad35f72 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java @@ -44,6 +44,7 @@ import gnu.trove.TIntHashSet; import org.jetbrains.android.compiler.AndroidAptCompiler; import org.jetbrains.android.compiler.AndroidCompileUtil; import org.jetbrains.android.compiler.AndroidIdlCompiler; +import org.jetbrains.android.maven.AndroidMavenProvider; import org.jetbrains.android.maven.AndroidMavenUtil; import org.jetbrains.android.sdk.AndroidPlatform; import org.jetbrains.android.sdk.AndroidPlatformChooser; @@ -147,7 +148,15 @@ public class AndroidFacetEditorTab extends FacetEditorTab { myResetPathsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - resetOptions(new AndroidFacetConfiguration()); + AndroidFacetConfiguration configuration = new AndroidFacetConfiguration(); + Module module = myContext.getModule(); + if (AndroidMavenUtil.isMavenizedModule(module)) { + AndroidMavenProvider mavenProvider = AndroidMavenUtil.getMavenProvider(); + if (mavenProvider != null) { + mavenProvider.setPathsToDefault(module, configuration); + } + } + resetOptions(configuration); } }); diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java index ea7572c95175..62dcd9f1128e 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidRootUtil.java @@ -29,10 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** @@ -136,7 +133,10 @@ public class AndroidRootUtil { return getFileByRelativeModulePath(module, '/' + SdkConstants.FD_GEN_SOURCES, false); } - public static void fillExternalLibrariesAndModules(final Module module, final Set result, final Library platformLibrary) { + private static void fillExternalLibrariesAndModules(final Module module, + final Set outputDirs, + @Nullable final Collection libraries, + final Library platformLibrary) { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { ModuleRootManager manager = ModuleRootManager.getInstance(module); @@ -144,18 +144,19 @@ public class AndroidRootUtil { if (!(entry instanceof ExportableOrderEntry) || ((ExportableOrderEntry)entry).getScope() != DependencyScope.COMPILE) { continue; } - if (entry instanceof LibraryOrderEntry) { + if (libraries != null && entry instanceof LibraryOrderEntry) { Library library = ((LibraryOrderEntry)entry).getLibrary(); + assert platformLibrary != null; if (!platformLibrary.equals(library)) { if (library != null) { for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) { if (file.exists()) { if (file.getFileSystem() instanceof JarFileSystem) { VirtualFile localFile = JarFileSystem.getInstance().getVirtualFileForJar(file); - if (localFile != null) result.add(localFile); + if (localFile != null) libraries.add(localFile); } else { - result.add(file); + libraries.add(file); } } } @@ -168,17 +169,17 @@ public class AndroidRootUtil { if (extension != null) { VirtualFile classDir = extension.getCompilerOutputPath(); boolean added = false; - if (!result.contains(classDir) && classDir != null && classDir.exists()) { - result.add(classDir); + if (!outputDirs.contains(classDir) && classDir != null && classDir.exists()) { + outputDirs.add(classDir); added = true; } VirtualFile classDirForTests = extension.getCompilerOutputPathForTests(); - if (!result.contains(classDirForTests) && classDirForTests != null && classDirForTests.exists()) { - result.add(classDirForTests); + if (!outputDirs.contains(classDirForTests) && classDirForTests != null && classDirForTests.exists()) { + outputDirs.add(classDirForTests); added = true; } if (added) { - fillExternalLibrariesAndModules(module, result, platformLibrary); + fillExternalLibrariesAndModules(module, outputDirs, libraries, platformLibrary); } } } @@ -188,16 +189,24 @@ public class AndroidRootUtil { } @NotNull - public static Set getExternalLibrariesAndModules(Module module, VirtualFile moduleOutputDir, Library platformLibrary) { + public static List getExternalLibraries(Module module, Library platformLibrary) { Set files = new HashSet(); - fillExternalLibrariesAndModules(module, files, platformLibrary); + List libs = new ArrayList(); + fillExternalLibrariesAndModules(module, files, libs, platformLibrary); + return libs; + } + + @NotNull + public static Set getDependentModules(Module module, VirtualFile moduleOutputDir) { + Set files = new HashSet(); + fillExternalLibrariesAndModules(module, files, null, null); files.remove(moduleOutputDir); return files; } @NotNull public static VirtualFile[] getResourceOverlayDirs(Module module) { - AndroidFacet facet = AndroidFacet.getInstance(module); + AndroidFacet facet = AndroidFacet.getInstance(module); if (facet == null) { return VirtualFile.EMPTY_ARRAY; } diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java index b25e0379d24d..fce124738c9c 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidFacetImporter.java @@ -16,7 +16,6 @@ package org.jetbrains.android.maven; import com.android.sdklib.IAndroidTarget; -import com.android.sdklib.SdkConstants; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.libraries.Library; @@ -72,7 +71,8 @@ public class AndroidFacetImporter extends FacetImporter dirs = new ArrayList(); - for (Object child : resourceOverlayDirectories.getChildren()) { - String dir = ((Element)child).getTextTrim(); - if (dir != null && dir.length() > 0) { - String relativePath = getRelativePath(moduleDirPath, makePath(project, dir)); - if (relativePath != null && relativePath.length() > 0) { - dirs.add('/' + relativePath); - } + Element resourceOverlayDirectories = getConfig(project, "resourceOverlayDirectories"); + if (resourceOverlayDirectories != null) { + List dirs = new ArrayList(); + for (Object child : resourceOverlayDirectories.getChildren()) { + String dir = ((Element)child).getTextTrim(); + if (dir != null && dir.length() > 0) { + String relativePath = getRelativePath(moduleDirPath, makePath(project, dir)); + if (relativePath != null && relativePath.length() > 0) { + dirs.add('/' + relativePath); } } - if (dirs.size() > 0) { - configuration.RES_OVERLAY_FOLDERS = ArrayUtil.toStringArray(dirs); - } } - else { - String resOverlayFolderRelPath = getPathFromConfig(project, moduleDirPath, "resourceOverlayDirectory"); - if (resOverlayFolderRelPath != null) { - configuration.RES_OVERLAY_FOLDERS = new String[]{'/' + resOverlayFolderRelPath}; - } + if (dirs.size() > 0) { + configuration.RES_OVERLAY_FOLDERS = ArrayUtil.toStringArray(dirs); } + } + else { + String resOverlayFolderRelPath = getPathFromConfig(project, moduleDirPath, "resourceOverlayDirectory"); + if (resOverlayFolderRelPath != null) { + configuration.RES_OVERLAY_FOLDERS = new String[]{'/' + resOverlayFolderRelPath}; + } + } - String assetsFolderRelPath = getPathFromConfig(project, moduleDirPath, "assetsDirectory"); - if (assetsFolderRelPath != null) { - configuration.ASSETS_FOLDER_RELATIVE_PATH = '/' + assetsFolderRelPath; - } + String assetsFolderRelPath = getPathFromConfig(project, moduleDirPath, "assetsDirectory"); + if (assetsFolderRelPath != null) { + configuration.ASSETS_FOLDER_RELATIVE_PATH = '/' + assetsFolderRelPath; + } - String manifestFileRelPath = getPathFromConfig(project, moduleDirPath, "androidManifestFile"); - if (manifestFileRelPath != null) { - configuration.MANIFEST_FILE_RELATIVE_PATH = '/' + manifestFileRelPath; - } + String manifestFileRelPath = getPathFromConfig(project, moduleDirPath, "androidManifestFile"); + if (manifestFileRelPath != null) { + configuration.MANIFEST_FILE_RELATIVE_PATH = '/' + manifestFileRelPath; + } - String nativeLibsFolderRelPath = getPathFromConfig(project, moduleDirPath, "nativeLibrariesDirectory"); - if (nativeLibsFolderRelPath != null) { - configuration.LIBS_FOLDER_RELATIVE_PATH = '/' + nativeLibsFolderRelPath; - } + String nativeLibsFolderRelPath = getPathFromConfig(project, moduleDirPath, "nativeLibrariesDirectory"); + if (nativeLibsFolderRelPath != null) { + configuration.LIBS_FOLDER_RELATIVE_PATH = '/' + nativeLibsFolderRelPath; } } diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProvider.java b/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProvider.java index 65139d0fb4db..27e198bcabdb 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProvider.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProvider.java @@ -17,6 +17,7 @@ package org.jetbrains.android.maven; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.module.Module; +import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -32,4 +33,6 @@ public interface AndroidMavenProvider { @NotNull List getMavenDependencyArtifactFiles(@NotNull Module module); + + void setPathsToDefault(@NotNull Module module, AndroidFacetConfiguration facetConfiguration); } diff --git a/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProviderImpl.java b/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProviderImpl.java index ff3ebddd5e30..7af72f7490eb 100644 --- a/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProviderImpl.java +++ b/plugins/android/src/org/jetbrains/android/maven/AndroidMavenProviderImpl.java @@ -15,7 +15,11 @@ */ package org.jetbrains.android.maven; +import com.android.sdklib.SdkConstants; import com.intellij.openapi.module.Module; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VfsUtil; +import org.jetbrains.android.facet.AndroidFacetConfiguration; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.maven.model.MavenArtifact; import org.jetbrains.idea.maven.project.MavenProject; @@ -31,6 +35,25 @@ import java.util.List; */ public class AndroidMavenProviderImpl implements AndroidMavenProvider { + public static void setPathsToDefault(MavenProject mavenProject, Module module, AndroidFacetConfiguration configuration) { + String moduleDirPath = FileUtil.toSystemIndependentName(new File(module.getModuleFilePath()).getParent()); + String genSources = FileUtil.toSystemIndependentName(mavenProject.getGeneratedSourcesDirectory(false)); + + if (VfsUtil.isAncestor(new File(moduleDirPath), new File(genSources), true)) { + String genRelativePath = FileUtil.getRelativePath(moduleDirPath, genSources, '/'); + if (genRelativePath != null) { + configuration.GEN_FOLDER_RELATIVE_PATH_APT = '/' + genRelativePath + "/r"; + configuration.GEN_FOLDER_RELATIVE_PATH_AIDL = '/' + genRelativePath + "/aidl"; + + configuration.USE_CUSTOM_APK_RESOURCE_FOLDER = true; + configuration.CUSTOM_APK_RESOURCE_FOLDER = '/' + genRelativePath + "/combined-resources/" + SdkConstants.FD_RES; + } + } + + configuration.COPY_RESOURCES_FROM_ARTIFACTS = true; + configuration.ENABLE_AAPT_COMPILER = false; + } + @Override public boolean isMavenizedModule(@NotNull Module module) { MavenProjectsManager mavenProjectsManager = MavenProjectsManager.getInstance(module.getProject()); @@ -50,4 +73,12 @@ public class AndroidMavenProviderImpl implements AndroidMavenProvider { } return result; } + + @Override + public void setPathsToDefault(@NotNull Module module, AndroidFacetConfiguration facetConfiguration) { + MavenProject mavenProject = MavenProjectsManager.getInstance(module.getProject()).findProject(module); + if (mavenProject != null) { + setPathsToDefault(mavenProject, module, facetConfiguration); + } + } } diff --git a/plugins/android/testData/dom/manifest/tn3_after.xml b/plugins/android/testData/dom/manifest/tn3_after.xml index d64f167c2ed1..72d40f30b18e 100644 --- a/plugins/android/testData/dom/manifest/tn3_after.xml +++ b/plugins/android/testData/dom/manifest/tn3_after.xml @@ -1,5 +1,5 @@ - diff --git a/plugins/android/testData/dom/manifest/tn4_after.xml b/plugins/android/testData/dom/manifest/tn4_after.xml index ca81825c1a8a..4c2047be5614 100644 --- a/plugins/android/testData/dom/manifest/tn4_after.xml +++ b/plugins/android/testData/dom/manifest/tn4_after.xml @@ -3,7 +3,7 @@ package="p1.a"> - diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/PathUtilEx.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/PathUtilEx.java index 163d9bd59488..6b901a54371b 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/execution/PathUtilEx.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/PathUtilEx.java @@ -75,7 +75,7 @@ public class PathUtilEx { } public static Sdk chooseJdk(Project project, Collection modules) { - Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectJdk(); + Sdk projectJdk = ProjectRootManager.getInstance(project).getProjectSdk(); if (projectJdk != null) { return projectJdk; } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java index 40be821385cf..789e548f7743 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntConfigurationImpl.java @@ -94,7 +94,7 @@ public class AntConfigurationImpl extends AntConfigurationBase implements Persis public String get(final AbstractPropertyContainer container) { if (!container.hasProperty(this)) return null; AntConfiguration antConfiguration = AntConfigurationImpl.INSTANCE.get(container); - return ProjectRootManager.getInstance(antConfiguration.getProject()).getProjectJdkName(); + return ProjectRootManager.getInstance(antConfiguration.getProject()).getProjectSdkName(); } public String copy(final String jdkName) { diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java index e2cf4a1f6e3f..0939e404de2f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomProject.java @@ -168,7 +168,7 @@ public abstract class AntDomProject extends AntDomNamedElement implements Proper return ProjectJdkTable.getInstance().findJdk(jdkName); } } - return ProjectRootManager.getInstance(tag.getProject()).getProjectJdk(); + return ProjectRootManager.getInstance(tag.getProject()).getProjectSdk(); } @NotNull diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java b/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java index 8bf4aa8f39b4..71194132edf6 100644 --- a/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java +++ b/plugins/ant/src/com/intellij/lang/ant/dom/CustomAntElementsRegistry.java @@ -283,21 +283,21 @@ public class CustomAntElementsRegistry { clazz = loader.loadClass(classname); } catch (ClassNotFoundException e) { - error = e.getMessage(); + error = "Class not found " + e.getMessage(); if (error == null) { error = ""; } clazz = null; } catch (NoClassDefFoundError e) { - error = e.getMessage(); + error = "Class definition not found " + e.getMessage(); if (error == null) { error = ""; } clazz = null; } catch (UnsupportedClassVersionError e) { - error = e.getMessage(); + error = "Unsupported class version " + e.getMessage(); if (error == null) { error = ""; } @@ -309,7 +309,7 @@ public class CustomAntElementsRegistry { private void addCustomDefinition(@NotNull AntDomNamedElement declaringTag, String customTagName, String nsUri, Class clazz, String error) { final XmlName xmlName = new XmlName(customTagName, nsUri == null? "" : nsUri); if (error != null) { - myErrors.put(xmlName, customTagName); + myErrors.put(xmlName, error); } myCustomElements.put(xmlName, clazz); myDeclarations.put(xmlName, declaringTag); diff --git a/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntFileImpl.java b/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntFileImpl.java index f0d1f9e7df88..c0ccc59e54b0 100644 --- a/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntFileImpl.java +++ b/plugins/ant/src/com/intellij/lang/ant/psi/impl/AntFileImpl.java @@ -346,7 +346,7 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile { public Sdk getTargetJdk() { final AntBuildFileImpl buildFile = (AntBuildFileImpl)getSourceElement().getCopyableUserData(AntBuildFile.ANT_BUILD_FILE_KEY); if (buildFile == null) { - return ProjectRootManager.getInstance(getProject()).getProjectJdk(); + return ProjectRootManager.getInstance(getProject()).getProjectSdk(); } String jdkName = AntBuildFileImpl.CUSTOM_JDK_NAME.get(buildFile.getAllOptions()); @@ -356,7 +356,7 @@ public class AntFileImpl extends LightPsiFileBase implements AntFile { if (jdkName != null && jdkName.length() > 0) { return ProjectJdkTable.getInstance().findJdk(jdkName); } - return ProjectRootManager.getInstance(getProject()).getProjectJdk(); + return ProjectRootManager.getInstance(getProject()).getProjectSdk(); } @Nullable diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml index 978e99d85bbb..3c92960dc36c 100644 --- a/plugins/git4idea/src/META-INF/plugin.xml +++ b/plugins/git4idea/src/META-INF/plugin.xml @@ -101,6 +101,9 @@ + @@ -113,6 +116,7 @@ + diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 5e2d107c71f9..70761bcdd287 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -54,9 +54,7 @@ import git4idea.checkin.GitCommitAndPushExecutor; import git4idea.checkout.branches.GitBranchConfigurations; import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; -import git4idea.config.GitVcsConfigurable; -import git4idea.config.GitVcsSettings; -import git4idea.config.GitVersion; +import git4idea.config.*; import git4idea.diff.GitDiffProvider; import git4idea.diff.GitTreeDiffProvider; import git4idea.history.GitHistoryProvider; @@ -83,6 +81,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; * Git VCS implementation */ public class GitVcs extends AbstractVcs { + public static final String NOTIFICATION_GROUP_ID = "Git"; /** * the logger */ @@ -130,7 +129,7 @@ public class GitVcs extends AbstractVcs { /** * project vcs settings */ - private final GitVcsSettings mySettings; + private final GitVcsApplicationSettings myAppSettings; /** * configuration support */ @@ -211,6 +210,7 @@ public class GitVcs extends AbstractVcs { * If true, the vcs was activated */ private boolean isActivated; + private final GitVcsSettings myProjectSettings; public static GitVcs getInstance(@NotNull Project project) { @@ -225,10 +225,12 @@ public class GitVcs extends AbstractVcs { @NotNull final GitDiffProvider gitDiffProvider, @NotNull final GitHistoryProvider gitHistoryProvider, @NotNull final GitRollbackEnvironment gitRollbackEnvironment, - @NotNull final GitVcsSettings gitSettings) { + @NotNull final GitVcsApplicationSettings gitSettings, + @NotNull final GitVcsSettings gitProjectSettings) { super(project, NAME); myVcsManager = gitVcsManager; - mySettings = gitSettings; + myAppSettings = gitSettings; + myProjectSettings = gitProjectSettings; myChangeProvider = gitChangeProvider; myCheckinEnvironment = gitCheckinEnvironment; myAnnotationProvider = gitAnnotationProvider; @@ -236,8 +238,8 @@ public class GitVcs extends AbstractVcs { myHistoryProvider = gitHistoryProvider; myRollbackEnvironment = gitRollbackEnvironment; myRevSelector = new GitRevisionSelector(); - myConfigurable = new GitVcsConfigurable(mySettings, myProject); - myUpdateEnvironment = new GitUpdateEnvironment(myProject, this, mySettings); + myConfigurable = new GitVcsConfigurable(myProjectSettings, myProject); + myUpdateEnvironment = new GitUpdateEnvironment(myProject, this, myProjectSettings); myMergeProvider = new GitMergeProvider(myProject); myReverseMergeProvider = new GitMergeProvider(myProject, true); myCommittedChangeListProvider = new GitCommittedChangeListProvider(myProject); @@ -501,6 +503,7 @@ public class GitVcs extends AbstractVcs { @Override protected void activate() { isActivated = true; + GitExecutableValidator.getInstance(myProject).checkExecutableAndNotifyIfNeeded(); if (!myProject.isDefault() && myRootTracker == null) { myRootTracker = new GitRootTracker(this, myProject, myRootListeners.getMulticaster()); } @@ -603,8 +606,8 @@ public class GitVcs extends AbstractVcs { * @return vcs settings for the current project */ @NotNull - public GitVcsSettings getSettings() { - return mySettings; + public GitVcsApplicationSettings getAppSettings() { + return myAppSettings; } /** @@ -621,7 +624,7 @@ public class GitVcs extends AbstractVcs { * Check version and report problem */ public void checkVersion() { - final String executable = mySettings.getGitExecutable(); + final String executable = myAppSettings.getPathToGit(); synchronized (myCheckingVersion) { if (myVersion != null && myVersionCheckExcecutable.equals(executable)) { return; diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java b/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java index 6108dbdf5ca6..bc248770abc2 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeProvider.java @@ -26,6 +26,7 @@ import git4idea.GitContentRevision; import git4idea.GitRevisionNumber; import git4idea.GitUtil; import git4idea.GitVcs; +import git4idea.config.GitExecutableValidator; import org.jetbrains.annotations.NotNull; import java.util.Collection; @@ -63,20 +64,23 @@ public class GitChangeProvider implements ChangeProvider { } Collection roots = GitUtil.gitRootsForPaths(affected); - final MyNonChangedHolder holder = new MyNonChangedHolder(myProject, dirtyScope.getDirtyFilesNoExpand(), addGate); - - for (VirtualFile root : roots) { - ChangeCollector c = new ChangeCollector(myProject, dirtyScope, root); - final Collection changes = c.changes(); - holder.changed(changes); - for (Change file : changes) { - builder.processChange(file, GitVcs.getKey()); + try { + final MyNonChangedHolder holder = new MyNonChangedHolder(myProject, dirtyScope.getDirtyFilesNoExpand(), addGate); + for (VirtualFile root : roots) { + ChangeCollector c = new ChangeCollector(myProject, dirtyScope, root); + final Collection changes = c.changes(); + holder.changed(changes); + for (Change file : changes) { + builder.processChange(file, GitVcs.getKey()); + } + for (VirtualFile f : c.unversioned()) { + builder.processUnversionedFile(f); + holder.unversioned(f); + } + holder.feedBuilder(builder); } - for (VirtualFile f : c.unversioned()) { - builder.processUnversionedFile(f); - holder.unversioned(f); - } - holder.feedBuilder(builder); + } catch (VcsException e) {// most probably the error happened because git is not configured + GitExecutableValidator.getInstance(myProject).showNotificationOrThrow(e); } } diff --git a/plugins/git4idea/src/git4idea/checkout/branches/GitBranchConfigurations.java b/plugins/git4idea/src/git4idea/checkout/branches/GitBranchConfigurations.java index 5d4dd5e90a00..1c6ff2091935 100644 --- a/plugins/git4idea/src/git4idea/checkout/branches/GitBranchConfigurations.java +++ b/plugins/git4idea/src/git4idea/checkout/branches/GitBranchConfigurations.java @@ -22,6 +22,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -266,9 +267,9 @@ public class GitBranchConfigurations implements PersistentStateComponent currents = new HashMap(); + final HashMap rootToCurrentBranch = new HashMap(); for (VirtualFile root : myGitRoots) { GitBranch current = GitBranch.current(myProject, root); - currents.put(root, current == null ? "" : current.getName()); + rootToCurrentBranch.put(root, current == null ? "" : current.getName()); } + if (myConfigurations.isEmpty()) { detectLocalConfigurations(true); - for (GitBranchConfiguration configuration : myConfigurations.values()) { - boolean currentsMatched = true; - for (VirtualFile root : myGitRoots) { - currentsMatched &= currents.get(root).equals(configuration.getReference(root.getPath())); - } - if (currentsMatched) { - myCurrentConfiguration = configuration; - break; - } - } + updateCurrentConfiguration(rootToCurrentBranch); if (myCurrentConfiguration == null) { // the configuration does not matches any standard, there could be no configurations with spaces at this point // since it is not allowed branch name. @@ -539,12 +532,32 @@ public class GitBranchConfigurations implements PersistentStateComponent rootToCurrentBranch) { + for (GitBranchConfiguration configuration : myConfigurations.values()) { + boolean currentsMatched = true; + for (VirtualFile root : myGitRoots) { + currentsMatched &= rootToCurrentBranch.get(root).equals(configuration.getReference(root.getPath())); + } + if (currentsMatched) { + myCurrentConfiguration = configuration; + break; + } + } + } + /** * Detect local configurations * diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index bed5e5d12974..9e39a986c89b 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -27,6 +27,7 @@ import com.intellij.util.EventDispatcher; import com.intellij.util.Processor; import git4idea.GitUtil; import git4idea.GitVcs; +import git4idea.config.GitVcsApplicationSettings; import git4idea.config.GitVcsSettings; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -42,104 +43,50 @@ import java.util.*; * A handler for git commands */ public abstract class GitHandler { - /** - * Error codes that are ignored for the handler - */ - private final HashSet myIgnoredErrorCodes = new HashSet(); - /** - * Error list - */ - private final List myErrors = Collections.synchronizedList(new LinkedList()); - /** - * the logger - */ - private static final Logger log = Logger.getInstance(GitHandler.class.getName()); - /** - * a command line - */ - final GeneralCommandLine myCommandLine; - /** - * process - */ - @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) Process myProcess; - /** - * If true, the standard output is not copied to version control console - */ - private boolean myStdoutSuppressed; - /** - * If true, the standard error is not copied to version control console - */ - private boolean myStderrSuppressed; - /** - * the context project (might be a default project) - */ - final Project myProject; - /** - * The descriptor for the command to be executed - */ - protected final GitCommand myCommand; - /** - * the working directory - */ - private final File myWorkingDirectory; - /** - * the flag indicating that environment has been cleaned up, by default is true because there is nothing to clean - */ - private boolean myEnvironmentCleanedUp = true; - /** - * the handler number - */ - private int myHandlerNo; - /** - * The processor for stdin - */ - private Processor myInputProcessor; - /** - * if true process might be cancelled - */ - // note that access is safe because it accessed in unsynchronized block only after process is started, and it does not change after that - @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private boolean myIsCancellable = true; - /** - * exit code or null if exit code is not yet available - */ - private Integer myExitCode; - /** - * Character set to use for IO - */ - @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) @NonNls private Charset myCharset = Charset.forName("UTF-8"); - /** - * No ssh flag - */ - @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private boolean myNoSSHFlag = false; - /** - * listeners - */ - private final EventDispatcher myListeners = EventDispatcher.create(GitHandlerListener.class); - /** - * if true, the command execution is not logged in version control view - */ - @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private boolean mySilent; - /** - * The vcs object - */ + protected final Project myProject; + protected final GitCommand myCommand; + + private final HashSet myIgnoredErrorCodes = new HashSet(); // Error codes that are ignored for the handler + private final List myErrors = Collections.synchronizedList(new LinkedList()); + private static final Logger log = Logger.getInstance(GitHandler.class.getName()); + final GeneralCommandLine myCommandLine; + @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) + Process myProcess; + + private boolean myStdoutSuppressed; // If true, the standard output is not copied to version control console + private boolean myStderrSuppressed; // If true, the standard error is not copied to version control console + private final File myWorkingDirectory; + + private boolean myEnvironmentCleanedUp = true; // the flag indicating that environment has been cleaned up, by default is true because there is nothing to clean + private int myHandlerNo; + private Processor myInputProcessor; // The processor for stdin + + // if true process might be cancelled + // note that access is safe because it accessed in unsynchronized block only after process is started, and it does not change after that + @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) + private boolean myIsCancellable = true; + + private Integer myExitCode; // exit code or null if exit code is not yet available + + @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) + @NonNls + private Charset myCharset = Charset.forName("UTF-8"); // Character set to use for IO + + @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) + private boolean myNoSSHFlag = false; + + private final EventDispatcher myListeners = EventDispatcher.create(GitHandlerListener.class); + @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) + private boolean mySilent; // if true, the command execution is not logged in version control view + protected final GitVcs myVcs; - /** - * The environment - */ private final Map myEnv; - /** - * The settings object - */ - private GitVcsSettings mySettings; - /** - * Suspend action used by {@link #suspendWriteLock()} - */ - private Runnable mySuspendAction; - /** - * Resume action used by {@link #resumeWriteLock()} - */ - private Runnable myResumeAction; + private GitVcsApplicationSettings myAppSettings; + private GitVcsSettings myProjectSettings; + + private Runnable mySuspendAction; // Suspend action used by {@link #suspendWriteLock()} + private Runnable myResumeAction; // Resume action used by {@link #resumeWriteLock()} /** @@ -152,7 +99,8 @@ public abstract class GitHandler { protected GitHandler(@NotNull Project project, @NotNull File directory, @NotNull GitCommand command) { myProject = project; myCommand = command; - mySettings = GitVcsSettings.getInstance(project); + myAppSettings = GitVcsApplicationSettings.getInstance(); + myProjectSettings = GitVcsSettings.getInstance(myProject); myEnv = new HashMap(System.getenv()); if (!myEnv.containsKey("HOME")) { String home = System.getProperty("user.home"); @@ -166,8 +114,8 @@ public abstract class GitHandler { } myWorkingDirectory = directory; myCommandLine = new GeneralCommandLine(); - if (mySettings != null) { - myCommandLine.setExePath(mySettings.getGitExecutable()); + if (myAppSettings != null) { + myCommandLine.setExePath(myAppSettings.getPathToGit()); } myCommandLine.setWorkingDirectory(myWorkingDirectory); if (command.name().length() > 0) { @@ -422,7 +370,7 @@ public abstract class GitHandler { if (log.isDebugEnabled()) { log.debug("running git: " + myCommandLine.getCommandLineString() + " in " + myWorkingDirectory); } - if (!myNoSSHFlag && mySettings.isIdeaSsh()) { + if (!myNoSSHFlag && myProjectSettings.isIdeaSsh()) { GitSSHService ssh = GitSSHIdeaService.getInstance(); myEnv.put(GitSSHHandler.GIT_SSH_ENV, ssh.getScriptPath().getPath()); myHandlerNo = ssh.registerHandler(new GitSSHGUIHandler(myProject)); diff --git a/plugins/git4idea/src/git4idea/config/GitExecutableValidator.java b/plugins/git4idea/src/git4idea/config/GitExecutableValidator.java new file mode 100644 index 000000000000..a60afbb92fe1 --- /dev/null +++ b/plugins/git4idea/src/git4idea/config/GitExecutableValidator.java @@ -0,0 +1,120 @@ +/* + * 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 git4idea.config; + +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.ui.GuiUtils; +import com.intellij.util.ui.UIUtil; +import git4idea.GitVcs; +import git4idea.i18n.GitBundle; +import org.jetbrains.annotations.NotNull; + +import javax.swing.event.HyperlinkEvent; + +/** + * Project service that is used to check whether currently set git executable is valid (just calls 'git version' and parses the output), + * and to display notification to the user proposing to fix the project set up. + * @author Kirill Likhodedov + */ +public class GitExecutableValidator { + + private Notification myNotification; + private final Project myProject; + + public static GitExecutableValidator getInstance(Project project) { + return ServiceManager.getService(project, GitExecutableValidator.class); + } + + public GitExecutableValidator(Project project) { + myProject = project; + } + + /** + * Returns true if 'git version' command was executed without errors and outputted a valid Git version information. + */ + public boolean isGitExecutableValid() { + try { + GitVcs.version(myProject); + return true; + } catch (VcsException e) { + return false; + } + } + + /** + * Shows notification that git is not configured with a link to the Settings to fix it. + * Expires the notification if user fixes the path to Git from the opened Settings dialog. + */ + public void showExecutableNotConfiguredNotification() { + final Notification newNotification = new Notification(GitVcs.NOTIFICATION_GROUP_ID, GitBundle.getString("executable.error.title"), + GitBundle.getString("executable.error.description"), NotificationType.ERROR, + new NotificationListener() { + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + ShowSettingsUtil.getInstance().showSettingsDialog(myProject, GitVcs.getInstance(myProject).getConfigurable()); + if (isGitExecutableValid()) { + notification.expire(); + } + } + }); + + // expire() needs to be called from EventDispatch thread. notify handles it by itself. + // but we want to be sure that previous notification expires before new one is shown (and assigned to myNotification). + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override public void run() { + if (myNotification != null && !myNotification.isExpired()) { + // don't display this notification twice, but better to redisplay it again so that popup appears. + myNotification.expire(); + } + myNotification = newNotification; + Notifications.Bus.notify(myNotification, myProject); + } + }); + } + + /** + * Checks if git executable is valid and displays the notification if not. + */ + public void checkExecutableAndNotifyIfNeeded() { + if (!isGitExecutableValid()) { + showExecutableNotConfiguredNotification(); + } + } + + /** + * Checks if git executable is valid. If not (which is a common case for low-level vcs exceptions), shows the + * notification. Otherwise throws the exception. + * This is to be used in catch-clauses + * @param e exception which was thrown. + * @throws VcsException if git executable is valid. + */ + public void showNotificationOrThrow(VcsException e) throws VcsException { + if (!isGitExecutableValid()) { + showExecutableNotConfiguredNotification(); + } else { + throw e; + } + } + +} diff --git a/plugins/git4idea/src/git4idea/config/GitVcsApplicationSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsApplicationSettings.java index 6935852252b9..38af49516670 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsApplicationSettings.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsApplicationSettings.java @@ -16,6 +16,7 @@ package git4idea.config; import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.util.SystemInfo; @@ -54,6 +55,10 @@ public class GitVcsApplicationSettings implements PersistentStateComponent

- + diff --git a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java index 6bf864833fa6..7e7d39b854e8 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsPanel.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsPanel.java @@ -34,58 +34,19 @@ import java.awt.event.ActionListener; * Git VCS configuration panel */ public class GitVcsPanel { - /** - * Test git executable button - */ - private JButton myTestButton; - /** - * The root panel - */ - private JComponent myPanel; - /** - * The git path field - */ + private JButton myTestButton; // Test git executable + private JComponent myRootPanel; private TextFieldWithBrowseButton myGitField; - /** - * Type of SSH executable to use - */ - private JComboBox mySSHExecutableComboBox; - /** - * The conversion policy - */ - private JComboBox myConvertTextFilesComboBox; - /** - * The confirmation checkbox - */ - private JCheckBox myAskBeforeConversionsCheckBox; - /** - * The if selected, the branches widget is enabled in the status bar - */ - private JCheckBox myEnableBranchesWidgetCheckBox; - /** - * The project - */ + private JComboBox mySSHExecutableComboBox; // Type of SSH executable to use + private JComboBox myConvertTextFilesComboBox; // The conversion policy + private JCheckBox myAskBeforeConversionsCheckBox; // The confirmation checkbox + private JCheckBox myEnableBranchesWidgetCheckBox; // if selected, the branches widget is enabled in the status bar private final Project myProject; - /** - * The settings component - */ - private final GitVcsSettings mySettings; - /** - * IDEA ssh value - */ - private static final String IDEA_SSH = - ApplicationNamesInfo.getInstance().getProductName() + " " + GitBundle.getString("git.vcs.config.ssh.mode.idea"); - /** - * Native SSH value - */ - private static final String NATIVE_SSH = GitBundle.getString("git.vcs.config.ssh.mode.native"); - /** - * IDEA ssh value - */ + private final GitVcsApplicationSettings myAppSettings; + private final GitVcsSettings myProjectSettings; + private static final String IDEA_SSH = ApplicationNamesInfo.getInstance().getProductName() + " " + GitBundle.getString("git.vcs.config.ssh.mode.idea"); // IDEA ssh value + private static final String NATIVE_SSH = GitBundle.getString("git.vcs.config.ssh.mode.native"); // Native SSH value private static final String CRLF_CONVERT_TO_PROJECT = GitBundle.getString("git.vcs.config.convert.project"); - /** - * Native SSH value - */ private static final String CRLF_DO_NOT_CONVERT = GitBundle.getString("git.vcs.config.convert.do.not.convert"); /** @@ -94,14 +55,15 @@ public class GitVcsPanel { * @param project the context project */ public GitVcsPanel(@NotNull Project project) { - mySettings = GitVcsSettings.getInstance(project); + myAppSettings = GitVcsApplicationSettings.getInstance(); + myProjectSettings = GitVcsSettings.getInstance(project); myProject = project; mySSHExecutableComboBox.addItem(IDEA_SSH); mySSHExecutableComboBox.addItem(NATIVE_SSH); mySSHExecutableComboBox.setSelectedItem(GitVcsSettings.isDefaultIdeaSsh() ? IDEA_SSH : NATIVE_SSH); mySSHExecutableComboBox .setToolTipText(GitBundle.message("git.vcs.config.ssh.mode.tooltip", ApplicationNamesInfo.getInstance().getFullProductName())); - myAskBeforeConversionsCheckBox.setSelected(mySettings.askBeforeLineSeparatorConversion()); + myAskBeforeConversionsCheckBox.setSelected(myProjectSettings.askBeforeLineSeparatorConversion()); myTestButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { testConnection(); @@ -119,8 +81,8 @@ public class GitVcsPanel { * Test availability of the connection */ private void testConnection() { - if (mySettings != null) { - mySettings.setGitExecutable(myGitField.getText()); + if (myAppSettings != null) { + myAppSettings.setPathToGit(myGitField.getText()); } final String s; try { @@ -143,7 +105,7 @@ public class GitVcsPanel { * @return the configuration panel */ public JComponent getPanel() { - return myPanel; + return myRootPanel; } /** @@ -152,7 +114,7 @@ public class GitVcsPanel { * @param settings the settings to load */ public void load(@NotNull GitVcsSettings settings) { - myGitField.setText(settings.getGitExecutable()); + myGitField.setText(settings.getAppSettings().getPathToGit()); mySSHExecutableComboBox.setSelectedItem(settings.isIdeaSsh() ? IDEA_SSH : NATIVE_SSH); myAskBeforeConversionsCheckBox.setSelected(settings.askBeforeLineSeparatorConversion()); myConvertTextFilesComboBox.setSelectedItem(crlfPolicyItem(settings)); @@ -187,7 +149,7 @@ public class GitVcsPanel { * @param settings the settings to load */ public boolean isModified(@NotNull GitVcsSettings settings) { - return !settings.getGitExecutable().equals(myGitField.getText()) || + return !settings.getAppSettings().getPathToGit().equals(myGitField.getText()) || (settings.isIdeaSsh() != IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem())) || !crlfPolicyItem(settings).equals(myConvertTextFilesComboBox.getSelectedItem()) || settings.askBeforeLineSeparatorConversion() != myAskBeforeConversionsCheckBox.isSelected() || @@ -200,7 +162,7 @@ public class GitVcsPanel { * @param settings the settings object */ public void save(@NotNull GitVcsSettings settings) { - settings.setGitExecutable(myGitField.getText()); + settings.getAppSettings().setPathToGit(myGitField.getText()); settings.setIdeaSsh(IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem())); Object policyItem = myConvertTextFilesComboBox.getSelectedItem(); GitVcsSettings.ConversionPolicy conversionPolicy; diff --git a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java index 1675509780f9..fa472c399aa7 100644 --- a/plugins/git4idea/src/git4idea/config/GitVcsSettings.java +++ b/plugins/git4idea/src/git4idea/config/GitVcsSettings.java @@ -36,63 +36,26 @@ import java.util.List; id = "ws", file = "$WORKSPACE_FILE$")}) public class GitVcsSettings implements PersistentStateComponent { - /** - * Default SSH policy - */ - private static final SshExecutable DEFAULT_SSH = SshExecutable.IDEA_SSH; - /** - * The git application settings - */ - private final GitVcsApplicationSettings myAppSettings; - /** - * The default executable for GIT - */ - private String myGitExecutable; - /** - * The previously entered authors of the commit (up to {@value #PREVIOUS_COMMIT_AUTHORS_LIMIT}) - */ - private List myCommitAuthors = new ArrayList(); - /** - * Limit for previous commit authors - */ - public static final int PREVIOUS_COMMIT_AUTHORS_LIMIT = 16; - /** - * Checkout includes tags - */ - private boolean myCheckoutIncludesTags = false; - /** - * IDEA SSH should be used instead of native SSH. - */ - private SshExecutable mySshExecutable = DEFAULT_SSH; - /** - * The policy that specifies how files are saved before update or rebase - */ - private UpdateChangesPolicy myUpdateChangesPolicy = UpdateChangesPolicy.STASH; - /** - * The type of update operation to perform - */ - private UpdateType myUpdateType = UpdateType.BRANCH_DEFAULT; - /** - * The crlf conversion policy - */ - private ConversionPolicy myLineSeparatorsConversion = ConversionPolicy.PROJECT_LINE_SEPARATORS; - /** - * If true, the dialog is shown with conversion options - */ - private boolean myAskBeforeLineSeparatorConversion = true; - /** - * The policy used in push active branches dialog - */ - private UpdateChangesPolicy myPushActiveBranchesRebaseSavePolicy = UpdateChangesPolicy.STASH; - /** - * The constructor - * - * @param appSettings the application settings instance - */ + public static final int PREVIOUS_COMMIT_AUTHORS_LIMIT = 16; // Limit for previous commit authors + private static final SshExecutable DEFAULT_SSH = SshExecutable.IDEA_SSH; // Default SSH policy + + private final GitVcsApplicationSettings myAppSettings; + private final List myCommitAuthors = new ArrayList(); // The previously entered authors of the commit (up to {@value #PREVIOUS_COMMIT_AUTHORS_LIMIT}) + private boolean myCheckoutIncludesTags = false; + private SshExecutable mySshExecutable = DEFAULT_SSH; // IDEA SSH should be used instead of native SSH. + private UpdateChangesPolicy myUpdateChangesPolicy = UpdateChangesPolicy.STASH; // The policy that specifies how files are saved before update or rebase + private UpdateType myUpdateType = UpdateType.BRANCH_DEFAULT; // The type of update operation to perform + private ConversionPolicy myLineSeparatorsConversion = ConversionPolicy.PROJECT_LINE_SEPARATORS; // The crlf conversion policy + private boolean myAskBeforeLineSeparatorConversion = true; // If true, the dialog is shown with conversion options + private UpdateChangesPolicy myPushActiveBranchesRebaseSavePolicy = UpdateChangesPolicy.STASH; // The policy used in push active branches dialog + public GitVcsSettings(GitVcsApplicationSettings appSettings) { myAppSettings = appSettings; - myGitExecutable = myAppSettings.defaultGit(); + } + + public GitVcsApplicationSettings getAppSettings() { + return myAppSettings; } /** @@ -177,24 +140,6 @@ public class GitVcsSettings implements PersistentStateComponent revisions = null; + try { + revisions = GitHistoryUtils.history(myProject, filePath); + } catch (VcsException e) { + GitExecutableValidator.getInstance(myProject).showNotificationOrThrow(e); } - List revisions = GitHistoryUtils.history(project, filePath); return createSession(filePath, revisions); } @@ -101,7 +104,7 @@ public class GitHistoryProvider implements VcsHistoryProvider { @Nullable protected VcsRevisionNumber calcCurrentRevisionNumber() { try { - return GitHistoryUtils.getCurrentRevision(project, GitHistoryUtils.getLastCommitName(project, filePath)); + return GitHistoryUtils.getCurrentRevision(myProject, GitHistoryUtils.getLastCommitName(myProject, filePath)); } catch (VcsException e) { // likely the file is not under VCS anymore. @@ -126,13 +129,18 @@ public class GitHistoryProvider implements VcsHistoryProvider { public void reportAppendableHistory(final FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException { final VcsAbstractHistorySession emptySession = createSession(path, Collections.emptyList()); partner.reportCreatedEmptySession(emptySession); - GitHistoryUtils.history(project, path, new Consumer() { + final GitExecutableValidator validator = GitExecutableValidator.getInstance(myProject); + GitHistoryUtils.history(myProject, path, new Consumer() { public void consume(GitFileRevision gitFileRevision) { partner.acceptRevision(gitFileRevision); } }, new Consumer() { public void consume(VcsException e) { - partner.reportException(e); + if (!validator.isGitExecutableValid()) { + validator.showExecutableNotConfiguredNotification(); + } else { + partner.reportException(e); + } } }); } @@ -141,6 +149,6 @@ public class GitHistoryProvider implements VcsHistoryProvider { * {@inheritDoc} */ public boolean supportsHistoryForDirectories() { - return false; + return true; } } diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 02453e91c050..2dfe0f0b9692 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -166,6 +166,7 @@ public class GitHistoryUtils { public void startFailed(Throwable exception) { //noinspection ThrowableInstanceNeverThrown exceptionConsumer.consume(new VcsException(exception)); + semaphore.up(); } @Override diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties index 42933bdec957..5595ffce9c40 100644 --- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties +++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties @@ -472,3 +472,7 @@ vfs.listener.checking.ignored=Checking for ignored files vfs.listener.delete.single.prompt=Do you want to delete the following file from Git?\n{0}\n\nIf you say NO, you can still delete it later manually. vfs.listener.delete.single.title=Delete file from Git vfs.listener.delete.title=Delete files from Git + +general.error = Git error +executable.error.title = Git executable problem +executable.error.description = Git couldn't be started. Probably the path to Git executable is not valid. Fix it. \ No newline at end of file diff --git a/plugins/git4idea/src/git4idea/ui/GitUIUtil.java b/plugins/git4idea/src/git4idea/ui/GitUIUtil.java index b12a98295cd5..3fea717099a0 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUIUtil.java +++ b/plugins/git4idea/src/git4idea/ui/GitUIUtil.java @@ -15,6 +15,11 @@ */ package git4idea.ui; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vcs.AbstractVcsHelper; @@ -24,12 +29,15 @@ import git4idea.GitBranch; import git4idea.GitRemote; import git4idea.GitVcs; import git4idea.config.GitConfigUtil; +import git4idea.config.GitExecutableValidator; +import git4idea.config.GitVcsConfigurable; import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.HyperlinkEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -402,4 +410,18 @@ public class GitUIUtil { checked.addActionListener(l); l.actionPerformed(null); } + + /** + * Handles a low-level Git execution exception. + * Checks that Git executable is valid. If it is not, then shows proper notification with an option to fix the path to Git. + * If it's valid, then we don't know what could happen and just display the general error notification. + */ + public static void checkGitExecutableAndShowNotification(final Project project, VcsException e) { + if (GitExecutableValidator.getInstance(project).isGitExecutableValid()) { + Notification notification = new Notification(GitVcs.NOTIFICATION_GROUP_ID, GitBundle.getString("general.error"), e.getLocalizedMessage(), NotificationType.ERROR); + Notifications.Bus.notify(notification, project); + } else { + GitExecutableValidator.getInstance(project).showExecutableNotConfiguredNotification(); + } + } } diff --git a/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java b/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java index 38cb8c9df5f0..8ceb2f769fda 100644 --- a/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java +++ b/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java @@ -213,7 +213,7 @@ public class GitIgnoreTracker { return String.valueOf(file.charAt(1)) + ":" + file.substring(2); } // otherwise the path is relative to "bin/git.exe" - File gitDir = new File(myVcs.getSettings().getGitExecutable()).getParentFile(); + File gitDir = new File(myVcs.getAppSettings().getPathToGit()).getParentFile(); if (gitDir != null) { gitDir = gitDir.getParentFile(); } diff --git a/plugins/groovy/resources/standardDsls/defaultArithmeticOperations.gdsl b/plugins/groovy/resources/standardDsls/defaultArithmeticOperations.gdsl index 1f31af2bc145..0440383bdf52 100644 --- a/plugins/groovy/resources/standardDsls/defaultArithmeticOperations.gdsl +++ b/plugins/groovy/resources/standardDsls/defaultArithmeticOperations.gdsl @@ -20,6 +20,7 @@ package standardDsls */ final String NUMBER = "java.lang.Number" +final String STRING = "java.lang.String" contributor(ctype:NUMBER) { method name: "plus", type: NUMBER, params:[arg:NUMBER] method name: "minus", type: NUMBER, params:[arg:NUMBER] @@ -34,4 +35,6 @@ contributor(ctype:NUMBER) { method name: "previous", type: psiType.canonicalText method name: "negative", type: psiType.canonicalText method name: "positive", type: psiType.canonicalText + + method name: "plus", type: STRING, params:[arg:STRING] } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/ClassContextFilter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/ClassContextFilter.java index af3d2f6d6138..9c67f2d0e1f1 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/ClassContextFilter.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/toplevel/ClassContextFilter.java @@ -10,7 +10,7 @@ import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; import com.intellij.util.ProcessingContext; -import com.intellij.util.containers.hash.HashMap; +import com.intellij.util.containers.ConcurrentHashMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.dsl.GroovyClassDescriptor; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -76,11 +76,11 @@ public class ClassContextFilter implements ContextFilter { private static PsiType getCachedType(String typeText, PsiFile context) { Map map = context.getUserData(CACHED_TYPES); if (map == null) { - map = new HashMap(); + map = new ConcurrentHashMap(); context.putUserData(CACHED_TYPES, map); } PsiType type = map.get(typeText); - if (type == null) { + if (type == null || !type.isValid()) { type = JavaPsiFacade.getElementFactory(context.getProject()).createTypeFromText(typeText, context); map.put(typeText, type); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index fa3e9b193166..88c645aacb77 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.InheritanceUtil; @@ -76,17 +77,7 @@ public class TypesUtil { return JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory().createTypeByFQClassName(qName, scope); } - final PsiType type = getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{rType}); - if (type != null) { - return type; - } - - if (typeEqualsToText(rType, GrStringUtil.GROOVY_LANG_GSTRING)) { - PsiType gstringType = JavaPsiFacade.getInstance(binaryExpression.getProject()).getElementFactory() - .createTypeByFQClassName(GrStringUtil.GROOVY_LANG_GSTRING, binaryExpression.getResolveScope()); - return getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{gstringType}); - } - return null; + return getOverloadedOperatorType(lType, binaryExpression.getOperationTokenType(), binaryExpression, new PsiType[]{rType}); } @Nullable @@ -497,4 +488,13 @@ public class TypesUtil { public static boolean typeEqualsToText(@NotNull PsiType type, @NotNull String text) { return text.endsWith(type.getPresentableText()) && text.equals(type.getCanonicalText()); } + + public static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) { + final Map map = s1.getSubstitutionMap(); + Map result = new com.intellij.util.containers.hash.HashMap(map.size()); + for (PsiTypeParameter parameter : map.keySet()) { + result.put(parameter, s2.substitute(map.get(parameter))); + } + return PsiSubstitutorImpl.createSubstitutor(result); + } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java index 8bcc56e7e44c..5bc64ebe2ba6 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/members/GrMethodBaseImpl.java @@ -29,6 +29,7 @@ import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.NamedStub; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureBackedByPsiMethod; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.ui.RowIcon; import com.intellij.util.ArrayUtil; import com.intellij.util.Function; @@ -65,6 +66,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyBaseElementImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.params.GrParameterListImpl; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.MethodTypeInferencer; @@ -175,6 +177,26 @@ public abstract class GrMethodBaseImpl extends GroovyBaseEl return inferred; } if (inferred != null && inferred != PsiType.NULL) { + if (inferred instanceof PsiClassType && nominal instanceof PsiClassType) { + final PsiClassType.ClassResolveResult declaredResult = ((PsiClassType)nominal).resolveGenerics(); + final PsiClass declaredClass = declaredResult.getElement(); + if (declaredClass != null) { + final PsiClassType.ClassResolveResult initializerResult = ((PsiClassType)inferred).resolveGenerics(); + final PsiClass initializerClass = initializerResult.getElement(); + if (initializerClass != null && + com.intellij.psi.util.PsiUtil.isRawSubstitutor(initializerClass, initializerResult.getSubstitutor())) { + if (declaredClass == initializerClass) return nominal; + final PsiSubstitutor declaredResultSubstitutor = declaredResult.getSubstitutor(); + final PsiSubstitutor superSubstitutor = + TypeConversionUtil.getClassSubstitutor(declaredClass, initializerClass, declaredResultSubstitutor); + + if (superSubstitutor != null) { + return JavaPsiFacade.getInstance(method.getProject()).getElementFactory() + .createType(declaredClass, TypesUtil.composeSubstitutors(declaredResultSubstitutor, superSubstitutor)); + } + } + } + } if (nominal.isAssignableFrom(inferred)) return inferred; } return nominal; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index e00a97424b9c..a5c0ff4b734b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -15,15 +15,16 @@ */ package org.jetbrains.plugins.groovy.refactoring.changeSignature; -import com.intellij.psi.*; -import com.intellij.psi.impl.PsiSubstitutorImpl; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage; import com.intellij.usageView.UsageInfo; -import com.intellij.util.containers.hash.HashMap; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -33,11 +34,10 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethod import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import java.util.Map; - /** * @author Maxim.Medvedev */ @@ -73,7 +73,7 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec final MethodSignature methodSignature = resolved.getSignature(PsiSubstitutor.EMPTY); final PsiSubstitutor superMethodSignatureSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(methodSignature, superMethodSignature); - mySubstitutor = composeSubstitutors(superMethodSignatureSubstitutor, mySubstitutor); + mySubstitutor = TypesUtil.composeSubstitutors(superMethodSignatureSubstitutor, mySubstitutor); } } } @@ -90,15 +90,6 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec } } - private static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) { - final Map map = s1.getSubstitutionMap(); - Map result = new HashMap(map.size()); - for (PsiTypeParameter parameter : map.keySet()) { - result.put(parameter, s2.substitute(map.get(parameter))); - } - return PsiSubstitutorImpl.createSubstitutor(result); - } - @Nullable public static GroovyResolveResult resolveMethod(final PsiElement ref) { if (ref instanceof GrEnumConstant) return ((GrEnumConstant)ref).resolveConstructorGenerics(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java index ece0e8a02fcd..8aeb31c50d25 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduceVariable/GroovyIntroduceVariableBase.java @@ -180,7 +180,8 @@ public abstract class GroovyIntroduceVariableBase implements RefactoringActionHa if (selectedExpr instanceof GrReferenceExpression && selectedExpr.getParent() instanceof GrMethodCall && - (((GrMethodCall)selectedExpr.getParent()).isCommandExpression() || selectedExpr.getParent() instanceof GrApplicationStatement)) { + (((GrMethodCall)selectedExpr.getParent()).isCommandExpression() || selectedExpr.getParent() instanceof GrApplicationStatement) || + selectedExpr instanceof GrApplicationStatement) { String message = RefactoringBundle.getCannotRefactorMessage(GroovyRefactoringBundle.message("selected.expression.in.command.expression")); showErrorMessage(project, editor, message); return false; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java index dd8de05b8b32..ef0f5332af28 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.java @@ -16,19 +16,19 @@ package org.jetbrains.plugins.groovy; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.testFramework.LightProjectDescriptor; -import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.module.StdModuleTypes; -import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.JavaSdkImpl; +import com.intellij.openapi.roots.ContentEntry; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.util.TestUtils; @@ -52,7 +52,7 @@ public abstract class LightGroovyTestCase extends LightCodeInsightFixtureTestCas public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY").getModifiableModel(); final VirtualFile groovyJar = - JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockJdkHome() + "/jre/lib/groovy-1.0.jar!/"); + JarFileSystem.getInstance().refreshAndFindFileByPath(TestUtils.getMockGroovy1_7LibraryName()+"!/"); modifiableModel.addRoot(groovyJar, OrderRootType.CLASSES); modifiableModel.commit(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy index cbe09540691b..5218ac2d2e13 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/dsl/GroovyTransformationsTest.groovy @@ -48,7 +48,7 @@ class GroovyTransformationsTest extends LightCodeInsightFixtureTestCase { public void testVetoableTransform() throws Throwable { doPlainTest() } - public void testNewifyTransform1() throws Throwable { doVariantsTest('newInstance', 'new', 'new', + public void testNewifyTransform1() throws Throwable { doVariantsTest('negative', 'newInstance', 'new', 'new', 'newInstance', 'newInstance0', 'newInstanceCallerCache', 'next') } public void testNewifyTransform2() throws Throwable { doVariantsTest('Leaf', 'Leaf', 'Leaf') } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java index ed398d693eb6..27d59683200a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/findUsages/FindUsagesTest.java @@ -190,7 +190,7 @@ public class FindUsagesTest extends LightGroovyTestCase { } public void testGDKSuperMethodSearch() throws Exception { - doSuperMethodTest("Object"); + doSuperMethodTest("T"); } public void testGDKSuperMethodForMapSearch() throws Exception { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java index 6a6fd3b29023..114a6b5dc10d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.java @@ -121,7 +121,7 @@ public class TypeInferenceTest extends GroovyResolveTestCase { public void testArrayLikeAccessWithIntSequence() { final GrReferenceExpression ref = (GrReferenceExpression)configureByFile("arrayLikeAccessWithIntSequence/A.groovy").getElement(); - assertEquals("java.util.List", ref.getType().getCanonicalText()); + assertEquals("java.util.List", ref.getType().getCanonicalText()); } public void testArrayAccess() { @@ -138,4 +138,8 @@ public class TypeInferenceTest extends GroovyResolveTestCase { GrReferenceExpression refExpr = (GrReferenceExpression)configureByFile("parameterWithBuiltinType/A.groovy"); assertEquals("java.lang.Integer", refExpr.getType().getCanonicalText()); } + + public void testRawTypeInReturnExpression() { + assertNotNull(resolve("A.groovy")); + } } diff --git a/plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy b/plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy new file mode 100644 index 000000000000..1b5bc55a4e51 --- /dev/null +++ b/plugins/groovy/testdata/resolve/inference/rawTypeInReturnExpression/A.groovy @@ -0,0 +1,14 @@ +class MissingInferenceTest { + Map>> factoryMethod() { new HashMap()} + + def myMethod() { + Map>> dataTyped = new HashMap() + def dataInferred = new HashMap>>() + def dataNotInferred = factoryMethod() + + println dataTyped ['foo'][5][2].charAt(2) + println dataInferred ['foo'][5][2].charAt(2) + println dataNotInferred['foo'][5][2].charAt(2) // no completion, highlighted as dynamic + } +} + diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java index 84aa2ac7fdbd..41f426d9a16b 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java @@ -26,10 +26,13 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiLiteralExpression; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -92,13 +95,10 @@ public class I18nizeAction extends AnAction { return PlatformDataKeys.EDITOR.getData(e.getDataContext()); } - public void actionPerformed(AnActionEvent e) { - final Editor editor = getEditor(e); - final Project project = editor.getProject(); - final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext()); - if (psiFile == null) return; - final I18nQuickFixHandler handler = getHandler(e); - if (handler == null) return; + public static void doI18nSelectedString(final @NotNull Project project, + final @NotNull Editor editor, + final @NotNull PsiFile psiFile, + final @NotNull I18nQuickFixHandler handler) { try { handler.checkApplicability(psiFile, editor); } @@ -136,4 +136,16 @@ public class I18nizeAction extends AnAction { }); } + public void actionPerformed(AnActionEvent e) { + final Editor editor = getEditor(e); + final Project project = editor.getProject(); + assert project != null; + final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext()); + if (psiFile == null) return; + final I18nQuickFixHandler handler = getHandler(e); + if (handler == null) return; + + doI18nSelectedString(project, editor, psiFile, handler); + } + } diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java index 870794475474..6b0782e07539 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java @@ -199,7 +199,7 @@ public abstract class TestObject implements JavaCommandLine { if (myJavaParameters.getJdk() == null){ myJavaParameters.setJdk(module != null ? ModuleRootManager.getInstance(module).getSdk() - : ProjectRootManager.getInstance(myProject).getProjectJdk()); + : ProjectRootManager.getInstance(myProject).getProjectSdk()); } myJavaParameters.getClassPath().add(JavaSdkUtil.getIdeaRtJarPath()); diff --git a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenRemoteObject.java b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenRemoteObject.java index 59ff9eb3c0f0..d6e66e4782ba 100644 --- a/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenRemoteObject.java +++ b/plugins/maven/facade-api/src/org/jetbrains/idea/maven/facade/MavenRemoteObject.java @@ -22,4 +22,9 @@ public class MavenRemoteObject extends RemoteObject{ protected boolean isKnownException(Throwable ex) { return ex.getClass().getName().startsWith(MavenRemoteObject.class.getPackage().getName()); } + + public RuntimeException rethrowException(Throwable e) { + Throwable wrap = wrapException(e); + throw wrap instanceof RuntimeException ? (RuntimeException)wrap : new RuntimeException(wrap); + } } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java index 467abb10a846..23707400f743 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java @@ -445,7 +445,7 @@ public class MavenProject { result.addAll(state.myReadingProblems); for (Map.Entry each : state.myModulesPathsAndNames.entrySet()) { - if (LocalFileSystem.getInstance().refreshAndFindFileByPath(each.getKey()) == null) { + if (LocalFileSystem.getInstance().findFileByPath(each.getKey()) == null) { result.add(createDependencyProblem(file, ProjectBundle.message("maven.project.problem.moduleNotFound", each.getValue()))); } } @@ -549,7 +549,7 @@ public class MavenProject { List result = new ArrayList(); Set pathsInStack = getModulePaths(); for (String each : pathsInStack) { - VirtualFile f = fs.refreshAndFindFileByPath(each); + VirtualFile f = fs.findFileByPath(each); if (f != null) result.add(f); } return result; diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/facade/MavenFacadeManagerTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/facade/MavenFacadeManagerTest.java index ebc7f3bc2967..a1e0c61b9401 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/facade/MavenFacadeManagerTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/facade/MavenFacadeManagerTest.java @@ -45,7 +45,7 @@ public class MavenFacadeManagerTest extends MavenTestCase { }); try { - result.get(5, TimeUnit.SECONDS); + result.get(10, TimeUnit.SECONDS); } catch (InterruptedException e) { throw new RuntimeException(e); diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java index f6a75cb6e492..e808b0a1211c 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/SpellCheckingInspection.java @@ -160,6 +160,8 @@ public class SpellCheckingInspection extends LocalInspectionTool { }; } + private static final boolean magicEvaluator = ApplicationManager.getApplication().isUnitTestMode(); + /** * Splits element text in tokens according to spell checker strategy of given language * @param element Psi element @@ -170,6 +172,11 @@ public class SpellCheckingInspection extends LocalInspectionTool { public static Token[] tokenize(@NotNull final PsiElement element, @NotNull final Language language) { final SpellcheckingStrategy factoryByLanguage = getFactoryByLanguage(language); final Tokenizer tokenizer = factoryByLanguage.getTokenizer(element); + String magicWord; + if (magicEvaluator && element.getText().indexOf(magicWord = "xmxmxm") != -1) { + System.out.println("~~~~~~"+tokenizer); + System.out.println(SpellCheckerManager.getInstance(element.getProject()).getUserDictionary().contains(magicWord)); + } return tokenizer.tokenize(element); } diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java index 999752289ea8..270004471a0d 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGRunnableState.java @@ -237,7 +237,7 @@ public class TestNGRunnableState extends JavaCommandLineState { .getPath());//todo !do not hard code lib name! // Configure rest of jars JavaParametersUtil.configureConfiguration(javaParameters, config); - Sdk jdk = module == null ? ProjectRootManager.getInstance(project).getProjectJdk() : ModuleRootManager.getInstance(module).getSdk(); + Sdk jdk = module == null ? ProjectRootManager.getInstance(project).getProjectSdk() : ModuleRootManager.getInstance(module).getSdk(); javaParameters.setJdk(jdk); final Object[] patchers = Extensions.getExtensions(ExtensionPoints.JUNIT_PATCHER); for (Object patcher : patchers) { diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java index cf418924b5cd..528be4a3c2c9 100644 --- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java +++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunConfiguration.java @@ -470,7 +470,7 @@ public final class XsltRunConfiguration extends RunConfigurationBase implements jdk = ModuleRootManager.getInstance(module).getSdk(); } if (jdk == null) { - jdk = ProjectRootManager.getInstance(getProject()).getProjectJdk(); + jdk = ProjectRootManager.getInstance(getProject()).getProjectSdk(); } return jdk; } diff --git a/resources-en/src/tips/Welcome.html b/resources-en/src/tips/Welcome.html index b0e03b34040c..5e0c440dfa2a 100644 --- a/resources-en/src/tips/Welcome.html +++ b/resources-en/src/tips/Welcome.html @@ -3,7 +3,7 @@
Welcome to IntelliJ - IDEA 9 + IDEA &majorVersion;

You can quickly get familiar with the main features of the IDE by reading these tips. You may try out the features described in the tips while this dialog stays open on the screen. If you close the dialog, you can always get back to it from the Help | Tip of the Day diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml index f4463faadd44..6d3a222eba79 100644 --- a/resources-en/src/tips/tips.xml +++ b/resources-en/src/tips/tips.xml @@ -84,6 +84,7 @@ + diff --git a/samples/actions/src/META-INF/plugin.xml b/samples/actions/src/META-INF/plugin.xml index 89b79070d4de..489749c669ee 100644 --- a/samples/actions/src/META-INF/plugin.xml +++ b/samples/actions/src/META-INF/plugin.xml @@ -1,4 +1,3 @@ - ActionsSample diff --git a/samples/conditionalOperatorConvertor/META-INF/plugin.xml b/samples/conditionalOperatorConvertor/META-INF/plugin.xml index ceb6ce3046cd..e63ba2e6da1a 100644 --- a/samples/conditionalOperatorConvertor/META-INF/plugin.xml +++ b/samples/conditionalOperatorConvertor/META-INF/plugin.xml @@ -1,6 +1,3 @@ - Conditional Operator Converter ConditionalOperatorConverter diff --git a/samples/plugin/src/META-INF/plugin.xml b/samples/plugin/src/META-INF/plugin.xml index c194183509af..031152e4f8b3 100644 --- a/samples/plugin/src/META-INF/plugin.xml +++ b/samples/plugin/src/META-INF/plugin.xml @@ -1,4 +1,3 @@ - Sample diff --git a/samples/vfs/src/META-INF/plugin.xml b/samples/vfs/src/META-INF/plugin.xml index ff45e7859720..a10dc993a13a 100644 --- a/samples/vfs/src/META-INF/plugin.xml +++ b/samples/vfs/src/META-INF/plugin.xml @@ -1,4 +1,3 @@ - VfsSample diff --git a/xml/dom-impl/src/com/intellij/xml/impl/dom/AbstractDomChildrenDescriptor.java b/xml/dom-impl/src/com/intellij/xml/impl/dom/AbstractDomChildrenDescriptor.java index 8e1f105a9a4d..95a2c47d9cbf 100644 --- a/xml/dom-impl/src/com/intellij/xml/impl/dom/AbstractDomChildrenDescriptor.java +++ b/xml/dom-impl/src/com/intellij/xml/impl/dom/AbstractDomChildrenDescriptor.java @@ -206,7 +206,7 @@ public abstract class AbstractDomChildrenDescriptor implements XmlElementDescrip } public int getContentType() { - throw new UnsupportedOperationException("Method getContentType not implemented in " + getClass()); + return CONTENT_TYPE_UNKNOWN; } public void init(final PsiElement element) { diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java index 4ca49d304c7e..a5401bd2a601 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlTagInsertHandler.java @@ -320,6 +320,8 @@ public class XmlTagInsertHandler implements InsertHandler { private static void completeTagTail(Template template, XmlElementDescriptor descriptor, PsiFile file, XmlTag context, boolean firstLevel) { boolean completeIt = !firstLevel || descriptor.getAttributesDescriptors(null).length == 0; switch (descriptor.getContentType()) { + case XmlElementDescriptor.CONTENT_TYPE_UNKNOWN: + return; case XmlElementDescriptor.CONTENT_TYPE_EMPTY: if (completeIt) { template.addTextSegment("/>"); diff --git a/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java b/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java index dd6df1d7ae6f..2daf4c2d01f2 100644 --- a/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java +++ b/xml/impl/src/com/intellij/xml/actions/XmlSplitTagAction.java @@ -140,13 +140,13 @@ public class XmlSplitTagAction implements IntentionAction { final String name = xmlTag.getName(); sb.append("<").append(name); if (attrs.length() > 0) { - sb.append(' ').append(attrs.toString()); + sb.append(' ').append(attrs); } sb.append('>'); sb.append(first); sb.append("<").append(name); if (attrsWoId.length() > 0) { - sb.append(' ').append(attrsWoId.toString()); + sb.append(' ').append(attrsWoId); } sb.append('>'); sb.append(second).append(""); diff --git a/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java index 36d365137c04..36d06639dceb 100644 --- a/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java +++ b/xml/impl/src/com/intellij/xml/impl/schema/AnyXmlElementDescriptor.java @@ -99,6 +99,6 @@ public class AnyXmlElementDescriptor implements XmlElementDescriptor { } public int getContentType() { - return 0; + return CONTENT_TYPE_UNKNOWN; } } diff --git a/xml/openapi/src/com/intellij/xml/XmlElementDescriptor.java b/xml/openapi/src/com/intellij/xml/XmlElementDescriptor.java index 22d0422edfeb..1b05741cb168 100644 --- a/xml/openapi/src/com/intellij/xml/XmlElementDescriptor.java +++ b/xml/openapi/src/com/intellij/xml/XmlElementDescriptor.java @@ -63,6 +63,7 @@ public interface XmlElementDescriptor extends PsiMetaData { int getContentType(); + int CONTENT_TYPE_UNKNOWN = -1; int CONTENT_TYPE_EMPTY = 0; int CONTENT_TYPE_ANY = 1; int CONTENT_TYPE_CHILDREN = 2;