diff --git a/bin/win/IdeaWin32.dll b/bin/win/IdeaWin32.dll new file mode 100644 index 000000000000..c1f03bf19449 Binary files /dev/null and b/bin/win/IdeaWin32.dll differ diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/BuildAllArtifactsAction.java b/java/compiler/impl/src/com/intellij/compiler/actions/BuildAllArtifactsAction.java new file mode 100644 index 000000000000..e21e4183ed7f --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/actions/BuildAllArtifactsAction.java @@ -0,0 +1,57 @@ +/* + * 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.compiler.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.compiler.CompilerManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.packaging.artifacts.Artifact; +import com.intellij.packaging.artifacts.ArtifactManager; +import com.intellij.packaging.impl.compiler.ArtifactCompileScope; + +import java.util.ArrayList; +import java.util.List; + +/** +* @author nik +*/ +public class BuildAllArtifactsAction extends AnAction { + public BuildAllArtifactsAction() { + super("Build All Artifacts", "Build all configured artifacts", null); + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(e.getData(PlatformDataKeys.PROJECT) != null); + } + + @Override + public void actionPerformed(AnActionEvent e) { + final Project project = e.getData(PlatformDataKeys.PROJECT); + if (project == null) return; + + List toBuild = new ArrayList(); + for (Artifact artifact : ArtifactManager.getInstance(project).getSortedArtifacts()) { + if (!StringUtil.isEmpty(artifact.getOutputPath())) { + toBuild.add(artifact); + } + } + CompilerManager.getInstance(project).make(ArtifactCompileScope.createArtifactsScope(project, toBuild), null); + } +} diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactActionGroup.java b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactActionGroup.java index cae981933a70..521e1d2dbbaa 100644 --- a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactActionGroup.java +++ b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactActionGroup.java @@ -15,10 +15,7 @@ */ package com.intellij.compiler.actions; -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.packaging.artifacts.Artifact; @@ -50,6 +47,11 @@ public class BuildArtifactActionGroup extends ActionGroup { actions.add(new BuildArtifactAction(project, artifact)); } } + if (actions.size() > 1) { + actions.add(0, new BuildAllArtifactsAction()); + actions.add(1, Separator.getInstance()); + } return actions.toArray(new AnAction[actions.size()]); } + } diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java index 3cc3def8a9ad..88f8743aa6b2 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/BackendCompilerWrapper.java @@ -730,8 +730,7 @@ public class BackendCompilerWrapper { if (paths == null || paths.isEmpty()) { return; } - final String prefix = packagePrefix != null && packagePrefix.length() > 0 ? packagePrefix.replace('.', '/') + "/" : ""; - final String filePath = "/" + prefix + VfsUtil.getRelativePath(srcFile, sourceRoot, '/'); + final String filePath = "/" + calcPackagePath(srcFile, sourceRoot, packagePrefix); for (final CompiledClass cc : paths) { myCompileContext.getProgressIndicator().checkCanceled(); if (LOG.isDebugEnabled()) { @@ -768,6 +767,18 @@ public class BackendCompilerWrapper { } } + /** + * + * @param srcFile + * @param sourceRoot + * @param packagePrefix + * @return A 'package'-path to a given src file relative to a specified root. "/" slashes must be used + */ + protected String calcPackagePath(VirtualFile srcFile, VirtualFile sourceRoot, String packagePrefix) { + final String prefix = packagePrefix != null && packagePrefix.length() > 0 ? packagePrefix.replace('.', '/') + "/" : ""; + return prefix + VfsUtil.getRelativePath(srcFile, sourceRoot, '/'); + } + @Nullable private Pair moveToRealLocation(String tempOutputDir, String pathToClass, VirtualFile sourceFile, final List filesToRefresh) { final Module module = myCompileContext.getModuleByFile(sourceFile); diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java index 87bb3488a304..f5e40da93aea 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/JVMNameUtil.java @@ -20,8 +20,10 @@ import com.intellij.debugger.DebuggerManager; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.jsp.JspFile; @@ -213,8 +215,12 @@ public class JVMNameUtil { throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("error.class.not.loaded", getDisplayName(process))); } - public String getDisplayName(DebugProcessImpl debugProcess) { - return getSourcePositionClassDisplayName(debugProcess, mySourcePosition); + public String getDisplayName(final DebugProcessImpl debugProcess) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + public String compute() { + return getSourcePositionClassDisplayName(debugProcess, mySourcePosition); + } + }); } } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java index 448e7f9db761..2f15d98d183f 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java @@ -76,7 +76,7 @@ public class FacetLibrariesValidatorImpl extends FacetLibrariesValidator { ModuleRootModel rootModel = myContext.getRootModel(); List roots = collectRoots(rootModel); - RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = myRequiredLibraries.checkLibraries(VfsUtil.toVirtualFileArray(roots)); + RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = myRequiredLibraries.checkLibraries(VfsUtil.toVirtualFileArray(roots), false); if (info == null) { return ValidationResult.OK; } @@ -184,7 +184,7 @@ public class FacetLibrariesValidatorImpl extends FacetLibrariesValidator { myPanel.apply(); final LibraryCompositionSettings settings = myPanel.getLibraryCompositionSettings(); final LibrariesContainer librariesContainer = myContext.getLibrariesContainer(); - if (settings.downloadFiles(myMirrorsMap, librariesContainer, myPanel.getMainPanel())) { + if (settings.downloadFiles(myMirrorsMap, librariesContainer, myPanel.getMainPanel(), false)) { ModifiableRootModel rootModel = myContext.getModifiableRootModel(); if (rootModel == null) { final ModifiableRootModel model = ModuleRootManager.getInstance(myContext.getModule()).getModifiableModel(); diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java index 651c8336f945..d8ac377ce2d6 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionOptionsPanel.java @@ -152,7 +152,7 @@ public class LibraryCompositionOptionsPanel { Library[] libraries = myLibrariesContainer.getAllLibraries(); for (Library library : libraries) { RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = - requiredLibraries.checkLibraries(myLibrariesContainer.getLibraryFiles(library, OrderRootType.CLASSES)); + requiredLibraries.checkLibraries(myLibrariesContainer.getLibraryFiles(library, OrderRootType.CLASSES), false); if (info == null || info.getLibraryInfos().length < libraryInfos.length) { suitableLibraries.add(library); } @@ -192,14 +192,14 @@ public class LibraryCompositionOptionsPanel { } private void updateAll() { - String missingJarsText = ""; + String missingJarsText; List roots = new ArrayList(); roots.addAll(myAddedJars); for (Library library : myUsedLibraries) { roots.addAll(Arrays.asList(myLibrariesContainer.getLibraryFiles(library, OrderRootType.CLASSES))); } RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = new RequiredLibrariesInfo(myLibraryCompositionSettings.getLibraryInfos()).checkLibraries( - VfsUtil.toVirtualFileArray(roots)); + VfsUtil.toVirtualFileArray(roots), false); if (info != null) { missingJarsText = ProjectBundle.message("label.text.libraries.are.missing", info.getMissingJarsText()); } diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java index 1a5c4d4d0fb9..43ab025dce27 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java @@ -113,7 +113,8 @@ public class LibraryCompositionSettings { return myTitle; } - public boolean downloadFiles(final @NotNull LibraryDownloadingMirrorsMap mirrorsMap, @NotNull LibrariesContainer librariesContainer, final @NotNull JComponent parent) { + public boolean downloadFiles(final @NotNull LibraryDownloadingMirrorsMap mirrorsMap, @NotNull LibrariesContainer librariesContainer, final @NotNull JComponent parent, + boolean all) { if (myDownloadLibraries) { RequiredLibrariesInfo requiredLibraries = new RequiredLibrariesInfo(getLibraryInfos()); @@ -123,7 +124,7 @@ public class LibraryCompositionSettings { roots.addAll(Arrays.asList(librariesContainer.getLibraryFiles(library, OrderRootType.CLASSES))); } VirtualFile[] jars = VfsUtil.toVirtualFileArray(roots); - RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = requiredLibraries.checkLibraries(jars); + RequiredLibrariesInfo.RequiredClassesNotFoundInfo info = requiredLibraries.checkLibraries(jars, all); if (info != null) { LibraryDownloadInfo[] downloadingInfos = LibraryDownloader.getDownloadingInfos(info.getLibraryInfos()); if (downloadingInfos.length > 0) { diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/RequiredLibrariesInfo.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/RequiredLibrariesInfo.java index 7d91565ddada..979f35626dd6 100644 --- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/RequiredLibrariesInfo.java +++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/RequiredLibrariesInfo.java @@ -43,12 +43,12 @@ public class RequiredLibrariesInfo { myLibraryInfos.add(lib); } - public @Nullable RequiredClassesNotFoundInfo checkLibraries(VirtualFile[] libraryFiles) { + public @Nullable RequiredClassesNotFoundInfo checkLibraries(VirtualFile[] libraryFiles, boolean all) { List infos = new ArrayList(); List classes = new ArrayList(); for (LibraryInfo info : myLibraryInfos) { - boolean notFound = false; + boolean notFound = all && info.getRequiredClasses().length == 0; for (String className : info.getRequiredClasses()) { if (!LibraryUtil.isClassAvailableInLibrary(libraryFiles, className)) { classes.add(className); diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java index 2b4d16d59cff..ee79291a9ba5 100644 --- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java @@ -242,7 +242,7 @@ public class AddSupportForFrameworksPanel { applyLibraryOptionsForSelected(); List list = getLibrariesCompositionSettingsList(); for (LibraryCompositionSettings compositionSettings : list) { - if (!compositionSettings.downloadFiles(myMirrorsMap, myLibrariesContainer, myMainPanel)) return false; + if (!compositionSettings.downloadFiles(myMirrorsMap, myLibrariesContainer, myMainPanel, true)) return false; } return true; } diff --git a/platform/lang-api/src/com/intellij/facet/ui/libraries/MavenLibraryUtil.java b/platform/lang-api/src/com/intellij/facet/ui/libraries/MavenLibraryUtil.java index 0d03bf238192..e7b51f1fa2fe 100644 --- a/platform/lang-api/src/com/intellij/facet/ui/libraries/MavenLibraryUtil.java +++ b/platform/lang-api/src/com/intellij/facet/ui/libraries/MavenLibraryUtil.java @@ -25,8 +25,8 @@ import com.intellij.ide.IdeBundle; */ public class MavenLibraryUtil { @NonNls private static final String[] MAVEN_MIRRORS = { - "http://www.ibiblio.org/maven2/", "http://repo1.maven.org/maven2/", + "http://www.ibiblio.org/maven2/", }; private static final RemoteRepositoryInfo MAVEN = new RemoteRepositoryInfo("maven", IdeBundle.message("maven.repository.presentable.name"), MAVEN_MIRRORS); diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index f5ce315e6deb..5a3376679f27 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -1148,7 +1148,7 @@ public class CodeStyleSettings implements Cloneable, JDOMExternalizable { if (fileTypeId != null && fileTypeId.length() > 0) { FileType target = FileTypeManager.getInstance().getFileTypeByExtension(fileTypeId); - if (FileTypes.UNKNOWN == target || FileTypes.PLAIN_TEXT == target) { + if (FileTypes.UNKNOWN == target || FileTypes.PLAIN_TEXT == target || target.getDefaultExtension().length() == 0) { target = new TempFileType(fileTypeId); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java index a6abff4db540..b7ebeeca4082 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java @@ -231,7 +231,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, setBeforeRunTasks(configuration, tasks); } - void checkRecentsLimit() { + void checkRecentsLimit() { while (getTempConfigurations().length > getConfig().getRecentsLimit()) { for (Iterator> it = myConfigurations.entrySet().iterator(); it.hasNext();) { Map.Entry entry = it.next(); @@ -351,7 +351,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, continue; } } - + addConfigurationElement(parentNode, runnerAndConfigurationSettings); } @@ -440,17 +440,33 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, public void readExternal(final Element parentNode) throws InvalidDataException { clear(); + final Comparator comparator = new Comparator() { + public int compare(Element a, Element b) { + final boolean aDefault = Boolean.valueOf(a.getAttributeValue("default", "false")); + final boolean bDefault = Boolean.valueOf(b.getAttributeValue("default", "false")); + return aDefault == bDefault ? 0 : aDefault ? -1 : 1; + } + }; + final List children = parentNode.getChildren(); + final List sortedElements = new ArrayList(); for (final Object aChildren : children) { final Element element = (Element)aChildren; - if (loadConfiguration(element, false) == null && Comparing.strEqual(element.getName(), CONFIGURATION)) { + if (Comparing.strEqual(element.getName(), CONFIGURATION)) { + sortedElements.add(element); + } + } + + Collections.sort(sortedElements, comparator); // ensure templates are loaded first! + + for (final Element element : sortedElements) { + if (loadConfiguration(element, false) == null) { if (myUnloadedElements == null) myUnloadedElements = new ArrayList(2); myUnloadedElements.add(element); } } myOrder.readExternal(parentNode); - mySelectedConfig = parentNode.getAttributeValue(SELECTED_ATTR); } @@ -551,7 +567,7 @@ public class RunManagerImpl extends RunManagerEx implements JDOMExternalizable, @Nullable private static ConfigurationFactory findFactoryOfTypeByName(final ConfigurationType type, final String factoryName) { if (factoryName == null) return null; - + if (type instanceof UnknownConfigurationType) { return type.getConfigurationFactories()[0]; } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java index 0900e9fb8a0a..89a85a68ab4a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java @@ -102,7 +102,6 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa else { myDialog = new MyDialog(shouldShowBackground, myProject, myCancelText); } - myDialog.changeCancelButtonText(myCancelText); Disposer.register(this, myDialog); @@ -494,6 +493,9 @@ public class ProgressWindow extends BlockingProgressIndicator implements Disposa private void createCenterPanel() { // Cancel button (if any) + if (myCancelText != null) { + myCancelButton.setText(myCancelText); + } myCancelButton.setVisible(myShouldShowCancel); myBackgroundButton.setVisible(myShouldShowBackground); 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 f956a0ff901a..bda7f3265ef6 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 @@ -19,17 +19,16 @@ import com.intellij.ide.AppLifecycleListener; import com.intellij.ide.highlighter.WorkspaceFileType; import com.intellij.ide.impl.ProjectUtil; import com.intellij.ide.startup.impl.StartupManagerImpl; -import com.intellij.notification.*; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.components.ExportableApplicationComponent; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.impl.stores.*; +import com.intellij.openapi.components.impl.stores.IComponentStore; +import com.intellij.openapi.components.impl.stores.IProjectStore; +import com.intellij.openapi.components.impl.stores.StorageUtil; +import com.intellij.openapi.components.impl.stores.XmlElementStorage; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProcessCanceledException; @@ -45,7 +44,6 @@ import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileEvent; @@ -66,7 +64,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import javax.swing.event.HyperlinkEvent; import java.io.File; import java.io.IOException; import java.util.*; @@ -597,7 +594,10 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt for (String component : components) { message += component + "\n"; } - message += "Shutdown IDEA?"; + + final boolean canRestart = ApplicationManager.getApplication().isRestartCapable(); + message += "Would you like to " + (canRestart ? "restart " : "shutdown "); + message += ApplicationNamesInfo.getInstance().getProductName() + "?"; if (Messages.showYesNoDialog(message, "Application Configuration Reload", Messages.getQuestionIcon()) == 0) { @@ -607,9 +607,13 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ((XmlElementStorage)stateStorage).disableSaving(); } } - ApplicationManagerEx.getApplicationEx().exit(true); + if (canRestart) { + ApplicationManagerEx.getApplicationEx().restart(); + } + else { + ApplicationManagerEx.getApplicationEx().exit(true); + } } - } return reloadOk[0]; diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java new file mode 100644 index 000000000000..5a121418eb38 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/FileInfo.java @@ -0,0 +1,36 @@ +/* + * 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.openapi.vfs.impl.win32; + +/** + * @author Dmitry Avdeev + */ +public class FileInfo { + + static { + initIDs(); + } + + private static native void initIDs(); + + public String name; + public int attributes; + public long timestamp; + + public String toString() { + return name; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java new file mode 100644 index 000000000000..b041683762de --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/IdeaWin32.java @@ -0,0 +1,26 @@ +/* + * 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.openapi.vfs.impl.win32; + +/** + * @author Dmitry Avdeev + */ +public class IdeaWin32 { + + public native FileInfo getInfo(String path); + + public native FileInfo[] listChildren(String path); +} diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java index 2768e9af57f7..7b79cd58ffe3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32Kernel.java @@ -15,16 +15,6 @@ */ package com.intellij.openapi.vfs.impl.win32; -import com.intellij.util.ArrayUtil; -import com.sun.jna.Library; -import com.sun.jna.Native; -import com.sun.jna.Pointer; -import com.sun.jna.Structure; -import com.sun.jna.examples.win32.W32API; -import com.sun.jna.win32.StdCallLibrary; -import com.sun.jna.win32.W32APIFunctionMapper; -import com.sun.jna.win32.W32APITypeMapper; - import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.HashMap; @@ -35,62 +25,38 @@ import java.util.Map; */ public class Win32Kernel { - private static final int MAX_PATH = 0x00000104; + public static final int FILE_ATTRIBUTE_DIRECTORY = 0x0010; + public static final int FILE_ATTRIBUTE_READONLY = 0x0001; - public static final int FILE_ATTRIBUTE_DIRECTORY = 0x00000010; - public static final int FILE_ATTRIBUTE_READONLY = 0x0001; + private IdeaWin32 myKernel = new IdeaWin32(); - private static W32API.HANDLE INVALID_HANDLE_VALUE = new W32API.HANDLE(Pointer.createConstant(0xFFFFFFFFl)); - - private static Kernel32 myKernel = (Kernel32)Native.loadLibrary("kernel32", Kernel32.class, new HashMap() { - { - put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE); - put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE); - }}); - - private final WIN32_FIND_DATA myData = new WIN32_FIND_DATA(); + private Map myCache = new HashMap(); void clearCache() { myCache.clear(); } - private static class FileInfo { - private FileInfo(WIN32_FIND_DATA data) { - this.dwFileAttributes = data.dwFileAttributes; - this.ftLastWriteTime = data.ftLastWriteTime.toLong(); - } - - int dwFileAttributes; - long ftLastWriteTime; - } - - private Map myCache = new HashMap(); - public String[] list(String absolutePath) { - ArrayList list = new ArrayList(); - WIN32_FIND_DATA data = myData; - W32API.HANDLE hFind = myKernel.FindFirstFile(absolutePath.replace('/', '\\') + "\\*", data); - if (hFind.equals(INVALID_HANDLE_VALUE)) return new String[0]; - try { - do { - String name = Native.toString(data.cFileName); - if (name.equals(".")) { - myCache.put(absolutePath, new FileInfo(data)); - continue; - } - else if (name.equals("..")) { - continue; - } - myCache.put(absolutePath + "/" + name, new FileInfo(data)); - list.add(name); + FileInfo[] fileInfos = myKernel.listChildren(absolutePath.replace('/', '\\') + "\\*.*"); + if (fileInfos == null) { + return new String[0]; + } + ArrayList names = new ArrayList(fileInfos.length); + for (int i = 0, fileInfosLength = fileInfos.length; i < fileInfosLength; i++) { + FileInfo info = fileInfos[i]; + if (info.name.equals(".")) { + myCache.put(absolutePath, info); + continue; } - while (myKernel.FindNextFile(hFind, data)); + else if (info.name.equals("..")) { + continue; + } + myCache.put(absolutePath + "/" + info.name, info); + names.add(info.name); } - finally { - myKernel.FindClose(hFind); - } - return ArrayUtil.toStringArray(list); + + return names.toArray(new String[names.size()]); } public boolean exists(String path) { @@ -105,91 +71,30 @@ public class Win32Kernel { public boolean isDirectory(String path) throws FileNotFoundException { FileInfo data = getInfo(path); - return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + return (data.attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; } public boolean isWritable(String path) throws FileNotFoundException { FileInfo fileInfo = getInfo(path); myCache.remove(path); - return (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0; + return (fileInfo.attributes & FILE_ATTRIBUTE_READONLY) == 0; } public long getTimeStamp(String path) throws FileNotFoundException { - return getInfo(path).ftLastWriteTime; + long timestamp = getInfo(path).timestamp; + return timestamp / 10000 - 11644473600000l; } private FileInfo getInfo(String path) throws FileNotFoundException { FileInfo info = myCache.get(path); if (info == null) { - WIN32_FIND_DATA data = myData; - W32API.HANDLE handle = myKernel.FindFirstFile(path.replace('/', '\\'), data); - if (handle.equals(INVALID_HANDLE_VALUE)) { + + info = myKernel.getInfo(path.replace('/', '\\')); + if (info == null) { throw new FileNotFoundException(path); } - myKernel.FindClose(handle); - info = new FileInfo(data); myCache.put(path, info); } return info; } - - public void release() throws Throwable { - myData.release(); - } - - public interface Kernel32 extends StdCallLibrary { - - W32API.HANDLE FindFirstFile(String lpFileName, WIN32_FIND_DATA lpFindFileData); - - boolean FindNextFile(W32API.HANDLE hFindFile, WIN32_FIND_DATA lpFindFileData); - - boolean FindClose(W32API.HANDLE hFindFile); - } - - public static class FILETIME extends Structure implements Structure.ByValue { - - public int dwLowDateTime; - public int dwHighDateTime; - - private static long l(int i) { - if (i >= 0) { - return i; - } - else { - return ((long)i & 0x7FFFFFFFl) + 0x80000000l; - } - } - - public long toLong() { - return (((long)dwHighDateTime << 32) + l(dwLowDateTime)) / 10000 - 11644473600000l; - } - } - - @SuppressWarnings({"UnusedDeclaration"}) - public static class WIN32_FIND_DATA extends Structure { - - public int dwFileAttributes; - - public FILETIME ftCreationTime; - - public FILETIME ftLastAccessTime; - - public FILETIME ftLastWriteTime; - - public int nFileSizeHigh; - - public int nFileSizeLow; - - public int dwReserved0; - - public int dwReserved1; - - public char[] cFileName = new char[MAX_PATH]; - - public char[] cAlternateFileName = new char[14]; - - public void release() throws Throwable { - finalize(); - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java index a5e329b7f594..85c336ad16db 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32LocalFileSystem.java @@ -32,6 +32,22 @@ public class Win32LocalFileSystem extends LocalFileSystemBase { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.win32.Win32LocalFileSystem"); + private static boolean ourIsAvailable; + + static { + try { + System.loadLibrary("IdeaWin32"); + ourIsAvailable = true; + } + catch (Throwable e) { + ourIsAvailable = false; + } + } + + public static boolean isAvailable() { + return ourIsAvailable; + } + private static final ThreadLocal THREAD_LOCAL = new ThreadLocal() { @Override protected Win32LocalFileSystem initialValue() { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java index a3cd8b45dc0e..0cb6ea5c8059 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/RefreshWorker.java @@ -19,7 +19,7 @@ */ package com.intellij.openapi.vfs.newvfs.persistent; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.LocalFileSystem; @@ -58,9 +58,13 @@ public class RefreshWorker { root.markClean(); } else { - if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && SystemInfo.isWindows && root.isDirectory() && - Registry.is("filesystem.useNative") && !ApplicationManager.getApplication().isUnitTestMode()) { - delegate = Win32LocalFileSystem.getWin32Instance(); + if (delegate.getProtocol().equals(LocalFileSystem.PROTOCOL) && + root.isDirectory() && ApplicationManagerEx.getApplicationEx().isInternal() && + Registry.is("filesystem.useNative")) { + + if (SystemInfo.isWindows && Win32LocalFileSystem.isAvailable()) { + delegate = Win32LocalFileSystem.getWin32Instance(); + } } final PersistentFS persistence = (PersistentFS)ManagingFS.getInstance(); diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index f865108d50b6..c7471702fe8a 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -556,9 +556,8 @@ action.RunAPT.text=Process {0} _Annotations action.RunAPT.description=Run Annotation Processors on the selected scope action.GenerateAntBuild.text=_Generate Ant Build... action.GenerateAntBuild.description=Generate Ant Build File from the Project +action.BuildAllArtifacts.text=Build All Artifacts group.BuildArtifactsGroup.text=Build Artifact -action.BuildJar.text=Build _Jars... -action.BuildJar.description=Archive module output directories into jar files group.RunMenu.text=R_un group.RunnerActions.text=Run/Debug action.editRunConfigurations.text=Edit Configu_rations diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties index 6ec6702098eb..625b0f97e468 100644 --- a/platform/platform-resources-en/src/misc/registry.properties +++ b/platform/platform-resources-en/src/misc/registry.properties @@ -38,7 +38,7 @@ ide.tabbedPane.bufferedPaint=true debugger.valueTooltipAutoShow=true debugger.valueTooltipAutoShow.description=Auto show tooltip on mouse over -filesystem.useNative=false +filesystem.useNative=true analyze.exceptions.on.the.fly=false diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/GenericNotifierImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/GenericNotifierImpl.java index 9007383485aa..241e57b12c75 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/GenericNotifierImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/GenericNotifierImpl.java @@ -19,6 +19,8 @@ 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.Application; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -84,7 +86,16 @@ public abstract class GenericNotifierImpl { notification = new MyNotification(myGroupId, myTitle, getNotificationContent(obj), myType, myListener, obj); myState.put(key, notification); } - Notifications.Bus.notify(notification, myProject); + final Application application = ApplicationManager.getApplication(); + if (application.isDispatchThread()) { + Notifications.Bus.notify(notification, myProject); + } else { + application.invokeLater(new Runnable() { + public void run() { + Notifications.Bus.notify(notification, myProject); + } + }); + } } public void removeLazyNotificationByKey(final Key key) { @@ -131,6 +142,14 @@ public abstract class GenericNotifierImpl { } } + @Nullable + protected T getObj(final Key key) { + synchronized (myLock) { + final MyNotification notification = myState.get(key); + return notification == null ? null : notification.getObj(); + } + } + protected static class MyNotification extends Notification { private T myObj; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java index 2705f6d60d0f..7af934338ec6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.vcs.impl; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupManager; @@ -26,10 +28,15 @@ import java.util.LinkedList; import java.util.List; public class VcsInitialization { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.VcsInitialization"); + private final Project myProject; private final List> myList; + private final Object myLock; + private boolean myInitStarted; - public VcsInitialization(Project project) { + public VcsInitialization(final Project project) { + myLock = new Object(); myProject = project; myList = new LinkedList>(); @@ -41,16 +48,28 @@ public class VcsInitialization { } public void add(final VcsInitObject vcsInitObject, final Runnable runnable) { - myList.add(new Pair(vcsInitObject, runnable)); + synchronized (myLock) { + if (myInitStarted) { + LOG.info("Registering startup activity AFTER initialization ", new Throwable()); + // post startup are normally called on awt thread + ApplicationManager.getApplication().invokeLater(runnable); + } + myList.add(new Pair(vcsInitObject, runnable)); + } } public void execute() { - Collections.sort(myList, new Comparator>() { + final List> list; + synchronized (myLock) { + list = myList; + myInitStarted = true; // list would not be modified starting from this point + } + Collections.sort(list, new Comparator>() { public int compare(Pair o1, Pair o2) { return new Integer(o1.getFirst().getOrder()).compareTo(new Integer(o2.getFirst().getOrder())); } }); - for (Pair pair : myList) { + for (Pair pair : list) { pair.getSecond().run(); } } diff --git a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties index e05089186358..affc7b593ff2 100644 --- a/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties +++ b/plugins/cvs/cvs-core/src/com/intellij/cvsSupport2/CvsBundle.properties @@ -440,6 +440,7 @@ import.wizard.include.to.import.action.name=Include to Import message.choose.stored.file.version.title=Choose stored version error.message.wrong.remote.repository=wrong remote repository: {0} propmt.text.enter.private.key.password.for=Enter private key password for {0} +prompt.path.to.private.key=Private key path: ''{0}'' close.tab.action.name=Close cvs.unknown.revision.presentation= browse.changes.user.field.label=&User diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionUtil.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionUtil.java index 15e978fa702c..fe705a0eb830 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionUtil.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/SshConnectionUtil.java @@ -43,6 +43,7 @@ public class SshConnectionUtil { if (password == null) { SshPasswordDialog sshPasswordDialog = new SshPasswordDialog(CvsBundle.message("propmt.text.enter.private.key.password.for", cvsRoot)); + sshPasswordDialog.setAdditionalText(CvsBundle.message("prompt.path.to.private.key", settings.PATH_TO_PPK)); sshPasswordDialog.show(); if (!sshPasswordDialog.isOK()) return false; password = sshPasswordDialog.getPassword(); diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.form b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.form index 1021c30c7886..6ede8d5f71a8 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.form +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.form @@ -1,39 +1,34 @@
- + - - - + - - + - + - - + - - + @@ -41,8 +36,7 @@ - - + @@ -50,13 +44,20 @@ - - + + + + + + + + + diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.java index 9a494903aff1..7241f4201672 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/ssh/ui/SshPasswordDialog.java @@ -16,6 +16,7 @@ package com.intellij.cvsSupport2.connections.ssh.ui; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.util.ui.UIUtil; import javax.swing.*; @@ -28,6 +29,7 @@ public class SshPasswordDialog extends DialogWrapper{ private JCheckBox myStoreCheckbox; private JPanel myPanel; private JLabel myLabel; + private JLabel myAdditionalLbl; public SshPasswordDialog(String propmtText) { @@ -35,6 +37,7 @@ public class SshPasswordDialog extends DialogWrapper{ myLabel.setText(propmtText); setTitle(com.intellij.CvsBundle.message("dialog.title.ssh.password")); init(); + myAdditionalLbl.setForeground(UIUtil.getInactiveTextColor()); } protected JComponent createCenterPanel() { @@ -52,4 +55,8 @@ public class SshPasswordDialog extends DialogWrapper{ public JComponent getPreferredFocusedComponent() { return myPasswordField; } + + public void setAdditionalText(final String text) { + myAdditionalLbl.setText(text); + } } diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/common/CvsCommandOperation.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/common/CvsCommandOperation.java index f19f785f6750..b2cbb8dfb7c1 100644 --- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/common/CvsCommandOperation.java +++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/common/CvsCommandOperation.java @@ -244,7 +244,7 @@ public abstract class CvsCommandOperation extends CvsOperation implements IFileI } catch (AuthenticationException e) { if (! root.isOffline()) { - ApplicationManager.getApplication().invokeLater(new Runnable() { + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { final LoginPerformer.MyForRootProvider performer = new LoginPerformer.MyForRootProvider(Collections.singletonList(root), new Consumer() { @@ -257,6 +257,7 @@ public abstract class CvsCommandOperation extends CvsOperation implements IFileI performer.loginAll(ModalityContextImpl.NON_MODAL); } }); + return; } throw root.processException(new CommandException(e, "Authentication problem")); } diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseClasspathStorageProvider.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseClasspathStorageProvider.java index 8668f3876f42..ede4a8be0074 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseClasspathStorageProvider.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseClasspathStorageProvider.java @@ -206,7 +206,7 @@ public class EclipseClasspathStorageProvider implements ClasspathStorageProvider element = null; } - if (element != null || model.getSourceRoots().length > 0) { + if (element != null || model.getSourceRoots().length > 0 || model.getOrderEntries().length > 2) { classpathWriter.writeClasspath(classpathElement, element); fileSet.write(new Document(classpathElement), EclipseXml.CLASSPATH_FILE); } diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java index 1a195a0e0b4e..bfa1cdc646e6 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java @@ -17,13 +17,15 @@ package org.jetbrains.idea.eclipse.config; import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleComponent; import com.intellij.openapi.module.ModuleServiceManager; -import org.jetbrains.annotations.NotNull; -public class EclipseModuleManager implements ModuleComponent{ +import java.util.HashMap; +import java.util.Map; +public class EclipseModuleManager { private CachedXmlDocumentSet myDocumentSet; + private Map myEclipseVariablePaths = new HashMap(); + private static final String SRC_PREFIX = "src:"; public EclipseModuleManager(Module module) {} @@ -39,18 +41,19 @@ public class EclipseModuleManager implements ModuleComponent{ myDocumentSet = documentSet; } - public void projectOpened() {} - - public void projectClosed() {} - - public void moduleAdded() {} - - @NotNull - public String getComponentName() { - return "EclipseModuleManager"; + public void registerEclipseVariablePath(String path, String var) { + myEclipseVariablePaths.put(path, var); } - public void initComponent() {} + public void registerEclipseSrcVariablePath(String path, String var) { + myEclipseVariablePaths.put(SRC_PREFIX + path, var); + } - public void disposeComponent() {} + public String getEclipseVariablePath(String path) { + return myEclipseVariablePaths.get(path); + } + + public String getEclipseSrcVariablePath(String path) { + return myEclipseVariablePaths.get(SRC_PREFIX + path); + } } diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java index 10a203cf9696..6284a6e65ca0 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathReader.java @@ -44,6 +44,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.eclipse.EclipseXml; import org.jetbrains.idea.eclipse.IdeaXml; +import org.jetbrains.idea.eclipse.config.EclipseModuleManager; import org.jetbrains.idea.eclipse.util.ErrorLog; import java.io.File; @@ -199,8 +200,10 @@ public class EclipseClasspathReader { clsPath = null; } usedVariables.add(clsVar); - final String url = PathMacroManager.getInstance(rootModel.getModule()).expandPath(getVariableRelatedPath(clsVar, clsPath)); - modifiableModel.addRoot(getUrl(url), OrderRootType.CLASSES); + + final String url = getUrl(PathMacroManager.getInstance(rootModel.getModule()).expandPath(getVariableRelatedPath(clsVar, clsPath))); + EclipseModuleManager.getInstance(rootModel.getModule()).registerEclipseVariablePath(url, path); + modifiableModel.addRoot(url, OrderRootType.CLASSES); final String srcPathAttr = element.getAttributeValue(EclipseXml.SOURCEPATH_ATTR); if (srcPathAttr != null) { @@ -218,8 +221,9 @@ public class EclipseClasspathReader { srcPath = null; } usedVariables.add(srcVar); - final String srcUrl = PathMacroManager.getInstance(rootModel.getModule()).expandPath(getVariableRelatedPath(srcVar, srcPath)); - modifiableModel.addRoot(getUrl(srcUrl), OrderRootType.SOURCES); + final String srcUrl = getUrl(PathMacroManager.getInstance(rootModel.getModule()).expandPath(getVariableRelatedPath(srcVar, srcPath))); + EclipseModuleManager.getInstance(rootModel.getModule()).registerEclipseSrcVariablePath(srcUrl, srcPathAttr); + modifiableModel.addRoot(srcUrl, OrderRootType.SOURCES); } final List docPaths = getJavadocAttribute(element); diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java index cf71b7650dd5..2fab1abd444f 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java @@ -20,8 +20,6 @@ */ package org.jetbrains.idea.eclipse.conversion; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; @@ -30,7 +28,6 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.ProjectRootManagerImpl; import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.text.CharFilter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; @@ -42,6 +39,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.eclipse.EclipseXml; import org.jetbrains.idea.eclipse.IdeaXml; +import org.jetbrains.idea.eclipse.config.EclipseModuleManager; import java.io.File; import java.util.ArrayList; @@ -107,27 +105,29 @@ public class EclipseClasspathWriter { setExported(orderEntry, libraryOrderEntry); } else { - final Project project = myModel.getModule().getProject(); - final String[] kind = new String[]{EclipseXml.LIB_KIND}; - String relativeClassPath = getRelativePath(files[0], kind); - - final String[] srcFiles = libraryOrderEntry.getUrls(OrderRootType.SOURCES); - final String relativePath; - if (srcFiles.length == 0) { - relativePath = null; + final String eclipseVariablePath = EclipseModuleManager.getInstance(libraryOrderEntry.getOwnerModule()).getEclipseVariablePath(files[0]); + final Element orderEntry; + if (eclipseVariablePath != null) { + orderEntry = addOrderEntry(EclipseXml.VAR_KIND, eclipseVariablePath, classpathRoot, oldRoot); } else { - final String[] srcKind = new String[1]; - final boolean replaceVarsInSrc = Comparing.strEqual(kind[0], EclipseXml.VAR_KIND); - relativePath = getRelativePath(srcFiles[srcFiles.length - 1], srcKind, replaceVarsInSrc, project, getContentRoot()); - if (replaceVarsInSrc && srcKind[0] == null) { - kind[0] = EclipseXml.LIB_KIND; - relativeClassPath = getRelativePath(files[0], kind, false, project, getContentRoot()); - } + orderEntry = addOrderEntry(EclipseXml.LIB_KIND, getRelativePath(files[0]), classpathRoot, oldRoot); } - final Element orderEntry = addOrderEntry(kind[0], relativeClassPath, classpathRoot, oldRoot); - setOrRemoveAttribute(orderEntry, EclipseXml.SOURCEPATH_ATTR, relativePath); + final String srcRelativePath; + final String eclipseSrcVariablePath; + + final String[] srcFiles = libraryOrderEntry.getUrls(OrderRootType.SOURCES); + if (srcFiles.length == 0) { + srcRelativePath = null; + eclipseSrcVariablePath = null; + } + else { + final String lastSourceRoot = srcFiles[srcFiles.length - 1]; + srcRelativePath = getRelativePath(lastSourceRoot); + eclipseSrcVariablePath = EclipseModuleManager.getInstance(libraryOrderEntry.getOwnerModule()).getEclipseSrcVariablePath(lastSourceRoot); + } + setOrRemoveAttribute(orderEntry, EclipseXml.SOURCEPATH_ATTR, eclipseSrcVariablePath != null ? eclipseSrcVariablePath : srcRelativePath); //clear javadocs before write new final List children = new ArrayList(orderEntry.getChildren(EclipseXml.ATTRIBUTES_TAG)); @@ -179,19 +179,9 @@ public class EclipseClasspathWriter { } } - private String getRelativePath(String srcFile, String[] kind) { - return getRelativePath(srcFile, kind, true, myModel.getModule().getProject(), getContentRoot()); - } - private String getRelativePath(String url) { - return getRelativePath(url, new String[1]); - } - - public static String getRelativePath(final String url, - String[] kind, - boolean replaceVars, - final Project project, - final VirtualFile contentRoot) { + final Project project = myModel.getModule().getProject(); + final VirtualFile contentRoot = getContentRoot(); final VirtualFile projectBaseDir = contentRoot != null ? contentRoot.getParent() : project.getBaseDir(); assert projectBaseDir != null; VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url); @@ -219,7 +209,7 @@ public class EclipseClasspathWriter { return "/" + VfsUtil.getRelativePath(file, projectBaseDir, '/'); } else { - return replaceVars ? stripIDEASpecificPrefix(url, kind) : ProjectRootManagerImpl.extractLocalPath(url); + return ProjectRootManagerImpl.extractLocalPath(url); } } else { @@ -234,7 +224,7 @@ public class EclipseClasspathWriter { return url.substring(projectUrl.length()); //leading / } - return replaceVars ? stripIDEASpecificPrefix(url, kind) : ProjectRootManagerImpl.extractLocalPath(url); + return ProjectRootManagerImpl.extractLocalPath(url); } } @@ -291,23 +281,6 @@ public class EclipseClasspathWriter { } } - private static String stripIDEASpecificPrefix(String path, String[] kind) { - String stripped = StringUtil - .strip(ProjectRootManagerImpl.extractLocalPath(PathMacroManager.getInstance(ApplicationManager.getApplication()).collapsePath(path)), - new CharFilter() { - public boolean accept(final char ch) { - return ch != '$'; - } - }); - boolean leaveLeadingSlash = false; - if (!Comparing.strEqual(stripped, ProjectRootManagerImpl.extractLocalPath(path))) { - leaveLeadingSlash = kind[0] == null; - kind[0] = EclipseXml.VAR_KIND; - } - return (leaveLeadingSlash ? "/" : "") + stripped; - } - - private static Element addOrderEntry(String kind, String path, Element classpathRoot, Element oldRoot) { if (oldRoot != null) { for (Object o : oldRoot.getChildren(EclipseXml.CLASSPATHENTRY_TAG)) { diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java index 23c0da2aeb0b..2988afab6d80 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java @@ -38,8 +38,8 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.InputValidator; import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Ref; @@ -319,31 +319,29 @@ public class EclipseImportBuilder extends ProjectImportBuilder implement } } if (!unknownLibraries.isEmpty()) { - if (message.length() > 0) message.append("\n"); - message.append(EclipseBundle.message("eclipse.import.warning.undefinded.libraries")); + final StringBuffer buf = new StringBuffer(); + buf.append(""); + buf.append(EclipseBundle.message("eclipse.import.warning.undefinded.libraries")); for (String name : unknownLibraries) { - message.append("\n").append(name); + buf.append("
").append(name); } if (model == null) { - message.append("\nPlease export Eclipse user libraries and import them now from"); - final String pathToUserLibraries = Messages.showInputDialog(project, message.toString(), getTitle(), Messages.getErrorIcon(), - project.getBaseDir().getPath() + - "/" + - project.getName() + - ".userlibraries", new InputValidator() { - public boolean checkInput(String inputString) { - return new File(inputString).exists(); - } - - public boolean canClose(String inputString) { - return checkInput(inputString); - } - }); - if (pathToUserLibraries != null) { + buf.append("
Please export Eclipse user libraries and import them now from resulted .userlibraries file"); + buf.append(""); + final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) { + @Override + public boolean isFileSelectable(VirtualFile file) { + return super.isFileSelectable(file) && Comparing.strEqual(file.getExtension(), "userlibraries"); + } + }; + descriptor.setDescription(buf.toString()); + descriptor.setTitle(getTitle()); + final VirtualFile[] selectedFiles = FileChooser.chooseFiles(project, descriptor, project.getBaseDir()); + if (selectedFiles.length == 1) { ApplicationManager.getApplication().runWriteAction(new Runnable() { public void run() { try { - EclipseUserLibrariesHelper.readProjectLibrariesContent(new File(pathToUserLibraries), project, unknownLibraries); + EclipseUserLibrariesHelper.readProjectLibrariesContent(new File(selectedFiles[0].getPath()), project, unknownLibraries); } catch (Exception e) { LOG.error(e); @@ -351,7 +349,6 @@ public class EclipseImportBuilder extends ProjectImportBuilder implement } }); } - return result; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java index 16cc3970e105..6c429fdebf05 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerBase.java @@ -56,6 +56,8 @@ import com.intellij.util.PathUtil; import com.intellij.util.PathsList; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.groovy.compiler.rt.CompilerMessage; import org.jetbrains.groovy.compiler.rt.GroovycRunner; import org.jetbrains.plugins.groovy.GroovyFileType; @@ -137,7 +139,9 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler { try { File fileWithParameters = File.createTempFile("toCompile", ""); - fillFileWithGroovycParameters(toCompile, fileWithParameters, outputDir, patchers, getMainOutput(compileContext, module, tests)); + final VirtualFile finalOutputDir = getMainOutput(compileContext, module, tests); + LOG.assertTrue(finalOutputDir != null, "No output directory for module " + module.getName() + (tests ? " tests" : " production")); + fillFileWithGroovycParameters(toCompile, fileWithParameters, outputDir, patchers, finalOutputDir); commandLine.addParameter(forStubs ? "stubs" : "groovyc"); commandLine.addParameter(fileWithParameters.getPath()); @@ -206,6 +210,7 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler { } } + @Nullable protected static VirtualFile getMainOutput(CompileContext compileContext, Module module, boolean tests) { return tests ? compileContext.getModuleOutputDirectoryForTests(module) : compileContext.getModuleOutputDirectory(module); } @@ -222,7 +227,8 @@ public abstract class GroovyCompilerBase implements TranslatingCompiler { return CompilerMessageCategory.ERROR; } - private void fillFileWithGroovycParameters(List virtualFiles, File f, VirtualFile outputDir, final List patchers, VirtualFile finalOutputDir) { + private void fillFileWithGroovycParameters(List virtualFiles, File f, VirtualFile outputDir, final List patchers, + @NotNull VirtualFile finalOutputDir) { if (LOG.isDebugEnabled()) { LOG.debug("Running groovyc on: " + virtualFiles.toString()); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.form b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.form index 1eaf3812dfd2..90a9f505b22f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.form +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.form @@ -8,7 +8,7 @@ - + @@ -37,6 +37,14 @@ + + + + + + + +
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.java index 54df775d2767..1af3db22ef53 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfigurable.java @@ -43,6 +43,7 @@ public class GroovyCompilerConfigurable implements SearchableConfigurable, Compi private JTextField myHeapSize; private JPanel myMainPanel; private JPanel myExcludesPanel; + private JCheckBox myUseGroovycStubs; private ExcludedEntriesConfigurable myExcludes; private final GroovyCompilerConfiguration myConfig; @@ -100,16 +101,20 @@ public class GroovyCompilerConfigurable implements SearchableConfigurable, Compi } public boolean isModified() { - return !Comparing.equal(myConfig.getHeapSize(), myHeapSize.getText()) || myExcludes.isModified(); + return !Comparing.equal(myConfig.getHeapSize(), myHeapSize.getText()) || + myExcludes.isModified() || + myConfig.isUseGroovycStubs() != myUseGroovycStubs.isSelected(); } public void apply() throws ConfigurationException { myExcludes.apply(); myConfig.setHeapSize(myHeapSize.getText()); + myConfig.setUseGroovycStubs(myUseGroovycStubs.isSelected()); } public void reset() { myHeapSize.setText(myConfig.getHeapSize()); + myUseGroovycStubs.setSelected(myConfig.isUseGroovycStubs()); myExcludes.reset(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfiguration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfiguration.java index 41b602735a4b..dfc2534355c8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfiguration.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompilerConfiguration.java @@ -36,11 +36,13 @@ import org.jdom.Element; ) public class GroovyCompilerConfiguration implements PersistentStateComponent, Disposable { private String myHeapSize = "400"; + private boolean myUseGroovycStubs = false; private final ExcludedEntriesConfiguration myExcludeFromStubGeneration = new ExcludedEntriesConfiguration(); public MyStateBean getState() { final MyStateBean bean = new MyStateBean(); bean.heapSize = myHeapSize; + bean.useGroovycStubs = myUseGroovycStubs; myExcludeFromStubGeneration.writeExternal(bean.excludes); return bean; } @@ -55,11 +57,7 @@ public class GroovyCompilerConfiguration implements PersistentStateComponent(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.JAVA)), - new HashSet(Arrays.asList(StdFileTypes.JAVA))); - } else { - GroovyToJavaGenerator generator = new GroovyToJavaGenerator(myProject); - compilerManager.addCompiler(generator); - compilerManager.addCompilationStatusListener(generator); - } + compilerManager.addTranslatingCompiler(new GroovycStubGenerator(myProject), + new HashSet(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.JAVA)), + new HashSet(Arrays.asList(StdFileTypes.JAVA))); + + GroovyToJavaGenerator generator = new GroovyToJavaGenerator(myProject); + compilerManager.addCompiler(generator); + compilerManager.addCompilationStatusListener(generator); compilerManager.addTranslatingCompiler(new GroovyCompiler(myProject), new HashSet(Arrays.asList(GroovyFileType.GROOVY_FILE_TYPE, StdFileTypes.CLASS)), diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java index 8241a74a4773..d30851a9e138 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovyToJavaGenerator.java @@ -114,6 +114,10 @@ public class GroovyToJavaGenerator implements SourceGeneratingCompiler, Compilat } public GenerationItem[] getGenerationItems(CompileContext context) { + if (GroovyCompilerConfiguration.getInstance(myProject).isUseGroovycStubs()) { + return new GenerationItem[0]; + } + myContext = context; List generationItems = new ArrayList(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java index a02a2b9ec3b6..235964624085 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/generator/GroovycStubGenerator.java @@ -24,9 +24,9 @@ import com.intellij.openapi.compiler.CompileScope; import com.intellij.openapi.compiler.CompilerPaths; import com.intellij.openapi.compiler.ex.CompileContextEx; import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -47,7 +47,6 @@ import java.util.List; * @author peter */ public class GroovycStubGenerator extends GroovyCompilerBase { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.compiler.generator.GroovycStubGenerator"); public GroovycStubGenerator(Project project) { super(project); @@ -55,8 +54,26 @@ public class GroovycStubGenerator extends GroovyCompilerBase { @Override public void compile(CompileContext compileContext, Chunk moduleChunk, VirtualFile[] virtualFiles, OutputSink sink) { + if (!GroovyCompilerConfiguration.getInstance(myProject).isUseGroovycStubs()) { + return; + } + final CompileScope scope = compileContext.getCompileScope(); - if (scope.getFiles(StdFileTypes.JAVA, true).length == 0) { + final VirtualFile[] javaFiles = scope.getFiles(StdFileTypes.JAVA, true); + if (javaFiles.length == 0) { + return; + } + + boolean hasJava = false; + for (VirtualFile javaFile : javaFiles) { + final Module module = ModuleUtil.findModuleForFile(javaFile, myProject); + if (module != null && moduleChunk.containsNode(module)) { + hasJava = true; + break; + } + } + + if (!hasJava) { return; } @@ -103,7 +120,6 @@ public class GroovycStubGenerator extends GroovyCompilerBase { if (!hasJava) { //always pass groovyc stub generator at least 1 java file, or it won't generate stubs - //todo not needed anymore with groovy 1.7? toCompile.add(createMockJavaFile(rootPath)); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/ui/GroovyFacetEditor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/ui/GroovyFacetEditor.java index 6abc0e7a4acc..4033da5fcca7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/ui/GroovyFacetEditor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/ui/GroovyFacetEditor.java @@ -26,8 +26,9 @@ import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContaine import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.ui.DocumentAdapter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,7 +37,6 @@ import org.jetbrains.plugins.groovy.config.LibraryManager; import org.jetbrains.plugins.groovy.util.GroovyUtils; import javax.swing.*; -import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -65,7 +65,6 @@ public class GroovyFacetEditor { private JComboBox myComboBox; private JRadioButton myExistingSdk; private JRadioButton myNewSdk; - private AbstractGroovyLibraryManager myChosenManager; private final Class myAcceptableManager; public GroovyFacetEditor(@Nullable Project project) { @@ -164,7 +163,15 @@ public class GroovyFacetEditor { @Nullable public AbstractGroovyLibraryManager getChosenManager() { if (addNewSdk()) { - return myChosenManager; + final String path = getNewSdkPath(); + if (path != null) { + final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(FileUtil.toSystemIndependentName(path)); + if (file != null && file.isDirectory()) { + return findManager(file); + } + } + + return null; } final Object selectedItem = myComboBox.getSelectedItem(); if (selectedItem != null && selectedItem instanceof Pair) { @@ -178,13 +185,6 @@ public class GroovyFacetEditor { } private void configureSdkPathField(@Nullable final Project project) { - mySdkPath.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - myChosenManager = null; - } - }); - mySdkPath.getButton().addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent e) { @@ -202,7 +202,6 @@ public class GroovyFacetEditor { if (files.length > 0) { final VirtualFile dir = files[0]; mySdkPath.setText(FileUtil.toSystemDependentName(dir.getPath())); - myChosenManager = findManager(dir); } } }); @@ -211,11 +210,22 @@ public class GroovyFacetEditor { @Nullable private static AbstractGroovyLibraryManager findManager(VirtualFile dir) { - for (AbstractGroovyLibraryManager manager : AbstractGroovyLibraryManager.EP_NAME.getExtensions()) { + if (GroovyUtils.getFilesInDirectoryByPattern(dir.getPath() + "/lib", "groovy.*\\.jar").length == 0) { + return null; + } + + final String name = dir.getName(); + + final AbstractGroovyLibraryManager[] managers = AbstractGroovyLibraryManager.EP_NAME.getExtensions(); + for (final AbstractGroovyLibraryManager manager : managers) { + if (StringUtil.startsWithIgnoreCase(name, manager.getLibraryPrefix())) { + return manager; + } + } + + for (final AbstractGroovyLibraryManager manager : managers) { if (manager.isSDKHome(dir)) { - if (GroovyUtils.getFilesInDirectoryByPattern(dir.getPath() + "/lib", "groovy.*\\.jar").length > 0) { - return manager; - } + return manager; } } return null; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gradle/GradleScriptType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gradle/GradleScriptType.java index de7cd8b904c3..5016ccab5373 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gradle/GradleScriptType.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gradle/GradleScriptType.java @@ -41,9 +41,12 @@ import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; import org.jetbrains.plugins.groovy.extensions.GroovyScriptType; import org.jetbrains.plugins.groovy.gant.GantUtils; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; +import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrShiftExpressionImpl; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.runner.GroovyScriptRunConfiguration; import org.jetbrains.plugins.groovy.runner.GroovyScriptRunner; @@ -80,10 +83,9 @@ public class GradleScriptType extends GroovyScriptType { pp = pp.getParent(); parent = parent.getParent(); } - if (pp != null && parent instanceof GrMethodCallExpression && PsiUtil.isMethodCall((GrMethodCallExpression)parent, "createTask")) { - final GrExpression[] arguments = ((GrMethodCallExpression)parent).getArgumentList().getExpressionArguments(); - if (arguments.length > 0 && arguments[0] instanceof GrLiteral && ((GrLiteral)arguments[0]).getValue() instanceof String) { - String target = (String)((GrLiteral)arguments[0]).getValue(); + if (pp != null) { + String target = getTaskTarget(parent); + if (target != null) { configuration.scriptParams = target; configuration.setName(configuration.getName() + "." + target); } @@ -95,6 +97,37 @@ public class GradleScriptType extends GroovyScriptType { } } + private String getTaskTarget(PsiElement parent) { + String target = null; + if (isCreateTaskMethod(parent)) { + final GrExpression[] arguments = ((GrMethodCallExpression)parent).getArgumentList().getExpressionArguments(); + if (arguments.length > 0 && arguments[0] instanceof GrLiteral && ((GrLiteral)arguments[0]).getValue() instanceof String) { + target = (String)((GrLiteral)arguments[0]).getValue(); + } + } + else if (parent instanceof GrApplicationStatement) { + PsiElement shiftExpression = parent.getChildren()[1].getChildren()[0]; + if (shiftExpression instanceof GrShiftExpressionImpl) { + PsiElement shiftiesChild = shiftExpression.getChildren()[0]; + if (shiftiesChild instanceof GrReferenceExpression) { + target = shiftiesChild.getText(); + } + else if (shiftiesChild instanceof GrMethodCallExpression) { + target = shiftiesChild.getChildren()[0].getText(); + } + } + else if (shiftExpression instanceof GrMethodCallExpression) { + target = shiftExpression.getChildren()[0].getText(); + } + } + + return target; + } + + private boolean isCreateTaskMethod(PsiElement parent) { + return parent instanceof GrMethodCallExpression && PsiUtil.isMethodCall((GrMethodCallExpression)parent, "createTask"); + } + @Override public GroovyScriptRunner getRunner() { return new GroovyScriptRunner() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java index f91b4f875526..a94b827e8cc3 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java @@ -85,22 +85,14 @@ public abstract class TokenSets implements GroovyTokenTypes { kDOUBLE ); - public static TokenSet KEYWORD_REFERENCE_NAMES = TokenSet.orSet(TokenSet.create( - kCLASS, - kIN, - kAS, - kDEF, - kIF, - kELSE, - kFOR, - kWHILE, - kSWITCH, - kTRY, - kCATCH, - kFINALLY, - kSTATIC, - kDEFAULT - ), BUILT_IN_TYPE); + /** + * all keywords except 'this' and 'super' + */ + public static TokenSet KEYWORD_REFERENCE_NAMES = TokenSet + .create(kPACKAGE, kIMPORT, kSTATIC, kDEF, kCLASS, kINTERFACE, kENUM, kEXTENDS, kSUPER, kVOID, kBOOLEAN, kBYTE, kCHAR, kSHORT, kINT, + kFLOAT, kLONG, kDOUBLE, kAS, kPRIVATE, kPUBLIC, kPROTECTED, kTRANSIENT, kNATIVE, kSYNCHRONIZED, kVOLATILE, kDEFAULT, kTHROWS, + kIMPLEMENTS, kIF, kELSE, kWHILE, kSWITCH, kFOR, kIN, kRETURN, kBREAK, kCONTINUE, kTHROW, kASSERT, kCASE, kTRY, kFINALLY, kCATCH, + kINSTANCEOF, kNEW, kTRUE, kNULL); public static final TokenSet PROPERTY_NAMES = TokenSet.create(mIDENT, mSTRING_LITERAL, mGSTRING_LITERAL); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java index 31eaa0a19fb8..e90f8d248f8f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunConfiguration.java @@ -60,7 +60,7 @@ public class GroovyScriptRunConfiguration extends ModuleBasedConfiguration(getProject()) { - @Override - protected void run(Result result) throws Throwable { - final ModifiableModuleModel moduleModel = ModuleManager.getInstance(getProject()).getModifiableModel(); - moduleModel.newModule("dependent/dependent.iml", StdModuleTypes.JAVA); - moduleModel.commit(); - - final Module dep = ModuleManager.getInstance(getProject()).findModuleByName("dependent"); - final ModifiableRootModel model = ModuleRootManager.getInstance(dep).getModifiableModel(); - model.addModuleOrderEntry(myModule); - final VirtualFile depRoot = myFixture.getTempDirFixture().getFile("dependent"); - final ContentEntry entry = model.addContentEntry(depRoot); - entry.addSourceFolder(depRoot, false); - model.setSdk(ModuleRootManager.getInstance(myModule).getSdk()); - - //model.getModuleExtension(CompilerModuleExtension.class).inheritCompilerOutputPath(true); - - model.commit(); - result.setResult(dep); - } - }.execute().getResultObject(); - return dep; - } - - private void deleteClassFile(final String className) throws IOException { - new WriteCommandAction(getProject()) { - protected void run(Result result) throws Throwable { - final CompilerModuleExtension extension = ModuleRootManager.getInstance(myModule).getModuleExtension(CompilerModuleExtension.class); - //noinspection ConstantConditions - extension.getCompilerOutputPath().findChild(className + ".class").delete(this); - } - }.execute(); - } - - private static void touch(VirtualFile file) throws IOException { - file.setBinaryContent(file.contentsToByteArray(), file.getModificationStamp() + 1, file.getTimeStamp() + 1); - } - - private static void setFileText(final PsiFile file, final String barText) throws IOException { - Runnable runnable = new Runnable() { - public void run() { - try { - VfsUtil.saveText(ObjectUtils.assertNotNull(file.getVirtualFile()), barText); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - }; - ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.NON_MODAL); - - } - - private List make() { - final Semaphore semaphore = new Semaphore(); - semaphore.down(); - final ErrorReportingCallback callback = new ErrorReportingCallback(semaphore); - CompilerManager.getInstance(getProject()).make(callback); - semaphore.waitFor(); - callback.throwException(); - return callback.getMessages(); - } - - /* - private void compile(VirtualFile... files) { - final Semaphore semaphore = new Semaphore(); - semaphore.down(); - final ErrorReportingCallback callback = new ErrorReportingCallback(semaphore); - CompilerManager.getInstance(getProject()).compile(files, new ErrorReportingCallback(semaphore), false); - semaphore.waitFor(); - callback.throwException(); - } - */ - - private void assertOutput(String className, String output) throws ExecutionException { - assertOutput(className, output, myModule); - } - - private void assertOutput(String className, String output, final Module module) throws ExecutionException { - final ApplicationConfiguration configuration = - new ApplicationConfiguration("app", getProject(), ApplicationConfigurationType.getInstance()); - configuration.setModule(module); - configuration.setMainClassName(className); - final DefaultRunExecutor extension = Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultRunExecutor.class); - final ExecutionEnvironment environment = new ExecutionEnvironment(configuration, new RunnerSettings(null, null),null, DataManager.getInstance().getDataContext()); - final DefaultJavaProgramRunner runner = ProgramRunner.PROGRAM_RUNNER_EP.findExtension(DefaultJavaProgramRunner.class); - final StringBuffer sb = new StringBuffer(); - final Semaphore semaphore = new Semaphore(); - semaphore.down(); - runner.execute(extension, environment, new ProgramRunner.Callback() { - public void processStarted(RunContentDescriptor descriptor) { - final ProcessHandler handler = descriptor.getProcessHandler(); - - assert handler != null; - handler.addProcessListener(new ProcessAdapter() { - public void onTextAvailable(ProcessEvent event, Key outputType) { - if (ProcessOutputTypes.SYSTEM != outputType) { - sb.append(event.getText()); - } - } - - @Override - public void processTerminated(ProcessEvent event) { - semaphore.up(); - } - }); - } - }); - semaphore.waitFor(); - assertEquals(output.trim(), StringUtil.convertLineSeparators(sb.toString().trim())); - } - - private static class ErrorReportingCallback implements CompileStatusNotification { - private final Semaphore mySemaphore; - private Throwable myError; - private List myMessages = new ArrayList(); - - public ErrorReportingCallback(Semaphore semaphore) { - mySemaphore = semaphore; - } - - public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { - try { - assertFalse("Code did not compile!", aborted); - for (CompilerMessageCategory category : CompilerMessageCategory.values()) { - for (CompilerMessage message : compileContext.getMessages(category)) { - final String msg = message.getMessage(); - if (category != CompilerMessageCategory.INFORMATION || !msg.startsWith("Compilation completed successfully")) { - myMessages.add(category + ": " + msg); - } - } - } - if (errors > 0) { - fail("Compiler errors occurred! " + StringUtil.join(myMessages, "\n")); - } - } - catch (Throwable t) { - myError = t; - } - finally { - mySemaphore.up(); - } - } - - void throwException() { - if (myError != null) { - throw new RuntimeException(myError); - } - } - - public List getMessages() { - return myMessages; - } - } -} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyCompilerTestCase.java new file mode 100644 index 000000000000..1478526fa023 --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyCompilerTestCase.java @@ -0,0 +1,258 @@ +package org.jetbrains.plugins.groovy.lang; + +import com.intellij.compiler.CompilerManagerImpl; +import com.intellij.execution.ExecutionException; +import com.intellij.execution.Executor; +import com.intellij.execution.application.ApplicationConfiguration; +import com.intellij.execution.application.ApplicationConfigurationType; +import com.intellij.execution.configurations.RunnerSettings; +import com.intellij.execution.executors.DefaultRunExecutor; +import com.intellij.execution.impl.DefaultJavaProgramRunner; +import com.intellij.execution.process.ProcessAdapter; +import com.intellij.execution.process.ProcessEvent; +import com.intellij.execution.process.ProcessHandler; +import com.intellij.execution.process.ProcessOutputTypes; +import com.intellij.execution.runners.ExecutionEnvironment; +import com.intellij.execution.runners.ProgramRunner; +import com.intellij.execution.ui.RunContentDescriptor; +import com.intellij.ide.DataManager; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.compiler.*; +import com.intellij.openapi.module.ModifiableModuleModel; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.module.StdModuleTypes; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.util.JDOMExternalizable; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.PsiTestUtil; +import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; +import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; +import com.intellij.testFramework.fixtures.TempDirTestFixture; +import com.intellij.testFramework.fixtures.impl.TempDirTestFixtureImpl; +import com.intellij.util.ObjectUtils; +import com.intellij.util.concurrency.Semaphore; +import org.jetbrains.plugins.groovy.compiler.GroovyCompilerLoader; +import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; +import org.jetbrains.plugins.groovy.util.GroovyUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * @author peter + */ +public class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestCase { + private TempDirTestFixture myMainOutput; + + @Override + protected void setUp() throws Exception { + myMainOutput = new TempDirTestFixtureImpl(); + myMainOutput.setUp(); + super.setUp(); + getProject().getComponent(GroovyCompilerLoader.class).projectOpened(); + CompilerManagerImpl.testSetup(); + + CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(myMainOutput.findOrCreateDir("out").getUrl()); + + addGroovyLibrary(myModule); + } + + @Override + protected void tuneFixture(JavaModuleFixtureBuilder moduleBuilder) throws Exception { + moduleBuilder.setMockJdkLevel(JavaModuleFixtureBuilder.MockJdkLevel.jdk15); + super.tuneFixture(moduleBuilder); + } + + protected static void addGroovyLibrary(final Module to) { + final String root = PathManager.getHomePath() + "/community/lib/"; + final File[] groovyJars = GroovyUtils.getFilesInDirectoryByPattern(root, GroovyConfigUtils.GROOVY_ALL_JAR_PATTERN); + assert groovyJars.length == 1; + PsiTestUtil.addLibrary(to, "groovy", root, groovyJars[0].getName()); + } + + @Override + protected void tearDown() throws Exception { + myMainOutput.tearDown(); + myMainOutput = null; + super.tearDown(); + } + + protected void setupTestSources() { + new WriteCommandAction(getProject()) { + protected void run(Result result) throws Throwable { + final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule); + final ModifiableRootModel rootModel = rootManager.getModifiableModel(); + final ContentEntry entry = rootModel.getContentEntries()[0]; + entry.removeSourceFolder(entry.getSourceFolders()[0]); + entry.addSourceFolder(myFixture.getTempDirFixture().findOrCreateDir("src"), false); + entry.addSourceFolder(myFixture.getTempDirFixture().findOrCreateDir("tests"), true); + rootModel.commit(); + } + }.execute(); + } + + protected Module addDependentModule() { + Module dep = new WriteCommandAction(getProject()) { + @Override + protected void run(Result result) throws Throwable { + final ModifiableModuleModel moduleModel = ModuleManager.getInstance(getProject()).getModifiableModel(); + moduleModel.newModule("dependent/dependent.iml", StdModuleTypes.JAVA); + moduleModel.commit(); + + final Module dep = ModuleManager.getInstance(getProject()).findModuleByName("dependent"); + final ModifiableRootModel model = ModuleRootManager.getInstance(dep).getModifiableModel(); + model.addModuleOrderEntry(myModule); + final VirtualFile depRoot = myFixture.getTempDirFixture().getFile("dependent"); + final ContentEntry entry = model.addContentEntry(depRoot); + entry.addSourceFolder(depRoot, false); + model.setSdk(ModuleRootManager.getInstance(myModule).getSdk()); + + //model.getModuleExtension(CompilerModuleExtension.class).inheritCompilerOutputPath(true); + + model.commit(); + result.setResult(dep); + } + }.execute().getResultObject(); + return dep; + } + + protected void deleteClassFile(final String className) throws IOException { + new WriteCommandAction(getProject()) { + protected void run(Result result) throws Throwable { + final CompilerModuleExtension extension = ModuleRootManager.getInstance(myModule).getModuleExtension(CompilerModuleExtension.class); + //noinspection ConstantConditions + extension.getCompilerOutputPath().findChild(className + ".class").delete(this); + } + }.execute(); + } + + protected static void touch(VirtualFile file) throws IOException { + file.setBinaryContent(file.contentsToByteArray(), file.getModificationStamp() + 1, file.getTimeStamp() + 1); + } + + protected static void setFileText(final PsiFile file, final String barText) throws IOException { + Runnable runnable = new Runnable() { + public void run() { + try { + VfsUtil.saveText(ObjectUtils.assertNotNull(file.getVirtualFile()), barText); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + ApplicationManager.getApplication().invokeAndWait(runnable, ModalityState.NON_MODAL); + + } + + protected void setFileName(final PsiFile bar, final String name) { + new WriteCommandAction(getProject()) { + protected void run(Result result) throws Throwable { + bar.setName(name); + } + }.execute(); + } + + protected List make() { + final Semaphore semaphore = new Semaphore(); + semaphore.down(); + final ErrorReportingCallback callback = new ErrorReportingCallback(semaphore); + CompilerManager.getInstance(getProject()).make(callback); + semaphore.waitFor(); + callback.throwException(); + return callback.getMessages(); + } + + protected void assertOutput(String className, String output) throws ExecutionException { + assertOutput(className, output, myModule); + } + + protected void assertOutput(String className, String output, final Module module) throws ExecutionException { + final ApplicationConfiguration configuration = + new ApplicationConfiguration("app", getProject(), ApplicationConfigurationType.getInstance()); + configuration.setModule(module); + configuration.setMainClassName(className); + final DefaultRunExecutor extension = Executor.EXECUTOR_EXTENSION_NAME.findExtension(DefaultRunExecutor.class); + final ExecutionEnvironment environment = new ExecutionEnvironment(configuration, new RunnerSettings(null, null),null, DataManager + .getInstance().getDataContext()); + final DefaultJavaProgramRunner runner = ProgramRunner.PROGRAM_RUNNER_EP.findExtension(DefaultJavaProgramRunner.class); + final StringBuffer sb = new StringBuffer(); + final Semaphore semaphore = new Semaphore(); + semaphore.down(); + runner.execute(extension, environment, new ProgramRunner.Callback() { + public void processStarted(RunContentDescriptor descriptor) { + final ProcessHandler handler = descriptor.getProcessHandler(); + + assert handler != null; + handler.addProcessListener(new ProcessAdapter() { + public void onTextAvailable(ProcessEvent event, Key outputType) { + if (ProcessOutputTypes.SYSTEM != outputType) { + sb.append(event.getText()); + } + } + + @Override + public void processTerminated(ProcessEvent event) { + semaphore.up(); + } + }); + } + }); + semaphore.waitFor(); + assertEquals(output.trim(), StringUtil.convertLineSeparators(sb.toString().trim())); + } + + private static class ErrorReportingCallback implements CompileStatusNotification { + private final Semaphore mySemaphore; + private Throwable myError; + private List myMessages = new ArrayList(); + + public ErrorReportingCallback(Semaphore semaphore) { + mySemaphore = semaphore; + } + + public void finished(boolean aborted, int errors, int warnings, final CompileContext compileContext) { + try { + assertFalse("Code did not compile!", aborted); + for (CompilerMessageCategory category : CompilerMessageCategory.values()) { + for (CompilerMessage message : compileContext.getMessages(category)) { + final String msg = message.getMessage(); + if (category != CompilerMessageCategory.INFORMATION || !msg.startsWith("Compilation completed successfully")) { + myMessages.add(category + ": " + msg); + } + } + } + if (errors > 0) { + fail("Compiler errors occurred! " + StringUtil.join(myMessages, "\n")); + } + } + catch (Throwable t) { + myError = t; + } + finally { + mySemaphore.up(); + } + } + + void throwException() { + if (myError != null) { + throw new RuntimeException(myError); + } + } + + public List getMessages() { + return myMessages; + } + } +} diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/TextSplitter.java b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/TextSplitter.java index f12b64eb5aad..39286a1407b8 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/inspections/TextSplitter.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/inspections/TextSplitter.java @@ -15,6 +15,7 @@ */ package com.intellij.spellchecker.inspections; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.codeStyle.NameUtil; @@ -72,6 +73,7 @@ public class TextSplitter { List results = new ArrayList(); String[] pieces = text.substring(i).split(WORD_SPLITTER); for (String s : pieces) { + ProgressManager.checkCanceled(); if (s.length() > 0) { int p1 = text.indexOf(s, i); TextRange range = TextRange.from(p1, s.length()); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthEquals.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthEquals.java new file mode 100644 index 000000000000..ec1e9f09ddb9 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthEquals.java @@ -0,0 +1,58 @@ +/* + * 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.jetbrains.idea.svn; + +import com.intellij.openapi.util.Comparing; +import org.tmatesoft.svn.core.auth.*; + +public class SvnAuthEquals { + private SvnAuthEquals() { + } + + public static boolean equals(final SVNAuthentication a1, final SVNAuthentication a2) { + if (a1 == a2) return true; + if (a1 == null || a2 == null) return false; + if (! Comparing.equal(a1.getKind(), a2.getKind())) return false; + if (! Comparing.equal(a1.getUserName(), a2.getUserName())) return false; + + final Class a1Class = a1.getClass(); + if (! a1Class.equals(a2.getClass())) return false; + + if (SVNUserNameAuthentication.class.equals(a1Class)) return true; + if (SVNPasswordAuthentication.class.equals(a1Class)) { + return Comparing.equal(((SVNPasswordAuthentication) a1).getPassword(), ((SVNPasswordAuthentication) a2).getPassword()); + } + if (SVNSSLAuthentication.class.equals(a1Class)) { + if (! Comparing.equal(((SVNSSLAuthentication) a1).getCertificateFile(), ((SVNSSLAuthentication) a2).getCertificateFile())) return false; + return Comparing.equal(((SVNSSLAuthentication) a1).getPassword(), ((SVNSSLAuthentication) a2).getPassword()); + } + if (SVNSSHAuthentication.class.equals(a1Class)) { + if (! Comparing.equal(((SVNSSHAuthentication) a1).getPrivateKeyFile(), ((SVNSSHAuthentication) a2).getPrivateKeyFile())) return false; + if (! Comparing.equal(((SVNSSHAuthentication) a1).getPassphrase(), ((SVNSSHAuthentication) a2).getPassphrase())) return false; + if (! Comparing.equal(((SVNSSHAuthentication) a1).getPortNumber(), ((SVNSSHAuthentication) a2).getPortNumber())) return false; + return Comparing.equal(((SVNSSHAuthentication) a1).getPassword(), ((SVNSSHAuthentication) a2).getPassword()); + } + return false; + } + + public static int hashCode(final SVNAuthentication a) { + int result = a.getKind().hashCode(); + if (a.getUserName() != null) { + result = (31 * result) + a.getUserName().hashCode(); + } + return result; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index 31d2e8f789d7..4d6b92ade4db 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier; import com.intellij.openapi.ui.MessageType; +import com.intellij.util.containers.SoftHashMap; import com.intellij.util.net.HttpConfigurable; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; @@ -60,11 +61,14 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager { } private static class PersistentAuthenticationProviderProxy implements ISVNAuthenticationProvider, IPersistentAuthenticationProvider { + private final Map myRewritePreventer; + private static final long ourRefreshInterval = 6000 * 1000; private final ISVNAuthenticationProvider myDelegate; private Project myProject; private PersistentAuthenticationProviderProxy(final ISVNAuthenticationProvider delegate) { myDelegate = delegate; + myRewritePreventer = new SoftHashMap(); } public void setProject(Project project) { @@ -83,7 +87,13 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager { public void saveAuthentication(final SVNAuthentication auth, final String kind, final String realm) throws SVNException { try { - ((IPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, kind, realm); + final SvnAuthWrapperEqualable newKey = new SvnAuthWrapperEqualable(auth); + final Long recent = myRewritePreventer.get(newKey); + final long currTime = System.currentTimeMillis(); + if (recent == null || ((recent != null) && ((currTime - recent.longValue()) > ourRefreshInterval))) { + ((IPersistentAuthenticationProvider) myDelegate).saveAuthentication(auth, kind, realm); + myRewritePreventer.put(newKey, currTime); + } } catch (final SVNException e) { // show notification so that user was aware his credentials were not saved @@ -280,4 +290,25 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager { } return null; } + + private static class SvnAuthWrapperEqualable extends Wrapper { + private SvnAuthWrapperEqualable(SVNAuthentication svnAuthentication) { + super(svnAuthentication); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (this == obj) return true; + if (obj instanceof SvnAuthWrapperEqualable) { + return SvnAuthEquals.equals(this.getT(), ((SvnAuthWrapperEqualable) obj).getT()); + } + return false; + } + + @Override + public int hashCode() { + return SvnAuthEquals.hashCode(getT()); + } + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java index f08e31f0768b..537249cef472 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java @@ -28,11 +28,13 @@ import com.intellij.openapi.vcs.changes.ui.ChangesViewBalloonProblemNotifier; import com.intellij.openapi.vcs.impl.GenericNotifierImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; import org.tmatesoft.svn.core.SVNAuthenticationException; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.auth.SVNAuthentication; import org.tmatesoft.svn.core.internal.util.SVNURLUtil; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNWCClient; @@ -59,7 +61,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl resultRef = new Ref(); final boolean done = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { public void run() { - final boolean result = interactiveValidation(obj.myProject, obj.getUrl()); + final boolean result = interactiveValidation(obj.myProject, obj.getUrl(), obj.getRealm(), obj.getKind()); log("ask result for: " + obj.getUrl() + " is: " + result); resultRef.set(result); if (result) { @@ -71,12 +73,13 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl outdatedRequests = new LinkedList(); + /*final List outdatedRequests = new LinkedList(); final Collection keys = getAllCurrentKeys(); for (SVNURL key : keys) { final SVNURL commonURLAncestor = SVNURLUtil.getCommonURLAncestor(key, obj.getUrl()); if ((! StringUtil.isEmptyOrSpaces(commonURLAncestor.getHost())) && (! StringUtil.isEmptyOrSpaces(commonURLAncestor.getPath()))) { - if (passiveValidation(myVcs.getProject(), key)) { + final AuthenticationRequest currObj = getObj(key); + if ((currObj != null) && passiveValidation(myVcs.getProject(), key, true, currObj.getRealm(), currObj.getKind())) { outdatedRequests.add(key); } } @@ -88,7 +91,7 @@ public class SvnAuthenticationNotifier extends GenericNotifierImpl { + private final T myT; + + public Wrapper(T t) { + myT = t; + } + + public T getT() { + return myT; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java index 35ef8e3207bc..7b9964eb6f1b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.ui.GuiUtils; import com.intellij.util.SystemProperties; import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNURL; @@ -32,17 +33,38 @@ import java.lang.reflect.InvocationTargetException; public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationProvider { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider"); private final Project myProject; + private static ThreadLocal myCallState = new ThreadLocal(); + private final SvnVcs myVcs; public SvnInteractiveAuthenticationProvider(final SvnVcs vcs) { + myVcs = vcs; myProject = vcs.getProject(); } + public static void clearCallState() { + myCallState.set(null); + } + + public static boolean wasCalled() { + return myCallState.get() != null && myCallState.get().isWasCalled(); + } + + public static boolean wasCancelled() { + return myCallState.get() != null && myCallState.get().isWasCancelled(); + } + public SVNAuthentication requestClientAuthentication(String kind, final SVNURL url, final String realm, SVNErrorMessage errorMessage, final SVNAuthentication previousAuth, final boolean authMayBeStored) { + final MyCallState callState = new MyCallState(true, false); + myCallState.set(callState); + // once we came here, we don't know _correct_ auth todo +- + final SvnConfiguration configuration = SvnConfiguration.getInstance(myProject); + configuration.clearCredentials(kind, realm); + final SVNAuthentication[] result = new SVNAuthentication[1]; Runnable command = null; @@ -146,6 +168,7 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP } log("3 authentication result: " + result[0]); } + callState.setWasCancelled(result[0] == null); return result[0]; } @@ -157,4 +180,26 @@ public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationP private void log(final String s) { LOG.debug(s); } + + public static class MyCallState { + private boolean myWasCalled; + private boolean myWasCancelled; + + public MyCallState(boolean wasCalled, boolean wasCancelled) { + myWasCalled = wasCalled; + myWasCancelled = wasCancelled; + } + + public boolean isWasCalled() { + return myWasCalled; + } + + public boolean isWasCancelled() { + return myWasCancelled; + } + + public void setWasCancelled(boolean wasCancelled) { + myWasCancelled = wasCancelled; + } + } } diff --git a/resources/src/idea/IdeaActions.xml b/resources/src/idea/IdeaActions.xml index eb8474183030..25b0ceb66668 100644 --- a/resources/src/idea/IdeaActions.xml +++ b/resources/src/idea/IdeaActions.xml @@ -182,6 +182,8 @@ + +