diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java b/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java new file mode 100644 index 000000000000..e977a7be6a46 --- /dev/null +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java @@ -0,0 +1,172 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.util.importProject; + +import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; +import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil; +import com.intellij.lexer.JavaLexer; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.module.StdModuleTypes; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.JavaTokenType; +import com.intellij.util.Consumer; +import com.intellij.util.StringBuilderSpinAllocator; +import com.intellij.util.text.CharArrayCharSequence; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public class JavaModuleInsight extends ModuleInsight { + private final JavaLexer myLexer; + + public JavaModuleInsight(@Nullable final ProgressIndicator progress, + Set existingModuleNames, + Set existingProjectLibraryNames) { + super(progress, existingModuleNames, existingProjectLibraryNames); + myLexer = new JavaLexer(LanguageLevel.JDK_1_5); + } + + @Override + protected boolean isSourceFile(final File file) { + return StringUtil.endsWithIgnoreCase(file.getName(), ".java"); + } + + @Override + protected boolean isLibraryFile(final String fileName) { + return StringUtil.endsWithIgnoreCase(fileName, ".jar") || StringUtil.endsWithIgnoreCase(fileName, ".zip"); + } + + @Override + protected void scanSourceFileForImportedPackages(final char[] chars, final Consumer result) { + myLexer.start(new CharArrayCharSequence(chars)); + + JavaSourceRootDetectionUtil.skipWhiteSpaceAndComments(myLexer); + if (myLexer.getTokenType() == JavaTokenType.PACKAGE_KEYWORD) { + advanceLexer(myLexer); + if (readPackageName(chars, myLexer) == null) { + return; + } + } + + while (true) { + if (myLexer.getTokenType() == JavaTokenType.SEMICOLON) { + advanceLexer(myLexer); + } + if (myLexer.getTokenType() != JavaTokenType.IMPORT_KEYWORD) { + return; + } + advanceLexer(myLexer); + + boolean isStaticImport = false; + if (myLexer.getTokenType() == JavaTokenType.STATIC_KEYWORD) { + isStaticImport = true; + advanceLexer(myLexer); + } + + final String packageName = readPackageName(chars, myLexer); + if (packageName == null) { + return; + } + + if (packageName.endsWith(".*")) { + result.consume(packageName.substring(0, packageName.length() - ".*".length())); + } + else { + int lastDot = packageName.lastIndexOf('.'); + if (lastDot > 0) { + String _packageName = packageName.substring(0, lastDot); + if (isStaticImport) { + lastDot = _packageName.lastIndexOf('.'); + if (lastDot > 0) { + result.consume(_packageName.substring(0, lastDot)); + } + } + else { + result.consume(_packageName); + } + } + } + } + } + + @Nullable + private static String readPackageName(final char[] text, final Lexer lexer) { + final StringBuilder buffer = StringBuilderSpinAllocator.alloc(); + try { + while (true) { + if (lexer.getTokenType() != JavaTokenType.IDENTIFIER && lexer.getTokenType() != JavaTokenType.ASTERISK) { + break; + } + buffer.append(text, lexer.getTokenStart(), lexer.getTokenEnd() - lexer.getTokenStart()); + + advanceLexer(lexer); + if (lexer.getTokenType() != JavaTokenType.DOT) { + break; + } + buffer.append('.'); + + advanceLexer(lexer); + } + + String packageName = buffer.toString(); + if (packageName.length() == 0 || StringUtil.endsWithChar(packageName, '.') || StringUtil.startsWithChar(packageName, '*')) { + return null; + } + return packageName; + } + finally { + StringBuilderSpinAllocator.dispose(buffer); + } + } + + private static void advanceLexer(final Lexer lexer) { + lexer.advance(); + JavaSourceRootDetectionUtil.skipWhiteSpaceAndComments(lexer); + } + + @Override + protected void scanLibraryForDeclaredPackages(File file, Consumer result) throws IOException { + final ZipFile zip = new ZipFile(file); + try { + final Enumeration entries = zip.entries(); + while (entries.hasMoreElements()) { + final String entryName = entries.nextElement().getName(); + if (StringUtil.endsWithIgnoreCase(entryName, ".class")) { + final int index = entryName.lastIndexOf('/'); + if (index > 0) { + final String packageName = entryName.substring(0, index).replace('/', '.'); + result.consume(packageName); + } + } + } + } + finally { + zip.close(); + } + } + + protected ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, final Collection sourceRoots) { + return new ModuleDescriptor(moduleContentRoot, StdModuleTypes.JAVA, sourceRoots); + } +} diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/LibrariesLayoutPanel.java b/java/idea-ui/src/com/intellij/ide/util/importProject/LibrariesLayoutPanel.java index 6e3b1982f0f5..1ee617e031e3 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/LibrariesLayoutPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/LibrariesLayoutPanel.java @@ -91,7 +91,7 @@ public class LibrariesLayoutPanel extends ProjectLayoutPanel{ } protected String getStepDescriptionText() { - return "Please review libraries found. At this stage you may set library names that will be used in the project,\n" + + return "Please review libraries found. At this stage you can set library names that will be used in the project,\n" + "exclude particular libraries from the project, or move jar files between the libraries."; } } diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java index 1abed77d29b7..7df7198649b4 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java @@ -16,8 +16,8 @@ package com.intellij.ide.util.importProject; import com.intellij.ide.highlighter.ModuleFileType; -import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot; import com.intellij.ide.util.projectWizard.ModuleBuilder; +import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.roots.ModifiableRootModel; @@ -37,7 +37,7 @@ import java.util.*; */ public class ModuleDescriptor { private String myName; - private final MultiMap myContentToSourceRoots = new MultiMap(); + private final MultiMap myContentToSourceRoots = new MultiMap(); private final Set myLibraryFiles = new HashSet(); private final Set myDependencies = new HashSet(); private static final String[] ourModuleNameStoplist = new String[] { @@ -47,14 +47,14 @@ public class ModuleDescriptor { private List myConfigurationUpdaters = new SmartList(); private ModuleType myModuleType; - public ModuleDescriptor(final File contentRoot, final ModuleType moduleType, final Collection sourceRoots) { + public ModuleDescriptor(final File contentRoot, final ModuleType moduleType, final Collection sourceRoots) { myName = suggestModuleName(contentRoot); myContentToSourceRoots.putValues(contentRoot, sourceRoots); myModuleType = moduleType; } public ModuleDescriptor(final File contentRoot, final ModuleType moduleType, - final JavaModuleSourceRoot sourceRoot) { + final DetectedProjectRoot sourceRoot) { this(contentRoot, moduleType, Collections.singletonList(sourceRoot)); } @@ -110,23 +110,23 @@ public class ModuleDescriptor { return Collections.unmodifiableSet(myContentToSourceRoots.keySet()); } - public Collection getSourceRoots() { + public Collection getSourceRoots() { return myContentToSourceRoots.values(); } - public Collection getSourceRoots(File contentRoot) { + public Collection getSourceRoots(File contentRoot) { return myContentToSourceRoots.get(contentRoot); } public void addContentRoot(File contentRoot) { - myContentToSourceRoots.put(contentRoot, new HashSet()); + myContentToSourceRoots.put(contentRoot, new HashSet()); } - public Collection removeContentRoot(File contentRoot) { + public Collection removeContentRoot(File contentRoot) { return myContentToSourceRoots.remove(contentRoot); } - public void addSourceRoot(final File contentRoot, JavaModuleSourceRoot sourceRoot) { + public void addSourceRoot(final File contentRoot, DetectedProjectRoot sourceRoot) { myContentToSourceRoots.putValue(contentRoot, sourceRoot); } @@ -156,7 +156,7 @@ public class ModuleDescriptor { public String toString() { @NonNls final StringBuilder builder = new StringBuilder(); builder.append("[Module: ").append(getContentRoots()).append(" | "); - for (JavaModuleSourceRoot sourceRoot : getSourceRoots()) { + for (DetectedProjectRoot sourceRoot : getSourceRoots()) { builder.append(sourceRoot.getDirectory().getName()).append(","); } builder.append("]"); diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java index 5b6b56cf4bd8..82d8dacda5b3 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java @@ -15,48 +15,39 @@ */ package com.intellij.ide.util.importProject; -import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil; -import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot; -import com.intellij.lexer.JavaLexer; -import com.intellij.lexer.Lexer; +import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; +import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.JavaTokenType; +import com.intellij.util.Consumer; import com.intellij.util.StringBuilderSpinAllocator; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.StringInterner; -import com.intellij.util.text.CharArrayCharSequence; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * @author Eugene Zhuravlev * Date: Jul 3, 2007 */ -public class ModuleInsight { +public abstract class ModuleInsight { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.importProject.ModuleInsight"); @NotNull private final ProgressIndicatorWrapper myProgress; private final Set myEntryPointRoots = new HashSet(); - private final List mySourceRoots = new ArrayList(); + private final List mySourceRoots = new ArrayList(); private final Set myIgnoredNames = new HashSet(); private final Map> mySourceRootToReferencedPackagesMap = new HashMap>(); private final Map> mySourceRootToPackagesMap = new HashMap>(); private final Map> myJarToPackagesMap = new HashMap>(); private final StringInterner myInterner = new StringInterner(); - private final JavaLexer myLexer; private List myModules; private List myLibraries; @@ -66,12 +57,11 @@ public class ModuleInsight { public ModuleInsight(@Nullable final ProgressIndicator progress, Set existingModuleNames, Set existingProjectLibraryNames) { myExistingModuleNames = existingModuleNames; myExistingProjectLibraryNames = existingProjectLibraryNames; - myLexer = new JavaLexer(LanguageLevel.JDK_1_5); myProgress = new ProgressIndicatorWrapper(progress); - setRoots(Collections.emptyList(), Collections.emptyList(), Collections.emptySet()); + setRoots(Collections.emptyList(), Collections.emptyList(), Collections.emptySet()); } - public final void setRoots(final List contentRoots, final List sourceRoots, final Set ignoredNames) { + public final void setRoots(final List contentRoots, final List sourceRoots, final Set ignoredNames) { myModules = null; myLibraries = null; @@ -105,8 +95,8 @@ public class ModuleInsight { try { myProgress.pushState(); - List processedRoots = new ArrayList(); - for (JavaModuleSourceRoot root : mySourceRoots) { + List processedRoots = new ArrayList(); + for (DetectedProjectRoot root : mySourceRoots) { final File sourceRoot = root.getDirectory(); if (myIgnoredNames.contains(sourceRoot.getName())) { continue; @@ -119,7 +109,7 @@ public class ModuleInsight { final HashSet selfPackages = new HashSet(); mySourceRootToPackagesMap.put(sourceRoot, selfPackages); - scanSources(sourceRoot, root.getPackagePrefix(), usedPackages, selfPackages) ; + scanSources(sourceRoot, ProjectFromSourcesBuilderImpl.getPackagePrefix(root), usedPackages, selfPackages) ; usedPackages.removeAll(selfPackages); processedRoots.add(root); } @@ -127,7 +117,7 @@ public class ModuleInsight { myProgress.pushState(); myProgress.setText("Building modules layout..."); - for (JavaModuleSourceRoot sourceRoot : processedRoots) { + for (DetectedProjectRoot sourceRoot : processedRoots) { final File srcRoot = sourceRoot.getDirectory(); final File moduleContentRoot = myEntryPointRoots.contains(srcRoot)? srcRoot : srcRoot.getParentFile(); ModuleDescriptor moduleDescriptor = contentRootToModules.get(moduleContentRoot); @@ -135,7 +125,7 @@ public class ModuleInsight { moduleDescriptor.addSourceRoot(moduleContentRoot, sourceRoot); } else { - moduleDescriptor = new ModuleDescriptor(moduleContentRoot, StdModuleTypes.JAVA, sourceRoot); + moduleDescriptor = createModuleDescriptor(moduleContentRoot, Collections.singletonList(sourceRoot)); contentRootToModules.put(moduleContentRoot, moduleDescriptor); } } @@ -156,6 +146,8 @@ public class ModuleInsight { } } + protected abstract ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, Collection sourceRoots); + private void buildModuleDependencies(final Map contentRootToModules) { final Set moduleContentRoots = contentRootToModules.keySet(); @@ -170,11 +162,11 @@ public class ModuleInsight { if (checkedModule.equals(aModule)) { continue; // avoid self-dependencies } - final Collection aModuleRoots = aModule.getSourceRoots(); + final Collection aModuleRoots = aModule.getSourceRoots(); checkModules: - for (JavaModuleSourceRoot srcRoot: checkedModule.getSourceRoots()) { + for (DetectedProjectRoot srcRoot: checkedModule.getSourceRoots()) { final Set referencedBySourceRoot = mySourceRootToReferencedPackagesMap.get(srcRoot.getDirectory()); - for (JavaModuleSourceRoot aSourceRoot : aModuleRoots) { + for (DetectedProjectRoot aSourceRoot : aModuleRoots) { if (ContainerUtil.intersects(referencedBySourceRoot, mySourceRootToPackagesMap.get(aSourceRoot.getDirectory()))) { checkedModule.addDependencyOn(aModule); break checkModules; @@ -188,7 +180,7 @@ public class ModuleInsight { private void buildJarDependencies(final ModuleDescriptor module) { for (File jarFile : myJarToPackagesMap.keySet()) { final Set jarPackages = myJarToPackagesMap.get(jarFile); - for (JavaModuleSourceRoot srcRoot : module.getSourceRoots()) { + for (DetectedProjectRoot srcRoot : module.getSourceRoots()) { if (ContainerUtil.intersects(mySourceRootToReferencedPackagesMap.get(srcRoot.getDirectory()), jarPackages)) { module.addLibraryFile(jarFile); break; @@ -238,8 +230,8 @@ public class ModuleInsight { public void merge(final ModuleDescriptor mainModule, final ModuleDescriptor module) { for (File contentRoot : module.getContentRoots()) { final File _contentRoot = appendContentRoot(mainModule, contentRoot); - final Collection sources = module.getSourceRoots(contentRoot); - for (JavaModuleSourceRoot source : sources) { + final Collection sources = module.getSourceRoots(contentRoot); + for (DetectedProjectRoot source : sources) { mainModule.addSourceRoot(_contentRoot, source); } } @@ -279,13 +271,13 @@ public class ModuleInsight { public ModuleDescriptor splitModule(final ModuleDescriptor descriptor, String newModuleName, final Collection contentsToExtract) { ModuleDescriptor newModule = null; for (File root : contentsToExtract) { - final Collection sources = descriptor.removeContentRoot(root); + final Collection sources = descriptor.removeContentRoot(root); if (newModule == null) { - newModule = new ModuleDescriptor(root, StdModuleTypes.JAVA, sources != null ? sources : new HashSet()); + newModule = createModuleDescriptor(root, sources != null ? sources : new HashSet()); } else { if (sources != null && sources.size() > 0) { - for (JavaModuleSourceRoot source : sources) { + for (DetectedProjectRoot source : sources) { newModule.addSourceRoot(root, source); } } @@ -352,10 +344,10 @@ public class ModuleInsight { return moduleRoot; // no need to include a separate root } if (FileUtil.isAncestor(contentRoot, moduleRoot, true)) { - final Collection currentSources = module.getSourceRoots(moduleRoot); + final Collection currentSources = module.getSourceRoots(moduleRoot); module.removeContentRoot(moduleRoot); module.addContentRoot(contentRoot); - for (JavaModuleSourceRoot source : currentSources) { + for (DetectedProjectRoot source : currentSources) { module.addSourceRoot(contentRoot, source); } return contentRoot; // no need to include a separate root @@ -406,9 +398,9 @@ public class ModuleInsight { scanSources(file, subPackageName, usedPackages, selfPackages); } else { - if (StringUtil.endsWithIgnoreCase(file.getName(), ".java")) { + if (isSourceFile(file)) { includeParentName = true; - scanJavaFile(file, usedPackages); + scanSourceFile(file, usedPackages); } } } @@ -418,17 +410,25 @@ public class ModuleInsight { } } - private void scanJavaFile(File file, final Set usedPackages) { + protected abstract boolean isSourceFile(final File file); + + private void scanSourceFile(File file, final Set usedPackages) { myProgress.setText2(file.getName()); try { final char[] chars = FileUtil.loadFileText(file); - scanImportStatements(chars, myLexer, usedPackages); + scanSourceFileForImportedPackages(chars, new Consumer() { + public void consume(final String s) { + usedPackages.add(myInterner.intern(s)); + } + }); } catch (IOException e) { LOG.info(e); } } + protected abstract void scanSourceFileForImportedPackages(final char[] chars, Consumer result); + private void scanRootForLibraries(File fromRoot) { if (myIgnoredNames.contains(fromRoot.getName())) { return; @@ -442,137 +442,40 @@ public class ModuleInsight { } else { final String fileName = file.getName(); - if (StringUtil.endsWithIgnoreCase(fileName, ".jar") || StringUtil.endsWithIgnoreCase(fileName, ".zip")) { + if (isLibraryFile(fileName)) { if (!myJarToPackagesMap.containsKey(file)) { final HashSet libraryPackages = new HashSet(); myJarToPackagesMap.put(file, libraryPackages); - scanLibrary(file, libraryPackages); - } - } - } - } - } - } - - - private void scanLibrary(File file, Set libraryPackages) { - myProgress.pushState(); - myProgress.setText2(file.getName()); - try { - final ZipFile zip = new ZipFile(file); - try { - final Enumeration entries = zip.entries(); - while(entries.hasMoreElements()) { - final String entryName = entries.nextElement().getName(); - if (StringUtil.endsWithIgnoreCase(entryName, ".class")) { - final int index = entryName.lastIndexOf('/'); - if (index > 0) { - final String packageName = entryName.substring(0, index).replace('/', '.'); - if (!libraryPackages.contains(packageName)) { - libraryPackages.add(myInterner.intern(packageName)); + myProgress.pushState(); + myProgress.setText2(file.getName()); + try { + scanLibraryForDeclaredPackages(file, new Consumer() { + public void consume(final String s) { + if (!libraryPackages.contains(s)) { + libraryPackages.add(myInterner.intern(s)); + } + } + }); + } + catch (IOException e) { + LOG.info(e); + } + catch (InternalError e) { // indicates that file is somehow damaged and cannot be processed + LOG.info(e); + } + finally { + myProgress.popState(); } } } } } - finally { - zip.close(); - } - } - catch (IOException e) { - LOG.info(e); - } - catch (InternalError e) { // indicates that zip file is somehow damaged and cannot be processed - LOG.info(e); - } - finally { - myProgress.popState(); } } - private void scanImportStatements(char[] text, final Lexer lexer, final Set usedPackages){ - lexer.start(new CharArrayCharSequence(text)); + protected abstract boolean isLibraryFile(final String fileName); - JavaSourceRootDetectionUtil.skipWhiteSpaceAndComments(lexer); - if (lexer.getTokenType() == JavaTokenType.PACKAGE_KEYWORD) { - advanceLexer(lexer); - if (readPackageName(text, lexer) == null) { - return; - } - } + protected abstract void scanLibraryForDeclaredPackages(File file, Consumer result) throws IOException; - while (true) { - if (lexer.getTokenType() == JavaTokenType.SEMICOLON) { - advanceLexer(lexer); - } - if (lexer.getTokenType() != JavaTokenType.IMPORT_KEYWORD) { - return; - } - advanceLexer(lexer); - - boolean isStaticImport = false; - if (lexer.getTokenType() == JavaTokenType.STATIC_KEYWORD) { - isStaticImport = true; - advanceLexer(lexer); - } - - final String packageName = readPackageName(text, lexer); - if (packageName == null) { - return; - } - - if (packageName.endsWith(".*")) { - usedPackages.add(myInterner.intern(packageName.substring(0, packageName.length() - ".*".length()))); - } - else { - int lastDot = packageName.lastIndexOf('.'); - if (lastDot > 0) { - String _packageName = packageName.substring(0, lastDot); - if (isStaticImport) { - lastDot = _packageName.lastIndexOf('.'); - _packageName = lastDot > 0? _packageName.substring(0, lastDot) : null; - } - if (_packageName != null) { - usedPackages.add(myInterner.intern(_packageName)); - } - } - } - } - } - - @Nullable - private static String readPackageName(final char[] text, final Lexer lexer) { - final StringBuilder buffer = StringBuilderSpinAllocator.alloc(); - try { - while(true){ - if (lexer.getTokenType() != JavaTokenType.IDENTIFIER && lexer.getTokenType() != JavaTokenType.ASTERISK) { - break; - } - buffer.append(text, lexer.getTokenStart(), lexer.getTokenEnd() - lexer.getTokenStart()); - - advanceLexer(lexer); - if (lexer.getTokenType() != JavaTokenType.DOT) { - break; - } - buffer.append('.'); - - advanceLexer(lexer); - } - - String packageName = buffer.toString(); - if (packageName.length() == 0 || StringUtil.endsWithChar(packageName, '.') || StringUtil.startsWithChar(packageName, '*') ) { - return null; - } - return packageName; - } - finally { - StringBuilderSpinAllocator.dispose(buffer); - } - } - - private static void advanceLexer(final Lexer lexer) { - lexer.advance(); - JavaSourceRootDetectionUtil.skipWhiteSpaceAndComments(lexer); - } } diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesLayoutPanel.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesLayoutPanel.java index bbcf40401cbd..3f566660d325 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesLayoutPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesLayoutPanel.java @@ -107,7 +107,7 @@ public class ModulesLayoutPanel extends ProjectLayoutPanel{ } protected String getStepDescriptionText() { - return "Please review suggested module structure for the project. At this stage you may set module names,\n" + + return "Please review suggested module structure for the project. At this stage you can set module names,\n" + "exclude particular modules from the project, merge or split individual modules.\n" + "All dependencies between the modules as well as dependencies on the libraries will be automatically updated."; } diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ProjectLayoutPanel.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ProjectLayoutPanel.java index e0daec0ec018..7ae726c961d7 100644 --- a/java/idea-ui/src/com/intellij/ide/util/importProject/ProjectLayoutPanel.java +++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ProjectLayoutPanel.java @@ -16,7 +16,7 @@ package com.intellij.ide.util.importProject; import com.intellij.ide.util.ElementsChooser; -import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot; +import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.InputValidator; @@ -263,11 +263,11 @@ abstract class ProjectLayoutPanel extends JPanel { builder.append(")"); } - final Collection sourceRoots = moduleDescriptor.getSourceRoots(); + final Collection sourceRoots = moduleDescriptor.getSourceRoots(); if (sourceRoots.size() > 0) { builder.append(" ["); - for (Iterator it = sourceRoots.iterator(); it.hasNext();) { - JavaModuleSourceRoot root = it.next(); + for (Iterator it = sourceRoots.iterator(); it.hasNext();) { + DetectedProjectRoot root = it.next(); builder.append(root.getDirectory().getName()); if (it.hasNext()) { builder.append(","); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java index d853f811e613..bbffb7efa215 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java @@ -77,43 +77,6 @@ public class JavaSourceRootDetectionUtil { } - @Nullable - public static Pair suggestRootForJavaFile(File javaFile, File topmostPossibleRoot, NullableFunction packageNameFetcher) { - if (!javaFile.isFile()) return null; - - final CharSequence chars; - try { - chars = new CharArrayCharSequence(FileUtil.loadFileText(javaFile)); - } - catch(IOException e){ - return null; - } - - String packageName = packageNameFetcher.fun(chars); - if (packageName != null) { - File root = javaFile.getParentFile(); - int index = packageName.length(); - while (index > 0) { - int index1 = packageName.lastIndexOf('.', index - 1); - String token = packageName.substring(index1 + 1, index); - String dirName = root.getName(); - final boolean equalsToToken = SystemInfo.isFileSystemCaseSensitive ? dirName.equals(token) : dirName.equalsIgnoreCase(token); - if (!equalsToToken || root.equals(topmostPossibleRoot)) { - return Pair.create(root, packageName.substring(0, index)); - } - String parent = root.getParent(); - if (parent == null) { - return null; - } - root = new File(parent); - index = index1; - } - return Pair.create(root, ""); - } - - return null; - } - @Nullable public static String getPackageName(CharSequence text) { Lexer lexer = new JavaLexer(LanguageLevel.JDK_1_3); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java index e557fc88ad6b..b22f8e35b417 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetector.java @@ -15,6 +15,7 @@ */ package com.intellij.ide.util.projectWizard.importSources; +import com.intellij.ide.util.projectWizard.importSources.util.CommonSourceRootDetectionUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.NullableFunction; @@ -36,7 +37,8 @@ public abstract class JavaSourceRootDetector extends ProjectStructureDetector { if (child.isFile()) { String extension = FileUtil.getExtension(child.getName()); if (extension.equals(fileExtension)) { - Pair root = JavaSourceRootDetectionUtil.suggestRootForJavaFile(child, base, getPackageNameFetcher()); + Pair root = CommonSourceRootDetectionUtil.suggestRootForFileWithPackageStatement(child, base, + getPackageNameFetcher()); if (root != null) { result.add(new JavaModuleSourceRoot(root.getFirst(), root.getSecond(), getLanguageName())); return DirectoryProcessingResult.skipChildrenAndParentsUpTo(root.getFirst()); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/JavaProjectStructureDetector.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/JavaProjectStructureDetector.java index bf26b2f2ee47..f230270c95fe 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/JavaProjectStructureDetector.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/JavaProjectStructureDetector.java @@ -17,10 +17,7 @@ package com.intellij.ide.util.projectWizard.importSources.impl; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.ide.util.DelegatingProgressIndicator; -import com.intellij.ide.util.importProject.LibrariesDetectionStep; -import com.intellij.ide.util.importProject.ModuleInsight; -import com.intellij.ide.util.importProject.ModulesDetectionStep; -import com.intellij.ide.util.importProject.ProjectDescriptor; +import com.intellij.ide.util.importProject.*; import com.intellij.ide.util.projectWizard.ModuleWizardStep; import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory; import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil; @@ -55,7 +52,7 @@ public class JavaProjectStructureDetector extends JavaSourceRootDetector { ProjectDescriptor projectDescriptor, Icon stepIcon) { final List steps = new ArrayList(); - final ModuleInsight moduleInsight = new ModuleInsight(new DelegatingProgressIndicator(), builder.getExistingModuleNames(), builder.getExistingProjectLibraryNames()); + final ModuleInsight moduleInsight = new JavaModuleInsight(new DelegatingProgressIndicator(), builder.getExistingModuleNames(), builder.getExistingProjectLibraryNames()); steps.add(new LibrariesDetectionStep(this, builder, projectDescriptor, moduleInsight, stepIcon, "reference.dialogs.new.project.fromCode.page1")); steps.add(new ModulesDetectionStep(this, builder, projectDescriptor, moduleInsight, stepIcon, "reference.dialogs.new.project.fromCode.page2")); steps.add(ProjectWizardStepFactory.getInstance().createProjectJdkStep(builder.getContext())); diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java index 1dbf1ead1b83..d7f56497e4f6 100644 --- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java @@ -290,12 +290,12 @@ public class ProjectFromSourcesBuilderImpl extends ProjectBuilder implements Pro VirtualFile moduleContentRoot = lfs.refreshAndFindFileByPath(FileUtil.toSystemIndependentName(contentRoot.getPath())); if (moduleContentRoot != null) { final ContentEntry contentEntry = rootModel.addContentEntry(moduleContentRoot); - final Collection sourceRoots = descriptor.getSourceRoots(contentRoot); - for (JavaModuleSourceRoot srcRoot : sourceRoots) { + final Collection sourceRoots = descriptor.getSourceRoots(contentRoot); + for (DetectedProjectRoot srcRoot : sourceRoots) { final String srcpath = FileUtil.toSystemIndependentName(srcRoot.getDirectory().getPath()); final VirtualFile sourceRoot = lfs.refreshAndFindFileByPath(srcpath); if (sourceRoot != null) { - contentEntry.addSourceFolder(sourceRoot, shouldBeTestRoot(srcRoot.getDirectory()), srcRoot.getPackagePrefix()); + contentEntry.addSourceFolder(sourceRoot, shouldBeTestRoot(srcRoot.getDirectory()), getPackagePrefix(srcRoot)); } } } @@ -321,6 +321,11 @@ public class ProjectFromSourcesBuilderImpl extends ProjectBuilder implements Pro } + public static String getPackagePrefix(final DetectedProjectRoot srcRoot) { + // TODO we can introduce DetectedProjectRootWithPackagePrefix interface + return srcRoot instanceof JavaModuleSourceRoot ? ((JavaModuleSourceRoot)srcRoot).getPackagePrefix() : ""; + } + @NotNull @Override public ProjectDescriptor getProjectDescriptor(@NotNull ProjectStructureDetector detector) { diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/util/CommonSourceRootDetectionUtil.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/util/CommonSourceRootDetectionUtil.java new file mode 100644 index 000000000000..7c4564170708 --- /dev/null +++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/util/CommonSourceRootDetectionUtil.java @@ -0,0 +1,71 @@ +/* + * Copyright 2000-2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.util.projectWizard.importSources.util; + +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.NullableFunction; +import com.intellij.util.text.CharArrayCharSequence; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; + +public class CommonSourceRootDetectionUtil { + + private CommonSourceRootDetectionUtil() { + } + + @Nullable + public static Pair suggestRootForFileWithPackageStatement(File file, + File topmostPossibleRoot, + NullableFunction packageNameFetcher) { + if (!file.isFile()) return null; + + final CharSequence chars; + try { + chars = new CharArrayCharSequence(FileUtil.loadFileText(file)); + } + catch(IOException e){ + return null; + } + + String packageName = packageNameFetcher.fun(chars); + if (packageName != null) { + File root = file.getParentFile(); + int index = packageName.length(); + while (index > 0) { + int index1 = packageName.lastIndexOf('.', index - 1); + String token = packageName.substring(index1 + 1, index); + String dirName = root.getName(); + final boolean equalsToToken = SystemInfo.isFileSystemCaseSensitive ? dirName.equals(token) : dirName.equalsIgnoreCase(token); + if (!equalsToToken || root.equals(topmostPossibleRoot)) { + return Pair.create(root, packageName.substring(0, index)); + } + String parent = root.getParent(); + if (parent == null) { + return null; + } + root = new File(parent); + index = index1; + } + return Pair.create(root, ""); + } + + return null; + } +} diff --git a/platform/lang-api/src/com/intellij/execution/filters/OpenFileHyperlinkInfo.java b/platform/lang-api/src/com/intellij/execution/filters/OpenFileHyperlinkInfo.java index 240cc7f96346..1aba19c8c268 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/OpenFileHyperlinkInfo.java +++ b/platform/lang-api/src/com/intellij/execution/filters/OpenFileHyperlinkInfo.java @@ -26,6 +26,9 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; public final class OpenFileHyperlinkInfo implements FileHyperlinkInfo { + + private static final int UNDEFINED_OFFSET = -1; + private final Project myProject; private final VirtualFile myFile; private final int myDocumentLine; @@ -49,7 +52,7 @@ public final class OpenFileHyperlinkInfo implements FileHyperlinkInfo { public OpenFileDescriptor getDescriptor() { int offset = calculateOffset(myFile, myDocumentLine, myDocumentColumn); - if (offset != -1) { + if (offset != UNDEFINED_OFFSET) { return new OpenFileDescriptor(myProject, myFile, offset); } // although document position != logical position, it seems better than returning 'null' @@ -67,6 +70,14 @@ public final class OpenFileHyperlinkInfo implements FileHyperlinkInfo { }); } + /** + * Calculates an offset, that matches given line and column of the document. + * + * @param file VirtualFile instance + * @param documentLine zero-based line of the document + * @param documentColumn zero-based column of the document + * @return calculated offset or UNDEFINED_OFFSET if it's impossible to calculate + */ private static int calculateOffset(@NotNull final VirtualFile file, final int documentLine, final int documentColumn) { return ApplicationManager.getApplication().runReadAction(new Computable() { @@ -83,7 +94,7 @@ public final class OpenFileHyperlinkInfo implements FileHyperlinkInfo { return lineStartOffset + fixedColumn; } } - return -1; + return UNDEFINED_OFFSET; } }); } diff --git a/java/java-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java similarity index 100% rename from java/java-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java rename to platform/lang-impl/src/com/intellij/codeInsight/unwrap/AbstractUnwrapper.java diff --git a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java index 9f5ebabc6f8f..46138e22e3f3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleConfigurationEditorProvider.java @@ -18,11 +18,12 @@ package com.intellij.openapi.module; import com.intellij.openapi.roots.ui.configuration.CommonContentEntriesEditor; import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationEditorProvider; import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState; +import com.intellij.openapi.util.Comparing; public class WebModuleConfigurationEditorProvider implements ModuleConfigurationEditorProvider { public ModuleConfigurationEditor[] createEditors(final ModuleConfigurationState state) { Module module = state.getRootModel().getModule(); - if (ModuleType.get(module) != WebModuleType.getInstance()) { + if (!Comparing.equal(ModuleType.get(module).getId(), WebModuleTypeBase.WEB_MODULE)) { return ModuleConfigurationEditor.EMPTY; } return new ModuleConfigurationEditor[]{new CommonContentEntriesEditor(module.getName(), state, false, false)}; diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java index ec976e30d5f5..e0cb7644c63e 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java @@ -675,6 +675,14 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec } // avoid documents piling up during batch processing if (FileDocumentManagerImpl.areTooManyDocumentsInTheQueue(myUncommittedDocuments)) { + if (ApplicationManager.getApplication().isUnitTestMode()) { + try { + LOG.error("Too many uncommitted documents for "+myProject + ":\n"+myUncommittedDocuments); + } + finally { + clearUncommitedDocuments(); + } + } commitAllDocuments(); } } diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java b/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java index b7a233b187be..8dbe2dc9bafa 100644 --- a/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java +++ b/platform/platform-api/src/com/intellij/openapi/diff/DirDiffManager.java @@ -22,8 +22,6 @@ import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.awt.event.WindowListener; - /** * @author Konstantin Bulenkov */ @@ -32,7 +30,7 @@ public abstract class DirDiffManager { return ServiceManager.getService(project, DirDiffManager.class); } - public abstract void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings, Runnable onWindowClose); + public abstract void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings, @Nullable Runnable onWindowClose); public abstract void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings); diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java index 1abcc3e33088..77a964fbbde8 100644 --- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java +++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java @@ -103,7 +103,7 @@ public abstract class ToolbarDecorator implements DataProvider, CommonActionsPan return new ListToolbarDecorator(list).initPositionAndBorder(); } - public static ToolbarDecorator createDecorator(@NotNull TableView table, ElementProducer producer) { + public static ToolbarDecorator createDecorator(@NotNull TableView table, @Nullable ElementProducer producer) { return new TableToolbarDecorator(table, producer).initPositionAndBorder(); } diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.form b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.form index 907c810e0f96..76747d1bc21c 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.form +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.form @@ -39,7 +39,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.java index 4402e1531ba4..d35aceef35b9 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.java +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroListEditor.java @@ -22,6 +22,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.text.StringTokenizer; import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; @@ -63,9 +65,20 @@ public class PathMacroListEditor { } }); + myPathMacroTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + public void valueChanged(final ListSelectionEvent e) { + updateButtons(); + } + }); + fillIgnoredVariables(); } + private void updateButtons() { + myEditButton.setEnabled(myPathMacroTable.getSelectedRowCount() == 1); + myRemoveButton.setEnabled(myPathMacroTable.getSelectedRowCount() > 0); + } + private void fillIgnoredVariables() { final Collection ignored = PathMacros.getInstance().getIgnoredMacroNames(); myIgnoredVariables.setText(StringUtil.join(ignored, ";")); @@ -106,6 +119,7 @@ public class PathMacroListEditor { public void reset() { myPathMacroTable.reset(); fillIgnoredVariables(); + updateButtons(); } public boolean isModified() { diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java index d617ffbaa59e..683cf659c365 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java @@ -78,7 +78,13 @@ public abstract class ResizeToolWindowAction extends AnAction implements DumbAwa } Component owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (owner == null || !(SwingUtilities.getWindowAncestor(owner) instanceof IdeFrame)) { + if (owner == null) { + setDisabled(e); + return; + } + + final Window windowAncestor = SwingUtilities.getWindowAncestor(owner); + if (!(windowAncestor instanceof IdeFrame) || windowAncestor instanceof IdeFrame.Child) { setDisabled(e); return; } diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index 82d2d33766e4..1eb7ee00396a 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -19,6 +19,8 @@ import com.intellij.CommonBundle; import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; import com.intellij.ide.highlighter.ProjectFileType; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.impl.stores.IProjectStore; import com.intellij.openapi.diagnostic.Logger; @@ -32,10 +34,7 @@ import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.wm.FocusCommand; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.openapi.wm.IdeFrame; -import com.intellij.openapi.wm.WindowManager; +import com.intellij.openapi.wm.*; import com.intellij.projectImport.ProjectOpenProcessor; import com.intellij.ui.AppIcon; import org.jdom.JDOMException; @@ -119,7 +118,22 @@ public class ProjectUtil { ProjectOpenProcessor provider = ProjectOpenProcessor.getImportProvider(virtualFile); if (provider != null) { - return provider.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame); + final Project project = provider.doOpenProject(virtualFile, projectToClose, forceOpenInNewFrame); + + if (project != null) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + public void run() { + if (!project.isDisposed()) { + final ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.PROJECT_VIEW); + if (toolWindow != null) { + toolWindow.activate(null); + } + } + } + }, ModalityState.NON_MODAL); + } + + return project; } return null; } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 02325b2d3141..11d31ef412d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -181,13 +181,27 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private static final boolean IS_UNDER_TEAMCITY = System.getProperty("bootstrap.testcases") != null; + + private static final boolean SHOULD_NOT_PERFORM_ACCESS_CHECK = System.getProperty("should.not.perform.access.check") != null; + private static final boolean IS_UNIT_TESTS = ApplicationManager.getApplication().isUnitTestMode(); + + private static final Collection additionalRoots = new THashSet(); + @TestOnly - public static void allowToAccess(@NotNull String root) { additionalRoots.add(FileUtil.toSystemIndependentName(root)); } + public static void allowToAccess(@NotNull String root) { + additionalRoots.add(FileUtil.toSystemIndependentName(root)); + } + @TestOnly private static void assertAccessInTests(VirtualFileSystemEntry child) { - if (IS_UNIT_TESTS && IS_UNDER_TEAMCITY && ApplicationManager.getApplication() instanceof ApplicationImpl && ((ApplicationImpl)ApplicationManager.getApplication()).isComponentsCreated()) { + if (IS_UNIT_TESTS && + IS_UNDER_TEAMCITY && + ApplicationManager.getApplication() instanceof ApplicationImpl && + ((ApplicationImpl)ApplicationManager.getApplication()).isComponentsCreated() + && + !SHOULD_NOT_PERFORM_ACCESS_CHECK) { NewVirtualFileSystem fileSystem = child.getFileSystem(); if (fileSystem != LocalFileSystem.getInstance() && fileSystem != JarFileSystem.getInstance()) { return; @@ -218,7 +232,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { if (!isUnder) { if (!allowed.isEmpty()) { - assert false : "File accessed outside allowed roots: " + child +";\n Allowed roots: "+new ArrayList(allowed); + assert false : "File accessed outside allowed roots: " + child + ";\n Allowed roots: " + new ArrayList(allowed); } } } @@ -271,6 +285,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { } private static boolean insideGettingRoots; + private static VirtualFile[] getAllRoots(Project project) { insideGettingRoots = true; Set roots = new THashSet(); @@ -366,7 +381,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { for (String name : names) { findChild(name, false, false, delegate); } - + // important: should return a copy here for safe iterations return new ArrayList(ensureAsMap().values()); } @@ -378,7 +393,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { return (VirtualFileSystemEntry[])myChildren; } - Pair pair = PersistentFS.listAll(this); + Pair pair = PersistentFS.listAll(this); final int[] childrenIds = pair.second; VirtualFileSystemEntry[] children; if (childrenIds.length == 0) { @@ -417,7 +432,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { if (loaded != null) { return loaded; } - + String name = ourPersistence.getName(id); return findChild(name, false, false, getFileSystem()); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 9500ffaba31d..ea2d1bc0be52 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -436,6 +436,7 @@ public final class InternalDecorator extends JPanel implements Queryable, TypeSa UISettings settings = UISettings.getInstance(); ToolWindowManagerImpl mgr = ((ToolWindowImpl)myWindow).getToolWindowManager(); + if (!mgr.isToolWindowRegistered(((ToolWindowImpl)myWindow).getId())) return new Insets(0, 0, 0, 0); List topIds = mgr.getIdsOn(ToolWindowAnchor.TOP); boolean topButtons = !settings.HIDE_TOOL_STRIPES && !topIds.isEmpty(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 972b583aaa14..59028eb5373d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -127,6 +127,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; private PropertyChangeListener myFocusListener; + public boolean isToolWindowRegistered(String id) { + return myLayout.isToolWindowRegistered(id); + } + private enum KeyState { waiting, pressed, released, hold } diff --git a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java index 8ff596a584ea..d1622f1e6eca 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/WizardPopup.java @@ -173,7 +173,10 @@ public abstract class WizardPopup extends AbstractPopup implements ActionListene ScreenUtil.moveRectangleToFitTheScreen(targetBounds); if (getParent() != null) { - if (getParent().getBounds().intersects(targetBounds)) { + final Rectangle parentBounds = getParent().getBounds(); + parentBounds.x += STEP_X_PADDING; + parentBounds.width -= STEP_X_PADDING * 2; + if (parentBounds.intersects(targetBounds)) { targetBounds.x = getParent().getBounds().x - targetBounds.width - STEP_X_PADDING; } } diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties index dfa8ddf80b29..5f4ba61a6ec7 100644 --- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties +++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties @@ -505,6 +505,7 @@ title.path.variables=Path Variables editbox.path.macro.value=Value: editbox.path.macro.name=Name: button.edit=&Edit +button.edit.dialog=&Edit... button.add=&Add... error.variable.already.exists=Variable with name {0} already exists column.name=Name diff --git a/platform/platform-resources-en/src/messages/ProjectBundle.properties b/platform/platform-resources-en/src/messages/ProjectBundle.properties index 6bf111b2b010..2133db0e581e 100644 --- a/platform/platform-resources-en/src/messages/ProjectBundle.properties +++ b/platform/platform-resources-en/src/messages/ProjectBundle.properties @@ -196,7 +196,7 @@ classpath.add.simple.module.library.action=Jars or directories... classpath.add.library.action=Library... classpath.add.module.dependency.action=Module Dependency... classpath.chooser.title.add.module.dependency=Choose Modules -classpath.chooser.description.add.module.dependency=Select the modules the current module should depend on +classpath.chooser.description.add.module.dependency=Select the modules the current module should depend on: classpath.title.adding.dependency=Adding dependency classpath.message.library.already.added=Library ''{0}'' already added to this module message.no.module.dependency.candidates=Found no modules to depend on @@ -315,7 +315,7 @@ project.roots.plain.mode.action.text.enabled=Show Module Groups project.roots.tooltip.library.has.broken.paths=Library ''{0}'' has broken {1, choice, 1#path|2#paths}. project.roots.error.message.invalid.roots=invalid {0} {1, choice, 1#root|2#roots} choose.modules.dialog.title=Choose Modules -choose.modules.dialog.description=Library '' {0}'' will be added to the selected modules. +choose.modules.dialog.description=Library ''{0}'' will be added to the selected modules. project.roots.javadoc.tab.description=Manage external JavaDocs attached to this module. External JavaDoc override JavaDoc annotations you might have in your module. project.roots.output.compiler.title=Compiler output project.roots.module.jdk.problem.message=Module SDK is not defined. diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java index a882ae689a06..907e71e81e84 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffManagerImpl.java @@ -26,7 +26,6 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; @@ -49,36 +48,30 @@ public class DirDiffManagerImpl extends DirDiffManager { final DirDiffTableModel model = new DirDiffTableModel(myProject, dir1, dir2, settings); if (settings.showInFrame) { DirDiffFrame frame = new DirDiffFrame(myProject, model); - if (onWindowClose != null) { - final JFrame jFrame = frame.getFrame(); - jFrame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - onWindowClose.run(); - jFrame.removeWindowListener(this); - } - }); - } + setWindowListener(onWindowClose, frame.getFrame()); frame.show(); } else { DirDiffDialog dirDiffDialog = new DirDiffDialog(myProject, model); if (myProject == null || myProject.isDefault()) { dirDiffDialog.setModal(true); } - if (onWindowClose != null) { - final Window owner = dirDiffDialog.getOwner(); - owner.addWindowListener(new WindowAdapter() { - @Override - public void windowClosed(WindowEvent e) { - onWindowClose.run(); - owner.removeWindowListener(this); - } - }); - } + setWindowListener(onWindowClose, dirDiffDialog.getOwner()); dirDiffDialog.show(); } } + private void setWindowListener(final Runnable onWindowClose, final Window window) { + if (onWindowClose != null) { + window.addWindowListener(new WindowAdapter() { + @Override + public void windowClosed(WindowEvent e) { + onWindowClose.run(); + window.removeWindowListener(this); + } + }); + } + } + @Override public void showDiff(@NotNull DiffElement dir1, @NotNull DiffElement dir2, DirDiffSettings settings) { showDiff(dir1, dir2, settings, null); @@ -100,7 +93,7 @@ public class DirDiffManagerImpl extends DirDiffManager { if (obj instanceof VirtualFile) { final VirtualFile file = (VirtualFile)obj; return JarFileSystem.PROTOCOL.equalsIgnoreCase(file.getExtension()) - ? new JarFileDiffElement(file) : new VirtualFileDiffElement(file); + ? new JarFileDiffElement(file) : new VirtualFileDiffElement(file); } return null; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java index 2ebd770d6060..b31a61d59a65 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java @@ -556,17 +556,18 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode private void refreshElementAfterCopyTo(DiffElement newElement, DirDiffElement element) { if (newElement != null) { + final DTree node = element.getNode(); + node.setType(DType.EQUAL); + node.setTarget(newElement); + synchronized (myElements) { - final DTree node = element.getNode(); final int row = myElements.indexOf(element); if (getSettings().showEqual) { - node.setType(DType.EQUAL); - node.setTarget(newElement); element.updateSourceFromTarget(newElement); fireTableRowsUpdated(row, row); } else { - removeElement(element); + removeElement(element, false); } } } @@ -610,40 +611,47 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode private void refreshElementAfterCopyFrom(DirDiffElement element, DiffElement newElement) { if (newElement != null) { final DTree node = element.getNode(); + node.setType(DType.EQUAL); + node.setSource(newElement); + synchronized (myElements) { final int row = myElements.indexOf(element); if (getSettings().showEqual) { - node.setType(DType.EQUAL); - node.setSource(newElement); element.updateTargetFromSource(newElement); fireTableRowsUpdated(row, row); } else { - removeElement(element); + removeElement(element, false); } } } } - private void removeElement(DirDiffElement element) { + private void removeElement(DirDiffElement element, boolean removeFromTree) { synchronized (myElements) { int row = myElements.indexOf(element); if (row != -1) { final DTree node = element.getNode(); - final DTree parentNode = element.getParentNode(); - parentNode.remove(node); + if (removeFromTree) { + final DTree parentNode = element.getParentNode(); + parentNode.remove(node); + } myElements.remove(row); int start = row; if (row > 0 && row == myElements.size() && myElements.get(row - 1).isSeparator()) { final DirDiffElement el = myElements.get(row - 1); - el.getParentNode().remove(el.getNode()); + if (removeFromTree) { + el.getParentNode().remove(el.getNode()); + } myElements.remove(row - 1); start = row - 1; } else if (row != myElements.size() && myElements.get(row).isSeparator() && row > 0 && myElements.get(row - 1).isSeparator()) { final DirDiffElement el = myElements.get(row - 1); - el.getParentNode().remove(el.getNode()); + if (removeFromTree) { + el.getParentNode().remove(el.getNode()); + } myElements.remove(row - 1); start = row - 1; } @@ -668,7 +676,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode else { synchronized (myElements) { if (myElements.indexOf(element) != -1) { - removeElement(element); + removeElement(element, true); } } } @@ -685,7 +693,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode else { synchronized (myElements) { if (myElements.indexOf(element) != -1) { - removeElement(element); + removeElement(element, true); } } final AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(getClass()); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java index 48de3e7cd9ca..d0e16a8d4c4b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java @@ -206,6 +206,10 @@ public abstract class ChangesTreeList extends JPanel { setShowFlatten(PropertiesComponent.getInstance(myProject).isTrueValue(FLATTEN_OPTION_KEY)); String emptyText = StringUtil.capitalize(DiffBundle.message("diff.count.differences.status.text", 0)); + setEmptyText(emptyText); + } + + public void setEmptyText(@NotNull String emptyText) { myTree.getEmptyText().setText(emptyText); myList.getEmptyText().setText(emptyText); } diff --git a/plugins/git4idea/src/git4idea/push/GitCommitsByBranch.java b/plugins/git4idea/src/git4idea/push/GitCommitsByBranch.java index 6054a71b01e7..1b533eab6b8d 100644 --- a/plugins/git4idea/src/git4idea/push/GitCommitsByBranch.java +++ b/plugins/git4idea/src/git4idea/push/GitCommitsByBranch.java @@ -16,12 +16,10 @@ package git4idea.push; import git4idea.GitBranch; +import git4idea.history.browser.GitCommit; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; /** * Holds Git commits made in a single repository grouped by branches. @@ -75,4 +73,12 @@ final class GitCommitsByBranch { return new GitCommitsByBranch(res); } + @NotNull + public Collection getAllCommits() { + Collection commits = new ArrayList(); + for (GitPushBranchInfo branchInfo : myCommitsByBranch.values()) { + commits.addAll(branchInfo.getCommits()); + } + return commits; + } } diff --git a/plugins/git4idea/src/git4idea/push/GitCommitsByRepoAndBranch.java b/plugins/git4idea/src/git4idea/push/GitCommitsByRepoAndBranch.java index 39f4df2c5b47..a75c5923a844 100644 --- a/plugins/git4idea/src/git4idea/push/GitCommitsByRepoAndBranch.java +++ b/plugins/git4idea/src/git4idea/push/GitCommitsByRepoAndBranch.java @@ -16,13 +16,11 @@ package git4idea.push; import git4idea.GitBranch; +import git4idea.history.browser.GitCommit; import git4idea.repo.GitRepository; import org.jetbrains.annotations.NotNull; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; +import java.util.*; /** * Holds Git commits grouped by repositories and by branches. @@ -83,5 +81,14 @@ final class GitCommitsByRepoAndBranch { return new GitCommitsByRepoAndBranch(commits); } + @NotNull + public Collection getAllCommits() { + Collection commits = new ArrayList(); + for (GitCommitsByBranch commitsByBranch : myCommitsByRepository.values()) { + commits.addAll(commitsByBranch.getAllCommits()); + } + return commits; + } + } diff --git a/plugins/git4idea/src/git4idea/push/GitPushLog.java b/plugins/git4idea/src/git4idea/push/GitPushLog.java index 7f6da09eef71..7f720211cbd1 100644 --- a/plugins/git4idea/src/git4idea/push/GitPushLog.java +++ b/plugins/git4idea/src/git4idea/push/GitPushLog.java @@ -26,10 +26,13 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.openapi.vcs.VcsDataKeys; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ui.ChangesBrowser; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.*; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.text.DateFormatUtil; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import git4idea.GitBranch; import git4idea.GitUtil; @@ -43,6 +46,7 @@ import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.*; import java.awt.*; +import java.io.File; import java.util.*; import java.util.List; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -61,14 +65,18 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { private final DefaultTreeModel myTreeModel; private final CheckedTreeNode myRootNode; private final ReentrantReadWriteLock TREE_CONSTRUCTION_LOCK = new ReentrantReadWriteLock(); + private final MyTreeCellRenderer myTreeCellRenderer; GitPushLog(@NotNull Project project, @NotNull Collection repositories, @NotNull final Consumer checkboxListener) { myProject = project; myAllRepositories = repositories; myRootNode = new CheckedTreeNode(null); + myRootNode.add(new DefaultMutableTreeNode(new FakeCommit())); + myTreeModel = new DefaultTreeModel(myRootNode); - myTree = new CheckboxTree(new MyTreeCellRenderer(), myRootNode) { + myTreeCellRenderer = new MyTreeCellRenderer(); + myTree = new CheckboxTree(myTreeCellRenderer, myRootNode) { @Override protected void onNodeStateChanged(CheckedTreeNode node) { Object userObject = node.getUserObject(); @@ -93,10 +101,12 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { if (node != null) { Object nodeInfo = node.getUserObject(); if (nodeInfo instanceof GitCommit) { + myChangesBrowser.getViewer().setEmptyText("No differences"); myChangesBrowser.setChangesToDisplay(((GitCommit)nodeInfo).getChanges()); return; } } + setDefaultEmptyText(); myChangesBrowser.setChangesToDisplay(Collections.emptyList()); } }); @@ -104,6 +114,7 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { myChangesBrowser = new ChangesBrowser(project, null, Collections.emptyList(), null, false, true, null, ChangesBrowser.MyUseCase.LOCAL_CHANGES, null); myChangesBrowser.getDiffAction().registerCustomShortcutSet(CommonShortcuts.getDiff(), myTree); + setDefaultEmptyText(); Splitter splitter = new Splitter(false, 0.7f); splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myTree)); @@ -113,6 +124,10 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { add(splitter); } + private void setDefaultEmptyText() { + myChangesBrowser.getViewer().setEmptyText("No commits selected"); + } + // Make changes available for diff action @Override public void calcData(DataKey key, DataSink sink) { @@ -140,6 +155,7 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { createNodes(commits); myTreeModel.nodeStructureChanged(myRootNode); myTree.setModel(myTreeModel); // TODO: why doesn't it repaint otherwise? + myTreeCellRenderer.recalculateWidth(commits.getAllCommits()); TreeUtil.expandAll(myTree); selectFirstCommit(); } @@ -243,6 +259,21 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { } private static class MyTreeCellRenderer extends CheckboxTree.CheckboxTreeCellRenderer { + + private int myDateMaxWidth; + + void recalculateWidth(@NotNull Collection commits) { + for (GitCommit commit : commits) { + int len = getDateString(commit).length(); + if (len > myDateMaxWidth) { + myDateMaxWidth = len; + } + } + } + + private static String getDateString(GitCommit commit) { + return DateFormatUtil.formatPrettyDateTime(commit.getAuthorTime()); + } @Override public void customizeRenderer(final JTree tree, final Object value, final boolean selected, final boolean expanded, final boolean leaf, final int row, final boolean hasFocus) { @@ -262,13 +293,14 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { if (userObject instanceof GitCommit) { GitCommit commit = (GitCommit)userObject; SimpleTextAttributes small = new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, renderer.getForeground()); - renderer.append(commit.getShortHash().toString(), small); - renderer.append(String.format("%15s ", DateFormatUtil.formatPrettyDateTime(commit.getAuthorTime())), small); + SimpleTextAttributes smallGrey = new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, UIUtil.getInactiveTextColor()); + renderer.append(commit.getShortHash().toString(), smallGrey); + renderer.append(String.format(" %" + myDateMaxWidth + "s ", getDateString(commit)), smallGrey); renderer.append(commit.getSubject(), small); - } else if (userObject instanceof GitRepository) { - renderer.append(((GitRepository)userObject).getPresentableUrl()); + String repositoryPath = calcRootPath((GitRepository)userObject); + renderer.append(repositoryPath, SimpleTextAttributes.GRAY_ATTRIBUTES); } else if (userObject instanceof GitBranchPair) { GitBranchPair branchPair = (GitBranchPair) userObject; @@ -276,13 +308,35 @@ class GitPushLog extends JPanel implements TypeSafeDataProvider { GitBranch dest = branchPair.getDest(); assert dest != null : "Destination branch can't be null for branch " + fromBranch; - SimpleTextAttributes attrs = fromBranch.isActive() ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES; - renderer.append(fromBranch.getName() + " -> " + dest.getName(), attrs); + renderer.append(fromBranch.getName() + " -> " + dest.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else if (userObject instanceof FakeCommit) { + int spaces = 6 + 15 + 3 + 30; + String s = String.format("%" + spaces + "s", " "); + renderer.append(s, new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, renderer.getBackground())); } else { renderer.append(userObject == null ? "" : userObject.toString()); } } + + @NotNull + private static String calcRootPath(@NotNull GitRepository repository) { + VirtualFile projectDir = repository.getProject().getBaseDir(); + + String repositoryPath = repository.getPresentableUrl(); + if (projectDir != null) { + String relativePath = VfsUtilCore.getRelativePath(repository.getRoot(), projectDir, File.separatorChar); + if (relativePath != null) { + repositoryPath = relativePath; + } + } + + return repositoryPath.isEmpty() ? "" : "." + File.separator + repositoryPath; + } + } + + private static class FakeCommit { } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java index 238156e9e6f7..926c4aab91e0 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.mvc; import com.intellij.ide.util.importProject.ModuleDescriptor; import com.intellij.ide.util.importProject.ProjectDescriptor; import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot; -import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot; import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder; import com.intellij.openapi.module.StdModuleTypes; @@ -53,7 +52,7 @@ public class GroovySdkForProjectFromSourcesStep extends GroovySdkWizardStepBase super.updateDataModel(); List modules = new ArrayList(); for (DetectedProjectRoot root : myBuilder.getProjectRoots(myDetector)) { - final ModuleDescriptor descriptor = new ModuleDescriptor(root.getDirectory(), StdModuleTypes.JAVA, Collections.emptyList()); + final ModuleDescriptor descriptor = new ModuleDescriptor(root.getDirectory(), StdModuleTypes.JAVA, Collections.emptyList()); descriptor.addConfigurationUpdater(createModuleConfigurationUpdater()); modules.add(descriptor); }