Merge remote-tracking branch 'origin/master'

This commit is contained in:
Kirill Likhodedov
2012-02-02 17:09:37 +04:00
46 changed files with 779 additions and 246 deletions
@@ -27,7 +27,7 @@ import com.intellij.refactoring.rename.PsiElementRenameHandler;
* @author ven
*/
public class RenameFileAction extends AnAction implements DumbAware {
public static final String RENAME_FILE = "Rename File";
public static final String RENAME_FILE = "Rename File...";
public void actionPerformed(final AnActionEvent e) {
final PsiFile file = e.getData(LangDataKeys.PSI_FILE);
@@ -47,7 +47,7 @@ public class RenameFileAction extends AnAction implements DumbAware {
presentation.setVisible(enabled);
if (enabled) {
presentation.setText(RENAME_FILE);
presentation.setDescription(RENAME_FILE);
presentation.setDescription("Rename selected file");
}
}
}
@@ -15,7 +15,6 @@
*/
package org.jetbrains.ether;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
@@ -31,7 +30,6 @@ import org.jetbrains.jps.Sdk;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.idea.IdeaProjectLoader;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.java.JavaBuilder;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
import org.jetbrains.jps.server.ClasspathBootstrap;
@@ -154,8 +152,12 @@ public abstract class IncrementalTestCase extends TestCase {
@Override
protected void tearDown() throws Exception {
super.tearDown();
delete(new File(workDir));
try {
super.tearDown();
}
finally {
delete(new File(workDir));
}
}
private String getProjectName() {
@@ -199,7 +201,7 @@ public abstract class IncrementalTestCase extends TestCase {
if (files != null) {
for (File f : files) {
copy(f, new File(output.getPath() + File.separator + f.getName()));
copy(f, new File(output.getPath(), f.getName()));
}
}
}
@@ -208,16 +210,26 @@ public abstract class IncrementalTestCase extends TestCase {
}
}
else if (input.isFile()) {
final FileReader in = new FileReader(input);
final FileWriter out = new FileWriter(output);
FileReader in = null;
FileWriter out = null;
try {
in = new FileReader(input);
out = new FileWriter(output);
int c;
while ((c = in.read()) != -1) out.write(c);
}
finally {
in.close();
out.close();
try {
if (in != null) {
in.close();
}
}
finally {
if (out != null) {
out.close();
}
}
}
}
}
@@ -241,7 +253,7 @@ public abstract class IncrementalTestCase extends TestCase {
final String basename = pathSep == -1 ? postfix : postfix.substring(pathSep + 1);
final String path =
getWorkDir() + File.separator + (pathSep == -1 ? "src" : postfix.substring(0, pathSep).replace('-', File.separatorChar));
final File output = new File(path + File.separator + basename);
final File output = new File(path, basename);
if (copy) {
copy(input, output);
@@ -275,7 +287,7 @@ public abstract class IncrementalTestCase extends TestCase {
final Sdk jdk = project.createSdk("JavaSDK", "IDEA jdk", System.getProperty("java.home"), null);
final List<String> paths = new LinkedList<String>();
paths.add(FileUtil.toSystemIndependentName(ClasspathBootstrap.getResourcePath(Object.class).getCanonicalPath()));
jdk.setClasspath(paths);
@@ -285,20 +297,32 @@ public abstract class IncrementalTestCase extends TestCase {
final ProjectDescriptor projectDescriptor =
new ProjectDescriptor(projectPath, project, new FSState(true), new ProjectTimestamps(projectName),
new BuildDataManager(projectName, true));
final IncProjectBuilder builder = new IncProjectBuilder(projectDescriptor, BuilderRegistry.getInstance(), CanceledStatus.NULL);
try {
builder.build(new AllProjectScope(project, true), false, true);
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), CanceledStatus.NULL
).build(
new AllProjectScope(project, true), false, true
);
modify();
modify();
if (SystemInfo.isUnix) {
Thread.sleep(1000);
if (SystemInfo.isUnix) {
Thread.sleep(1000L);
}
new IncProjectBuilder(
projectDescriptor, BuilderRegistry.getInstance(), CanceledStatus.NULL
).build(
new AllProjectScope(project, false), true, false
);
FileAssert.assertEquals(new File(getBaseDir() + ".log"), new File(getWorkDir() + ".log"));
}
finally {
projectDescriptor.release();
}
builder.build(new AllProjectScope(project, false), true, false);
projectDescriptor.release();
FileAssert.assertEquals(new File(getBaseDir() + ".log"), new File(getWorkDir() + ".log"));
}
}
@@ -25,30 +25,40 @@ import java.util.Map;
* @author yole
*/
public class CoreJarHandler extends JarHandlerBase {
private final Map<String, VirtualFile> myFileMap = new HashMap<String, VirtualFile>();
private final CoreJarFileSystem myFileSystem;
private final VirtualFile myRoot;
public CoreJarHandler(CoreJarFileSystem fileSystem, String path) {
super(path);
myFileSystem = fileSystem;
Map<EntryInfo, CoreJarVirtualFile> entries = new HashMap<EntryInfo, CoreJarVirtualFile>();
for (EntryInfo info : getEntriesMap().values()) {
getOrCreateFile(info, entries);
}
myRoot = getOrCreateFile(getEntryInfo(""), entries);
}
private CoreJarVirtualFile getOrCreateFile(EntryInfo info, Map<EntryInfo, CoreJarVirtualFile> entries) {
CoreJarVirtualFile answer = entries.get(info);
if (answer == null) {
EntryInfo parentEntry = info.parent;
answer = new CoreJarVirtualFile(this, info, parentEntry != null ? getOrCreateFile(parentEntry, entries) : null);
entries.put(info, answer);
}
return answer;
}
@Nullable
public VirtualFile findFileByPath(String pathInJar) {
if (getZip() == null) {
return null;
}
VirtualFile file = myFileMap.get(pathInJar);
if (file == null) {
if (pathInJar.length() > 0) {
EntryInfo entryInfo = getEntryInfo(pathInJar);
if (entryInfo == null) {
return null;
}
}
file = new CoreJarVirtualFile(myFileSystem, this, pathInJar);
myFileMap.put(pathInJar, file);
}
return file;
return myRoot != null ? myRoot.findFileByRelativePath(pathInJar) : null;
}
public CoreJarFileSystem getFileSystem() {
return myFileSystem;
}
}
@@ -23,44 +23,42 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @author yole
*/
public class CoreJarVirtualFile extends VirtualFile {
private final CoreJarFileSystem myFileSystem;
private final CoreJarHandler myHandler;
private final String myPathInJar;
private final VirtualFile myParent;
private VirtualFile[] myChildren;
private final ArrayList<VirtualFile> myChildren = new ArrayList<VirtualFile>();
private final JarHandlerBase.EntryInfo myEntry;
public CoreJarVirtualFile(CoreJarFileSystem fileSystem, CoreJarHandler handler, String pathInJar) {
myFileSystem = fileSystem;
public CoreJarVirtualFile(CoreJarHandler handler, JarHandlerBase.EntryInfo entry, CoreJarVirtualFile parent) {
myHandler = handler;
myPathInJar = pathInJar;
myParent = calcParent();
myParent = parent;
myEntry = entry;
if (parent != null) {
parent.myChildren.add(this);
}
}
@NotNull
@Override
public String getName() {
final int lastSlash = myPathInJar.lastIndexOf('/');
if (lastSlash < 0) {
return myPathInJar;
}
return myPathInJar.substring(lastSlash+1);
return myEntry.shortName;
}
@NotNull
@Override
public VirtualFileSystem getFileSystem() {
return myFileSystem;
return myHandler.getFileSystem();
}
@Override
public String getPath() {
return myHandler.myBasePath + "!/" + myPathInJar;
if (myParent == null) return myHandler.myBasePath + "!/";
return myParent.getPath() + "/" + myEntry.shortName;
}
@Override
@@ -70,7 +68,7 @@ public class CoreJarVirtualFile extends VirtualFile {
@Override
public boolean isDirectory() {
return myHandler.isDirectory(this);
return myEntry.isDirectory;
}
@Override
@@ -83,35 +81,9 @@ public class CoreJarVirtualFile extends VirtualFile {
return myParent;
}
private VirtualFile calcParent() {
if (myPathInJar.length() == 0) {
return null;
}
int lastSlash = myPathInJar.lastIndexOf('/');
if (lastSlash < 0) {
return myHandler.findFileByPath("");
}
return myHandler.findFileByPath(myPathInJar.substring(0, lastSlash));
}
@Override
public VirtualFile[] getChildren() {
VirtualFile[] answer = myChildren;
if (answer == null) {
answer = calcChildren();
myChildren = answer;
}
return answer;
}
private VirtualFile[] calcChildren() {
List<VirtualFile> result = new ArrayList<VirtualFile>();
final String[] children = myHandler.list(this);
for (String child : children) {
final VirtualFile childFile = myPathInJar.isEmpty() ? myHandler.findFileByPath(child) : myHandler.findFileByPath(myPathInJar + "/" + child);
result.add(childFile);
}
return result.toArray(new VirtualFile[result.size()]);
return myChildren.toArray(new VirtualFile[myChildren.size()]);
}
@NotNull
@@ -137,4 +137,6 @@ public interface ModifiableModuleModel {
boolean hasModuleGroups();
void setModuleGroupPath(Module module, String[] groupPath);
void setModuleFilePath(Module module, String oldPath, String newFilePath);
}
@@ -22,6 +22,10 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.undo.BasicUndoableAction;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.command.undo.UndoableAction;
import com.intellij.openapi.command.undo.UnexpectedUndoException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.module.ModifiableModuleModel;
@@ -37,6 +41,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.rename.RenameHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author dsl
@@ -86,6 +91,41 @@ public class RenameModuleHandler implements RenameHandler, TitledHandler {
}
public boolean canClose(final String inputString) {
final String oldName = myModule.getName();
final ModifiableModuleModel modifiableModel = renameModule(inputString);
if (modifiableModel == null) return false;
final Ref<Boolean> success = Ref.create(Boolean.TRUE);
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
UndoableAction action = new BasicUndoableAction() {
public void undo() throws UnexpectedUndoException {
final ModifiableModuleModel modifiableModel = renameModule(oldName);
if (modifiableModel != null) {
modifiableModel.commit();
}
}
@Override
public void redo() throws UnexpectedUndoException {
final ModifiableModuleModel modifiableModel = renameModule(inputString);
if (modifiableModel != null) {
modifiableModel.commit();
}
}
};
UndoManager.getInstance(myProject).undoableActionPerformed(action);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
modifiableModel.commit();
}
});
}
}, IdeBundle.message("command.renaming.module", oldName), null);
return success.get().booleanValue();
}
@Nullable
private ModifiableModuleModel renameModule(String inputString) {
final ModifiableModuleModel modifiableModel = ModuleManager.getInstance(myProject).getModifiableModel();
try {
modifiableModel.renameModule(myModule, inputString);
@@ -93,19 +133,9 @@ public class RenameModuleHandler implements RenameHandler, TitledHandler {
catch (ModuleWithNameAlreadyExists moduleWithNameAlreadyExists) {
Messages.showErrorDialog(myProject, IdeBundle.message("error.module.already.exists", inputString),
IdeBundle.message("title.rename.module"));
return false;
return null;
}
final Ref<Boolean> success = Ref.create(Boolean.TRUE);
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
modifiableModel.commit();
}
});
}
}, IdeBundle.message("command.renaming.module", myModule.getName()), null);
return success.get().booleanValue();
return modifiableModel;
}
}
@@ -29,6 +29,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.AreaInstance;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleComponent;
import com.intellij.openapi.module.impl.scopes.ModuleWithDependenciesScope;
@@ -36,6 +37,7 @@ import com.intellij.openapi.module.impl.scopes.ModuleWithDependentsScope;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -329,6 +331,20 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
final Object requestor = event.getRequestor();
if (MODULE_RENAMING_REQUESTOR.equals(requestor)) return;
if (!VirtualFile.PROP_NAME.equals(event.getPropertyName())) return;
final VirtualFile parent = event.getParent();
if (parent != null) {
final String parentPath = parent.getPath();
final String ancestorPath = parentPath + "/" + event.getOldValue();
final String moduleFilePath = getModuleFilePath();
if (VfsUtil.isAncestor(new File(ancestorPath), new File(moduleFilePath), true)) {
final String newValue = (String)event.getNewValue();
final String relativePath = FileUtil.getRelativePath(ancestorPath, moduleFilePath, '/');
final String newFilePath = parentPath + "/" + newValue + "/" + relativePath;
setModuleFilePath(moduleFilePath, newFilePath);
}
}
final VirtualFile moduleFile = getModuleFile();
if (moduleFile == null) return;
if (moduleFile.equals(event.getFile())) {
@@ -336,6 +352,29 @@ public class ModuleImpl extends ComponentManagerImpl implements Module {
ModuleManagerImpl.getInstanceImpl(getProject()).fireModuleRenamedByVfsEvent(ModuleImpl.this);
}
}
private void setModuleFilePath(String moduleFilePath, String newFilePath) {
ClasspathStorage.modulePathChanged(ModuleImpl.this, newFilePath);
final ModifiableModuleModel modifiableModel = ModuleManagerImpl.getInstanceImpl(getProject()).getModifiableModel();
modifiableModel.setModuleFilePath(ModuleImpl.this, moduleFilePath, newFilePath);
modifiableModel.commit();
getStateStore().setModuleFilePath(newFilePath);
}
@Override
public void fileMoved(VirtualFileMoveEvent event) {
final VirtualFile oldParent = event.getOldParent();
final VirtualFile newParent = event.getNewParent();
final String dirName = event.getFileName();
final String ancestorPath = oldParent.getPath() + "/" + dirName;
final String moduleFilePath = getModuleFilePath();
if (VfsUtil.isAncestor(new File(ancestorPath), new File(moduleFilePath), true)) {
final String relativePath = FileUtil.getRelativePath(ancestorPath, moduleFilePath, '/');
setModuleFilePath(moduleFilePath, newParent.getPath() + "/" + dirName + "/" + relativePath);
}
}
}
protected MutablePicoContainer createPicoContainer() {
@@ -919,6 +919,12 @@ public class ModuleManagerImpl extends ModuleManager implements ProjectComponent
myModuleGroupPath.put(module, groupPath);
}
}
@Override
public void setModuleFilePath(Module module, String oldPath, String newFilePath) {
myPathToModule.remove(oldPath);
myPathToModule.put(newFilePath, module);
}
}
private void commitModel(final ModuleModelImpl moduleModel, final Runnable runnable) {
@@ -328,6 +328,10 @@ public class ClasspathStorage implements StateStorage {
getProvider(getStorageType(module)).moduleRenamed(module, newName);
}
public static void modulePathChanged(Module module, String path) {
getProvider(getStorageType(module)).modulePathChanged(module, path);
}
private static class DefaultStorageProvider implements ClasspathStorageProvider {
@NonNls
public String getID() {
@@ -356,6 +360,10 @@ public class ClasspathStorage implements StateStorage {
public String getContentRoot(ModifiableRootModel model) {
return null;
}
@Override
public void modulePathChanged(Module module, String path) {
}
}
public static class UnsupportedStorageProvider implements ClasspathStorageProvider {
@@ -406,5 +414,10 @@ public class ClasspathStorage implements StateStorage {
public String getContentRoot(ModifiableRootModel model) {
return null;
}
@Override
public void modulePathChanged(Module module, String path) {
throw new UnsupportedOperationException(getDescription());
}
}
}
@@ -53,6 +53,8 @@ public interface ClasspathStorageProvider {
String getContentRoot(ModifiableRootModel model);
void modulePathChanged(Module module, String path);
interface ClasspathConverter {
FileSet getFileSet();
@@ -20,6 +20,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.local.LocalFileSystemBase;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.io.FileNotFoundException;
@@ -91,6 +92,10 @@ public class Win32LocalFileSystem extends LocalFileSystemBase {
@NotNull
@Override
public String[] list(@NotNull VirtualFile file) {
if (isInvalidSymLink(file)) {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
try {
String[] strings = myKernel.list(file.getPath());
if (checkMe && !Arrays.asList(strings).equals(Arrays.asList(super.list(file)))) {
@@ -44,7 +44,10 @@ public class SymLinkHandlingTest extends LightPlatformLangTestCase {
}
public void testBadLinksAreIgnored() throws Exception {
if (!SystemInfo.areSymLinksSupported) return;
if (!SystemInfo.areSymLinksSupported) {
System.out.println("Test not passed");
return;
}
final File missingFile = new File(FileUtil.getTempDirectory(), "missing_file");
assertTrue(missingFile.getAbsolutePath(), !missingFile.exists() || missingFile.delete());
@@ -152,7 +152,7 @@ public class UnixProcessManager {
result = false;
}
StringBuffer errorStr = new StringBuffer();
StringBuilder errorStr = new StringBuilder();
while ((s = stdError.readLine()) != null) {
errorStr.append(s).append("\n");
}
@@ -172,24 +172,21 @@ public class UnixProcessManager {
}
public static String[] getPSCmd(boolean commandLineOnly) {
String psCommand = "/bin/ps";
if (!new File(psCommand).isFile()) {
psCommand = "ps";
}
if (SystemInfo.isLinux) {
return new String[]{"ps", "-e", "e", "--format", commandLineOnly ? "%a" : "%P%p%a"};
return new String[]{psCommand, "-e", "--format", commandLineOnly ? "%a" : "%P%p%a"};
}
else if (SystemInfo.isMac) {
return new String[]{"ps", "-ax", "-E", "-o", commandLineOnly ? "command" : "ppid,pid,command"};
}
else if (SystemInfo.isFreeBSD) {
return new String[]{"ps", "-ax", "-e", "-o", commandLineOnly ? "command" : "ppid,pid,command"};
else if (SystemInfo.isMac || SystemInfo.isFreeBSD) {
return new String[]{psCommand, "-ax", "-o", commandLineOnly ? "command" : "ppid,pid,command"};
}
else {
throw new IllegalStateException(System.getProperty("os.name") + " is not supported.");
}
}
public static boolean containsMarker(@NotNull String environ, @NotNull String uid) {
return environ.contains(uid);
}
@NotNull
public static String readProcEnviron(int child_pid) throws FileNotFoundException {
StringBuffer res = new StringBuffer();
@@ -322,4 +322,5 @@ android.lint.inspections.set.to.wrap.content=Replace size attribute with 'wrap_c
android.lint.inspections.add.permission.attribute=Add 'permission' attribute
android.lint.inspections.add.input.type.attribute=Add 'inputType' attribute
android.lint.inspections.remove.unnecessary.view=Remove unnecessary view
android.lint.inspections.replace.with.suggested.characters=Replace with suggested characters
android.lint.inspections.replace.with.suggested.characters=Replace with suggested characters
android.facet.settings.pack.test.sources=Include test code and resources into APK
@@ -35,6 +35,7 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
@@ -351,14 +352,24 @@ public class AndroidCompileUtil {
}
public static void generate(final Module module, final GeneratingCompiler compiler) {
module.getProject().getComponent(AndroidProjectComponent.class).runIfNotInCompilation(new Runnable() {
final Project project = module.getProject();
final AndroidProjectComponent component = ApplicationManager.getApplication().runReadAction(new Computable<AndroidProjectComponent>() {
@Nullable
@Override
public AndroidProjectComponent compute() {
return !project.isDisposed() ? project.getComponent(AndroidProjectComponent.class) : null;
}
});
if (component == null) {
return;
}
component.runIfNotInCompilation(new Runnable() {
@Override
public void run() {
assert !ApplicationManager.getApplication().isDispatchThread();
final CompileContext[] contextWrapper = new CompileContext[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
Project project = module.getProject();
if (project.isDisposed()) return;
CompilerTask task = new CompilerTask(project, true, "Android auto-generation", true);
CompileScope scope = new ModuleCompileScope(module, false);
@@ -105,11 +105,6 @@ public class AndroidDexCompiler implements ClassPostProcessingCompiler {
}
}
}
private static boolean shouldRunProguard(@NotNull AndroidFacet facet, @NotNull CompileContext context) {
return AndroidCompileUtil.isReleaseBuild(context) &&
AndroidCompileUtil.getProguardConfigFile(facet) != null;
}
private static final class PrepareAction implements Computable<ProcessingItem[]> {
private final CompileContext myContext;
@@ -129,7 +124,10 @@ public class AndroidDexCompiler implements ClassPostProcessingCompiler {
Collection<VirtualFile> files;
if (shouldRunProguard(facet, myContext)) {
final boolean shouldRunProguard = myContext.getCompileScope().
getUserData(AndroidProguardCompiler.PROGUARD_CFG_PATH_KEY) != null;
if (shouldRunProguard) {
final VirtualFile obfuscatedSourcesJar = dexOutputDir.findChild(AndroidProguardCompiler.PROGUARD_OUTPUT_JAR_NAME);
if (obfuscatedSourcesJar == null) {
myContext.addMessage(CompilerMessageCategory.INFORMATION, "Dex won't be launched for module " +
@@ -166,10 +164,12 @@ public class AndroidDexCompiler implements ClassPostProcessingCompiler {
}
}
VirtualFile outputDirForTests = extension.getCompilerOutputPathForTests();
if (facet.getConfiguration().PACK_TEST_CODE) {
VirtualFile outputDirForTests = extension.getCompilerOutputPathForTests();
if (outputDirForTests != null) {
addModuleOutputDir(files, outputDirForTests);
if (outputDirForTests != null) {
addModuleOutputDir(files, outputDirForTests);
}
}
}
@@ -226,7 +226,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler {
}
try {
VirtualFile[] sourceRoots = AndroidPackagingCompiler.getSourceRootsForModuleAndDependencies(idlItem.myModule);
VirtualFile[] sourceRoots = AndroidPackagingCompiler.getSourceRootsForModuleAndDependencies(idlItem.myModule, false);
final String[] sourceRootPaths = AndroidCompileUtil.toOsPaths(sourceRoots);
final Map<CompilerMessageCategory, List<String>> messages = AndroidIdl
@@ -65,11 +65,14 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
return VirtualFile.EMPTY_ARRAY;
}
private static void fillSourceRoots(@NotNull Module module, @NotNull Set<Module> visited, @NotNull Set<VirtualFile> result) {
private static void fillSourceRoots(@NotNull Module module,
@NotNull Set<Module> visited,
@NotNull Set<VirtualFile> result,
boolean includingTests) {
visited.add(module);
VirtualFile resDir = AndroidRootUtil.getResourceDir(module);
ModuleRootManager manager = ModuleRootManager.getInstance(module);
for (VirtualFile sourceRoot : manager.getSourceRoots()) {
for (VirtualFile sourceRoot : manager.getSourceRoots(includingTests)) {
if (resDir != sourceRoot) {
result.add(sourceRoot);
}
@@ -78,10 +81,10 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
DependencyScope scope = moduleOrderEntry.getScope();
if (scope == DependencyScope.COMPILE || scope == DependencyScope.TEST) {
if (scope == DependencyScope.COMPILE) {
Module depModule = moduleOrderEntry.getModule();
if (depModule != null && !visited.contains(depModule)) {
fillSourceRoots(depModule, visited, result);
fillSourceRoots(depModule, visited, result, false);
}
}
}
@@ -89,9 +92,9 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
}
@NotNull
public static VirtualFile[] getSourceRootsForModuleAndDependencies(@NotNull Module module) {
public static VirtualFile[] getSourceRootsForModuleAndDependencies(@NotNull Module module, boolean includingTests) {
Set<VirtualFile> result = new HashSet<VirtualFile>();
fillSourceRoots(module, new HashSet<Module>(), result);
fillSourceRoots(module, new HashSet<Module>(), result, includingTests);
return VfsUtil.toVirtualFileArray(result);
}
@@ -102,7 +105,7 @@ public class AndroidPackagingCompiler implements PackagingCompiler {
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null && !facet.getConfiguration().LIBRARY_PROJECT) {
VirtualFile manifestFile = AndroidRootUtil.getManifestFileForCompiler(facet);
VirtualFile[] sourceRoots = getSourceRootsForModuleAndDependencies(module);
VirtualFile[] sourceRoots = getSourceRootsForModuleAndDependencies(module, facet.getConfiguration().PACK_TEST_CODE);
if (manifestFile != null) {
AndroidFacetConfiguration configuration = facet.getConfiguration();
VirtualFile outputDir = AndroidDexCompiler.getOutputDirectoryForDex(module);
@@ -21,6 +21,8 @@ import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
@@ -30,8 +32,8 @@ import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PsiNavigateUtil;
import com.intellij.util.xml.*;
import org.jetbrains.android.dom.ResourceType;
import org.jetbrains.android.dom.AdditionalConverter;
import org.jetbrains.android.dom.ResourceType;
import org.jetbrains.android.dom.resources.Item;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.ResourceValue;
@@ -110,7 +112,8 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
if (module == null) return result;
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet == null) return result;
Set<String> recommendedTypes = getResourceTypes(context);
final Set<String> recommendedTypes = getResourceTypes(context);
// hack to check if it is a real id attribute
if (recommendedTypes.contains("id") && recommendedTypes.size() == 1) {
@@ -122,7 +125,7 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
String value = getValue(element);
assert value != null;
if (!myQuiet || value.startsWith("@")) {
if (!myQuiet || StringUtil.startsWithChar(value, '@')) {
String resourcePackage = null;
String systemPrefix = getPackagePrefix(SYSTEM_RESOURCE_PACKAGE);
if (value.startsWith(systemPrefix)) {
@@ -137,12 +140,17 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
addResourceReferenceValues(facet, type, resourcePackage, result, explicitResourceType);
}
else {
final Set<String> filteringSet = SYSTEM_RESOURCE_PACKAGE.equals(resourcePackage)
? null
: getResourceTypesInCurrentModule(facet);
for (String type : ResourceManager.REFERABLE_RESOURCE_TYPES) {
String typePrefix = getTypePrefix(resourcePackage, type);
if (value.startsWith(typePrefix)) {
addResourceReferenceValues(facet, type, resourcePackage, result, true);
}
else if (recommendedTypes.contains(type)) {
else if (recommendedTypes.contains(type) &&
(filteringSet == null || filteringSet.contains(type))) {
result.add(ResourceValue.literal(typePrefix));
}
}
@@ -157,6 +165,23 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
}
return result;
}
@NotNull
private static Set<String> getResourceTypesInCurrentModule(@NotNull AndroidFacet facet) {
final Set<String> result = new HashSet<String>();
final LocalResourceManager manager = facet.getLocalResourceManager();
for (VirtualFile resSubdir : manager.getResourceSubdirs(null)) {
final String resType = AndroidResourceUtil.getResourceTypeByDirName(resSubdir.getName());
if (resType != null && com.android.resources.ResourceType.getEnum(resType) != null) {
result.add(resType);
}
}
result.addAll(manager.getValueResourceTypes());
return result;
}
@NotNull
private String getTypePrefix(String resourcePackage, String type) {
@@ -81,6 +81,8 @@ public class AndroidFacetConfiguration implements FacetConfiguration {
public String CUSTOM_DEBUG_KEYSTORE_PATH = "";
public boolean PACK_TEST_CODE = false;
private AndroidFacet myFacet = null;
public void init(@NotNull Module module, @NotNull VirtualFile contentRoot) {
@@ -115,8 +115,8 @@
</vspacer>
</children>
</grid>
<grid id="84519" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<grid id="84519" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="4" right="0"/>
<constraints>
<tabbedpane title="Compiler"/>
</constraints>
@@ -124,7 +124,7 @@
<border type="none"/>
<children>
<grid id="3e085" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="4" bottom="0" right="0"/>
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
@@ -198,11 +198,11 @@
</grid>
<vspacer id="e716a">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="4c810" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="4" bottom="0" right="0"/>
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
@@ -237,7 +237,7 @@
</children>
</grid>
<grid id="c2a96" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="4" bottom="0" right="0"/>
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
@@ -297,6 +297,14 @@
</component>
</children>
</grid>
<component id="39707" class="javax.swing.JCheckBox" binding="myIncludeTestCodeAndCheckBox" default-binding="true">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/AndroidBundle" key="android.facet.settings.pack.test.sources"/>
</properties>
</component>
</children>
</grid>
</children>
@@ -93,6 +93,7 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
private JLabel myRGenPathLabel;
private TextFieldWithBrowseButton myCustomDebugKeystoreField;
private JBLabel myCustomKeystoreLabel;
private JCheckBox myIncludeTestCodeAndCheckBox;
public AndroidFacetEditorTab(FacetEditorContext context, AndroidFacetConfiguration androidFacetConfiguration) {
final Project project = context.getProject();
@@ -282,6 +283,9 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
if (!myConfiguration.CUSTOM_DEBUG_KEYSTORE_PATH.equals(getSelectedCustomKeystorePath())) {
return true;
}
if (myConfiguration.PACK_TEST_CODE != myIncludeTestCodeAndCheckBox.isSelected()) {
return true;
}
return false;
}
@@ -390,6 +394,8 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myConfiguration.RUN_PROCESS_RESOURCES_MAVEN_TASK = myRunProcessResourcesRadio.isSelected();
myConfiguration.GENERATE_UNSIGNED_APK = myGenerateUnsignedApk.isSelected();
myConfiguration.PACK_TEST_CODE = myIncludeTestCodeAndCheckBox.isSelected();
boolean useCustomAptSrc = myUseCustomSourceDirectoryRadio.isSelected();
@@ -513,6 +519,7 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
myCompileResourcesByIdeRadio.setSelected(!myConfiguration.RUN_PROCESS_RESOURCES_MAVEN_TASK);
myGenerateUnsignedApk.setSelected(myConfiguration.GENERATE_UNSIGNED_APK);
myIncludeTestCodeAndCheckBox.setSelected(myConfiguration.PACK_TEST_CODE);
updateAptPanel();
@@ -16,6 +16,7 @@
package org.jetbrains.android.facet;
import com.android.resources.ResourceFolderType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.GeneratingCompiler;
import com.intellij.openapi.module.Module;
@@ -31,6 +32,7 @@ import org.jetbrains.android.compiler.*;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
@@ -147,7 +149,7 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
final GeneratingCompiler compilerToRun = ApplicationManager.getApplication().runReadAction(new Computable<GeneratingCompiler>() {
@Nullable
public GeneratingCompiler compute() {
return computeCompilerToRun();
return computeCompilerToRunAndInvalidateLocalAttributesMap();
}
});
@@ -175,7 +177,7 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
}
@Nullable
private GeneratingCompiler computeCompilerToRun() {
private GeneratingCompiler computeCompilerToRunAndInvalidateLocalAttributesMap() {
if (myFacet.isDisposed()) {
return null;
}
@@ -197,10 +199,18 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
return null;
}
parent = parent.getParent();
final VirtualFile gp = parent.getParent();
final VirtualFile resourceDir = AndroidRootUtil.getResourceDir(module);
if (gp == resourceDir &&
ResourceFolderType.VALUES.getName().equals(AndroidResourceUtil.getResourceTypeByDirName(parent.getName()))) {
myFacet.getLocalResourceManager().invalidateAttributeDefinitions();
}
if (AndroidAptCompiler.isToCompileModule(module, myFacet.getConfiguration()) &&
(myFacet.getConfiguration().REGENERATE_R_JAVA && parent == AndroidRootUtil.getResourceDir(module) ||
AndroidRootUtil.getManifestFile(module) == file)) {
(myFacet.getConfiguration().REGENERATE_R_JAVA && (gp == resourceDir ||
AndroidRootUtil.getManifestFile(module) == file))) {
final Manifest manifest = myFacet.getManifest();
final String aPackage = manifest != null ? manifest.getPackage().getValue() : null;
@@ -209,8 +219,6 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
AndroidCompileUtil.removeDuplicatingClasses(myModule, myCachedPackage, AndroidUtils.R_CLASS_NAME, null, aptGenDirPath);
}
myCachedPackage = aPackage;
myFacet.getLocalResourceManager().invalidateAttributeDefinitions();
return new AndroidAptCompiler();
}
@@ -256,14 +256,9 @@ public class AndroidRootUtil {
}
}
}
else {
if (!outputDirs.contains(classDir) && classDir != null && classDir.exists()) {
outputDirs.add(classDir);
}
VirtualFile classDirForTests = extension.getCompilerOutputPathForTests();
if (!outputDirs.contains(classDirForTests) && classDirForTests != null && classDirForTests.exists()) {
outputDirs.add(classDirForTests);
}
// do not support android-app->android-app compile dependencies
else if (facet == null && !outputDirs.contains(classDir) && classDir != null && classDir.exists()) {
outputDirs.add(classDir);
}
}
fillExternalLibrariesAndModules(depModule, outputDirs, libraries, visited, !libraryProject || exportedLibrariesOnly);
@@ -128,6 +128,7 @@ public class AndroidModuleBuilder extends JavaModuleBuilder {
if (myProjectType == ProjectType.TEST) {
assert myTestedModule != null;
facet.getConfiguration().PACK_TEST_CODE = true;
ModuleOrderEntry entry = rootModel.addModuleOrderEntry(myTestedModule);
entry.setScope(DependencyScope.PROVIDED);
}
@@ -17,6 +17,7 @@
package org.jetbrains.android.resourceManagers;
import com.android.AndroidConstants;
import com.android.resources.ResourceType;
import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -27,10 +28,14 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.android.AndroidFileTemplateProvider;
import org.jetbrains.android.AndroidValueResourcesIndex;
import org.jetbrains.android.actions.CreateResourceFileAction;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.Attr;
@@ -42,13 +47,12 @@ import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
import static org.jetbrains.android.util.AndroidUtils.loadDomElement;
@@ -135,6 +139,43 @@ public class LocalResourceManager extends ResourceManager {
return facet != null ? facet.getLocalResourceManager() : null;
}
@NotNull
public Set<String> getValueResourceTypes() {
final Map<VirtualFile, Set<String>> file2Types = new HashMap<VirtualFile, Set<String>>();
final FileBasedIndex index = FileBasedIndex.getInstance();
final GlobalSearchScope scope = GlobalSearchScope.projectScope(myModule.getProject());
for (String resourceType : ResourceType.getNames()) {
final ResourceEntry typeMarkerEntry = AndroidValueResourcesIndex.createTypeMarkerEntry(resourceType);
for (Set<ResourceEntry> entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) {
for (ResourceEntry entry : entrySet) {
final Collection<VirtualFile> files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope);
for (VirtualFile file : files) {
Set<String> resourcesInFile = file2Types.get(file);
if (resourcesInFile == null) {
resourcesInFile = new HashSet<String>();
file2Types.put(file, resourcesInFile);
}
resourcesInFile.add(entry.getType());
}
}
}
}
final Set<String> result = new HashSet<String>();
for (VirtualFile file : getAllValueResourceFiles()) {
final Set<String> types = file2Types.get(file);
if (types != null) {
result.addAll(types);
}
}
return result;
}
@NotNull
public AttributeDefinitions getAttributeDefinitions() {
if (myAttrDefs == null) {
@@ -92,11 +92,10 @@ public class AndroidRunConfiguration extends AndroidRunConfigurationBase impleme
}
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
RunProfileState state = super.getState(executor, env);
public AndroidRunningState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
AndroidRunningState state = super.getState(executor, env);
if (state != null) {
assert state instanceof AndroidRunningState;
((AndroidRunningState)state).setDeploy(DEPLOY);
state.setDeploy(DEPLOY);
}
return state;
}
@@ -31,7 +31,6 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderEntry;
@@ -158,7 +157,8 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
TARGET_SELECTION_MODE = mode.name();
}
private static boolean fillRuntimeAndTestDependencies(@NotNull Module module, @NotNull Map<AndroidFacet, String> module2PackageName) {
private static boolean fillRuntimeAndTestDependencies(@NotNull Module module,
@NotNull Map<AndroidFacet, String> module2PackageName) {
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
if (entry instanceof ModuleOrderEntry) {
ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)entry;
@@ -167,8 +167,7 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
AndroidFacet depFacet = AndroidFacet.getInstance(depModule);
if (depFacet != null &&
!module2PackageName.containsKey(depFacet) &&
!depFacet.getConfiguration().LIBRARY_PROJECT &&
moduleOrderEntry.getScope() != DependencyScope.COMPILE) {
!depFacet.getConfiguration().LIBRARY_PROJECT) {
String packageName = getPackageName(depFacet);
if (packageName == null) {
return false;
@@ -184,7 +183,7 @@ public abstract class AndroidRunConfigurationBase extends ModuleBasedConfigurati
return true;
}
public RunProfileState getState(@NotNull final Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
public AndroidRunningState getState(@NotNull final Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
final Module module = getConfigurationModule().getModule();
if (module == null) {
throw new ExecutionException("Module is not found");
@@ -218,10 +218,6 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
return myLock;
}
public AndroidFacet getAndroidFacet() {
return myFacet;
}
public String getPackageName() {
return myPackageName;
}
@@ -230,6 +226,7 @@ public abstract class AndroidRunningState implements RunProfileState, AndroidDeb
return myFacet.getModule();
}
@NotNull
public AndroidFacet getFacet() {
return myFacet;
}
@@ -28,6 +28,7 @@ import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.junit.JUnitUtil;
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
import com.intellij.execution.testframework.ui.BaseTestsOutputConsoleView;
import com.intellij.execution.ui.ConsoleView;
@@ -35,6 +36,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass;
@@ -43,6 +46,7 @@ import com.intellij.psi.PsiPackage;
import org.jetbrains.android.dom.manifest.Instrumentation;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidFacetConfiguration;
import org.jetbrains.android.run.AndroidApplicationLauncher;
import org.jetbrains.android.run.AndroidRunConfigurationBase;
import org.jetbrains.android.run.AndroidRunConfigurationEditor;
@@ -108,6 +112,44 @@ public class AndroidTestRunConfiguration extends AndroidRunConfigurationBase {
}
}
@Override
public AndroidRunningState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
final AndroidRunningState state = super.getState(executor, env);
if (state == null) {
return null;
}
final AndroidFacet facet = state.getFacet();
final AndroidFacetConfiguration configuration = facet.getConfiguration();
if (!configuration.PACK_TEST_CODE) {
final Module module = facet.getModule();
final int count = getTestSourceRootCount(module);
if (count > 0) {
final String message = "Code and resources under test source " + (count > 1 ? "roots" : "root") +
" aren't included into debug APK.\nWould you like to include them and recompile " +
module.getName() + " module?" + "\n(You may change this option in Android facet settings later)";
final int result =
Messages.showYesNoCancelDialog(getProject(), message, "Test code not included into APK", Messages.getQuestionIcon());
if (result == Messages.YES) {
configuration.PACK_TEST_CODE = true;
}
else if (result == Messages.CANCEL) {
return null;
}
}
}
return state;
}
private static int getTestSourceRootCount(@NotNull Module module) {
final ModuleRootManager manager = ModuleRootManager.getInstance(module);
return manager.getSourceRoots(true).length - manager.getSourceRoots(false).length;
}
private void checkTestMethod() throws RuntimeConfigurationException {
JavaRunConfigurationModule configurationModule = getConfigurationModule();
final PsiClass testClass =
@@ -166,7 +208,7 @@ public class AndroidTestRunConfiguration extends AndroidRunConfigurationBase {
BaseTestsOutputConsoleView consoleView = SMTestRunnerConnectionUtil
.createAndAttachConsole("Android", state.getProcessHandler(), properties, state.getRunnerSettings(), state.getConfigurationSettings()
);
Disposer.register(state.getAndroidFacet().getModule().getProject(), consoleView);
Disposer.register(state.getFacet().getModule().getProject(), consoleView);
return consoleView;
}
@@ -76,10 +76,17 @@ class AndroidSdkConfigurableForm {
final IAndroidTarget target = (IAndroidTarget)e.getItem();
List<OrderRoot> roots = AndroidSdkUtils.getLibraryRootsForTarget(target, mySdkLocation);
Map<OrderRootType, VirtualFile[]> configuredRoots = new HashMap<OrderRootType, VirtualFile[]>();
Map<OrderRootType, String[]> configuredRoots = new HashMap<OrderRootType, String[]>();
for (OrderRootType type : OrderRootType.getAllTypes()) {
configuredRoots.put(type, sdkModificator.getRoots(type));
final VirtualFile[] oldRoots = sdkModificator.getRoots(type);
final String[] oldRootPaths = new String[oldRoots.length];
for (int i = 0; i < oldRootPaths.length; i++) {
oldRootPaths[i] = oldRoots[i].getPath();
}
configuredRoots.put(type, oldRootPaths);
}
for (OrderRoot root : roots) {
@@ -87,8 +94,8 @@ class AndroidSdkConfigurableForm {
sdkModificator.removeRoot(root.getFile(), root.getType());
}
else {
VirtualFile[] configuredRootsForType = configuredRoots.get(root.getType());
if (ArrayUtil.find(configuredRootsForType, root.getFile()) == -1) {
String[] configuredRootsForType = configuredRoots.get(root.getType());
if (ArrayUtil.find(configuredRootsForType, root.getFile().getPath()) == -1) {
sdkModificator.addRoot(root.getFile(), root.getType());
}
}
@@ -455,12 +455,15 @@ public class AndroidUtils {
LOG.info(commandLine.getCommandLineString());
OSProcessHandler handler = new OSProcessHandler(commandLine.createProcess(), "");
final StringBuffer buffer = new StringBuffer();
final ProcessAdapter listener = new ProcessAdapter() {
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
buffer.append(event.getText());
}
};
if (timeout == null || timeout > 0) {
handler.addProcessListener(new ProcessAdapter() {
public void onTextAvailable(final ProcessEvent event, final Key outputType) {
messageBuilder.append(event.getText());
}
});
handler.addProcessListener(listener);
}
handler.startNotify();
@@ -483,7 +486,9 @@ public class AndroidUtils {
}
if (timeout == null || timeout > 0) {
String message = messageBuilder.toString();
handler.removeProcessListener(listener);
final String message = buffer.toString();
messageBuilder.append(message);
LOG.info(message);
}
@@ -9,7 +9,6 @@ import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.ArrayUtil;
import java.io.IOException;
import java.util.ArrayList;
@@ -116,9 +115,7 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
public void testResourceCompletion() throws Throwable {
doTestCompletionVariants("av3.xml", "@color/", "@android:", "@drawable/");
List<String> list = getAllResources();
list.add("@android:");
doTestCompletionVariants("av8.xml", ArrayUtil.toStringArray(list));
doTestCompletionVariants("av8.xml", "@android:", "@anim/", "@color/", "@dimen/", "@drawable/", "@id/", "@layout/", "@string/", "@style/");
}
public void testLocalResourceCompletion1() throws Throwable {
@@ -1,11 +1,8 @@
package org.jetbrains.android.dom;
import com.android.sdklib.SdkConstants;
import com.intellij.util.ArrayUtil;
import org.jetbrains.android.inspections.AndroidUnknownAttributeInspection;
import java.util.List;
/**
* @author coyote
*/
@@ -73,9 +70,7 @@ public class AndroidManifestDomTest extends AndroidDomTest {
}
public void testResourceCompletion3() throws Throwable {
List<String> list = getAllResources();
list.add("@android:");
doTestCompletionVariants("av4.xml", ArrayUtil.toStringArray(list));
doTestCompletionVariants("av4.xml", "@android:", "@anim/", "@color/", "@dimen/", "@drawable/", "@id/", "@string/", "@style/");
}
public void testTagNameCompletion1() throws Throwable {
@@ -103,6 +103,14 @@ public class EclipseClasspathStorageProvider implements ClasspathStorageProvider
return model.getContentRoots()[0].getPath();
}
@Override
public void modulePathChanged(Module module, String path) {
final EclipseModuleManager moduleManager = EclipseModuleManager.getInstance(module);
if (moduleManager != null) {
moduleManager.setDocumentSet(null);
}
}
public static void registerFiles(final CachedXmlDocumentSet fileCache, final Module module, final String moduleRoot, final String storageRoot) {
fileCache.register(EclipseXml.CLASSPATH_FILE, storageRoot);
fileCache.register(EclipseXml.PROJECT_FILE, storageRoot);
@@ -89,12 +89,13 @@ public class MavenPluginConfigurationDomExtender extends DomExtender<MavenDomCon
String name = eachParameter.getName().getStringValue();
if (name == null) continue;
if (namesWithParameters.containsKey(name)) continue;
ParameterData data = new ParameterData(eachParameter);
fillParameterData(name, data, eachMojo);
namesWithParameters.put(name, data);
ParameterData oldParameter = namesWithParameters.get(name);
if (oldParameter == null || hasMorePriority(data, oldParameter, executionElement != null)) {
namesWithParameters.put(name, data);
}
}
}
}
@@ -102,6 +103,16 @@ public class MavenPluginConfigurationDomExtender extends DomExtender<MavenDomCon
return namesWithParameters.values();
}
private static boolean hasMorePriority(ParameterData d1, ParameterData d2, boolean isForExecutionSection) {
if (!isForExecutionSection) {
if (StringUtil.isEmptyOrSpaces(d1.getMojo().getPhase().getStringValue())) return false;
if (StringUtil.isEmptyOrSpaces(d2.getMojo().getPhase().getStringValue())) return true;
}
return d1.getRequiringLevel() > d2.getRequiringLevel();
}
private static void fillParameterData(String name, ParameterData data, MavenDomMojo mojo) {
XmlTag config = mojo.getConfiguration().getXmlTag();
if (config == null) return;
@@ -153,15 +164,27 @@ public class MavenPluginConfigurationDomExtender extends DomExtender<MavenDomCon
}
}
private static void addRequiredAnnotation(DomExtension e, ParameterData data) {
if (!StringUtil.isEmptyOrSpaces(data.defaultValue)
|| !StringUtil.isEmptyOrSpaces(data.expression)) {
return;
}
private static void addRequiredAnnotation(DomExtension e, final ParameterData data) {
if (Boolean.parseBoolean(data.parameter.getRequired().getStringValue())) {
e.addCustomAnnotation(new Required(){
@Override
public boolean value() {
return StringUtil.isEmptyOrSpaces(data.defaultValue) && StringUtil.isEmptyOrSpaces(data.expression);
}
final String required = data.parameter.getRequired().getStringValue();
if (!StringUtil.isEmptyOrSpaces(required)) {
e.addCustomAnnotation(new MyRequired(required));
@Override
public boolean nonEmpty() {
return true;
}
@Override
public boolean identifier() {
return false;
}
public Class<? extends Annotation> annotationType() {
return Required.class;
}
});
}
}
@@ -181,43 +204,32 @@ public class MavenPluginConfigurationDomExtender extends DomExtender<MavenDomCon
String type = parameter.getType().getStringValue();
if (type.endsWith("[]")) return true;
List<String> collectionClasses = Arrays.asList("java.util.List",
"java.util.Set",
"java.util.Collection");
return collectionClasses.contains(type);
return type.equals("java.util.List") || type.equals("java.util.Set") || type.equals("java.util.Collection");
}
public static class ParameterData {
public MavenDomParameter parameter;
public final MavenDomParameter parameter;
public @Nullable String defaultValue;
public @Nullable String expression;
private ParameterData(MavenDomParameter parameter) {
this.parameter = parameter;
}
}
private static class MyRequired implements Required {
private final String myRequired;
public MyRequired(String required) {
myRequired = required;
@NotNull
public MavenDomMojo getMojo() {
return (MavenDomMojo)parameter.getParent().getParent();
}
public boolean value() {
return Boolean.valueOf(myRequired);
}
public int getRequiringLevel() {
if (!Boolean.parseBoolean(parameter.getRequired().getStringValue())) return 0;
public boolean nonEmpty() {
return false;
}
if (!StringUtil.isEmptyOrSpaces(defaultValue) || !StringUtil.isEmptyOrSpaces(expression)) {
return 1;
}
public boolean identifier() {
return false;
}
public Class<? extends Annotation> annotationType() {
return Required.class;
return 2;
}
}
}
@@ -23,6 +23,9 @@ public interface MavenDomMojo extends MavenDomElement {
@NotNull
GenericDomValue<String> getGoal();
@NotNull
GenericDomValue<String> getPhase();
@NotNull
MavenDomParameters getParameters();
@@ -31,6 +31,7 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformIcons;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomUtil;
@@ -51,13 +52,12 @@ import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
public class MavenPropertyPsiReference extends MavenPsiReference {
private static final Set<String> BASEDIR_PROPS =
new THashSet<String>(Arrays.asList("basedir", "project.basedir", "pom.basedir", "baseUri", "project.baseUri", "pom.baseUri"));
CollectionFactory.newTroveSet("basedir", "project.basedir", "pom.basedir", "baseUri", "project.baseUri", "pom.baseUri");
private static final String TIMESTAMP_PROP = "maven.build.timestamp";
@@ -896,25 +896,23 @@ public class MavenProject {
MavenProjectChanges result = new MavenProjectChanges();
result.packaging |= !Comparing.equal(myPackaging, other.myPackaging);
result.packaging = !Comparing.equal(myPackaging, other.myPackaging);
result.output |= !Comparing.equal(myFinalName, other.myFinalName);
result.output |= !Comparing.equal(myBuildDirectory, other.myBuildDirectory);
result.output |= !Comparing.equal(myOutputDirectory, other.myOutputDirectory);
result.output |= !Comparing.equal(myTestOutputDirectory, other.myTestOutputDirectory);
result.output = !Comparing.equal(myFinalName, other.myFinalName)
|| !Comparing.equal(myBuildDirectory, other.myBuildDirectory)
|| !Comparing.equal(myOutputDirectory, other.myOutputDirectory)
|| !Comparing.equal(myTestOutputDirectory, other.myTestOutputDirectory);
result.sources |= !Comparing.equal(mySources, other.mySources);
result.sources |= !Comparing.equal(myTestSources, other.myTestSources);
result.sources |= !Comparing.equal(myResources, other.myResources);
result.sources |= !Comparing.equal(myTestResources, other.myTestResources);
result.sources = !Comparing.equal(mySources, other.mySources)
|| !Comparing.equal(myTestSources, other.myTestSources)
|| !Comparing.equal(myResources, other.myResources)
|| !Comparing.equal(myTestResources, other.myTestResources);
boolean repositoryChanged = !Comparing.equal(myLocalRepository, other.myLocalRepository);
result.dependencies |= repositoryChanged;
result.dependencies |= !Comparing.equal(myDependencies, other.myDependencies);
result.dependencies = repositoryChanged || !Comparing.equal(myDependencies, other.myDependencies);
result.plugins |= repositoryChanged;
result.plugins |= !Comparing.equal(myPlugins, other.myPlugins);
result.plugins = repositoryChanged || !Comparing.equal(myPlugins, other.myPlugins);
return result;
}
@@ -0,0 +1,203 @@
<?xml version='1.0' encoding='UTF-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>maven-plugins</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<version>19</version>
<relativePath>../maven-plugins/pom.xml</relativePath>
</parent>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<packaging>maven-plugin</packaging>
<name>Maven Resources Plugin</name>
<description>
The Resources Plugin handles the copying of project resources to the output
directory. There are two different kinds of resources: main resources and test resources. The
difference is that the main resources are the resources associated to the main
source code while the test resources are associated to the test source code.
Thus, this allows the separation of resources for the main source code and its
unit tests.
</description>
<inceptionYear>2001</inceptionYear>
<prerequisites>
<maven>${mavenVersion}</maven>
</prerequisites>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/maven/plugins/tags/maven-resources-plugin-2.5</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/plugins/tags/maven-resources-plugin-2.5</developerConnection>
<url>http://svn.apache.org/viewvc/maven/plugins/tags/maven-resources-plugin-2.5</url>
</scm>
<issueManagement>
<system>JIRA</system>
<url>http://jira.codehaus.org/browse/MRESOURCES</url>
</issueManagement>
<properties>
<mavenFilteringVersion>1.0</mavenFilteringVersion>
<mavenVersion>2.0.6</mavenVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-settings</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-monitor</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
<version>1.0-alpha-9-stable-1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
<version>${mavenFilteringVersion}</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-interpolation</artifactId>
<version>1.13</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>1.0-beta-1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>run-its</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-descriptor</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-invoker-plugin</artifactId>
<configuration>
<debug>true</debug>
<projectsDirectory>src/it</projectsDirectory>
<pomIncludes>
<pomInclude>**/pom.xml</pomInclude>
</pomIncludes>
<postBuildHookScript>verify</postBuildHookScript>
<localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath>
<goals>
<goal>clean</goal>
<goal>process-test-resources</goal>
</goals>
<settingsFile>src/it/settings.xml</settingsFile>
<cloneProjectsTo>${project.build.directory}/it</cloneProjectsTo>
<properties>
<execProps>fromExecProps</execProps>
</properties>
</configuration>
<executions>
<execution>
<id>integration-test</id>
<goals>
<goal>install</goal>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
@@ -65,7 +65,7 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic
" </extensions>" +
"</build>");
assertCompletionVariants(myProjectPom, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin");
assertCompletionVariants(myProjectPom, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin", "maven-resources-plugin");
}
public void testArtifactWithoutGroupCompletion() throws Exception {
@@ -86,6 +86,7 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic
"maven-war-plugin",
"maven-surefire-plugin",
"build-helper-maven-plugin",
"maven-resources-plugin",
"maven-eclipse-plugin");
}
@@ -71,7 +71,7 @@ public class MavenPluginCompletionAndResolutionTest extends MavenDomWithIndicesT
" </plugins>" +
"</build>");
assertCompletionVariants(myProjectPom, "maven-compiler-plugin", "maven-war-plugin", "maven-surefire-plugin", "maven-eclipse-plugin");
assertCompletionVariants(myProjectPom, "maven-compiler-plugin", "maven-war-plugin", "maven-surefire-plugin", "maven-eclipse-plugin", "maven-resources-plugin");
}
public void testArtifactWithoutGroupCompletion() throws Exception {
@@ -92,6 +92,7 @@ public class MavenPluginCompletionAndResolutionTest extends MavenDomWithIndicesT
"maven-war-plugin",
"build-helper-maven-plugin",
"maven-surefire-plugin",
"maven-resources-plugin",
"maven-eclipse-plugin");
}
@@ -902,4 +903,59 @@ public class MavenPluginCompletionAndResolutionTest extends MavenDomWithIndicesT
assertCompletionVariants(myProjectPom);
}
public void testRequiringParameter() throws Throwable {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
"<version>1</version>" +
"<build>" +
" <plugins>" +
" <plugin>\n" +
" <artifactId>maven-resources-plugin</artifactId>\n" +
" <configuration>\n" +
" <<error descr=\"Value must not be empty\">outputDirectory</error>/>\n" +
" </configuration>\n" +
" </plugin>\n" +
" <plugin>\n" +
" <artifactId>maven-resources-plugin</artifactId>\n" +
"" +
" <configuration>\n" +
" <outputDirectory>aaa</outputDirectory>\n" +
" </configuration>\n" +
" </plugin>\n" +
" <plugin>\n" +
" <artifactId>maven-resources-plugin</artifactId>\n" +
"" +
" <configuration>\n" +
" </configuration>\n" +
" </plugin>\n" +
" <plugin>\n" +
" <artifactId>maven-resources-plugin</artifactId>\n" +
" <executions>" +
" <execution>" +
" <goals> " +
" <goal>copy-resources</goal>" +
" <goal>resources</goal>" +
" </goals> " +
" <<error descr=\"'outputDirectory' child tag should be defined\">configuration</error>>\n" +
" </configuration>\n" +
" " +
" </execution>" +
" </executions>" +
"" +
" <configuration>\n" +
" </configuration>\n" +
" </plugin>\n" +
" </plugins>" +
"</build>");
checkHighlighting();
}
}
@@ -129,6 +129,7 @@ public final class GuiEditor extends JPanel implements DataProvider {
private final Document myDocument;
final MainProcessor myProcessor;
@NotNull private final JScrollPane myScrollPane;
/**
* This layered pane contains all layers to lay components out and to
* show all necessary decoration items
@@ -302,11 +303,12 @@ public final class GuiEditor extends JPanel implements DataProvider {
gbc.gridy = 1;
gbc.weightx = 1.0;
gbc.weighty = 1.0;
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myLayeredPane);
scrollPane.setBackground(Color.WHITE);
panel.add(scrollPane, gbc);
myHorzCaptionPanel.attachToScrollPane(scrollPane);
myVertCaptionPanel.attachToScrollPane(scrollPane);
myScrollPane = ScrollPaneFactory.createScrollPane(myLayeredPane);
myScrollPane.setBackground(Color.WHITE);
panel.add(myScrollPane, gbc);
myHorzCaptionPanel.attachToScrollPane(myScrollPane);
myVertCaptionPanel.attachToScrollPane(myScrollPane);
myValidCard.add(panel, BorderLayout.CENTER);
@@ -319,7 +321,7 @@ public final class GuiEditor extends JPanel implements DataProvider {
myPsiTreeChangeListener = new MyPsiTreeChangeListener();
PsiManager.getInstance(module.getProject()).addPsiTreeChangeListener(myPsiTreeChangeListener);
myQuickFixManager = new QuickFixManagerImpl(this, myGlassLayer, scrollPane.getViewport());
myQuickFixManager = new QuickFixManagerImpl(this, myGlassLayer, myScrollPane.getViewport());
myDropTargetListener = new DesignDropTargetListener(this);
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
@@ -987,7 +989,9 @@ public final class GuiEditor extends JPanel implements DataProvider {
width += 50;
height += 40;
return new Dimension(width, height);
Rectangle bounds = myScrollPane.getViewport().getBounds();
return new Dimension(Math.max(width, bounds.width), Math.max(height, bounds.height));
}
public Dimension getPreferredScrollableViewportSize() {