diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 6b63c1264612..0da33fa5eb4f 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -8,7 +8,7 @@ OS_TYPE="`uname -s`" # --------------------------------------------------------------------- -# Locate a JDK installation directory which will be used to ruin the IDE. +# Locate a JDK installation directory which will be used to run the IDE. # Try (in order): @@product_uc@@_JDK, JDK_HOME, JAVA_HOME, "java" in PATH. # --------------------------------------------------------------------- if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then diff --git a/bin/scripts/win/idea.bat b/bin/scripts/win/idea.bat index d92bc5e11c1c..214e41642168 100644 --- a/bin/scripts/win/idea.bat +++ b/bin/scripts/win/idea.bat @@ -5,15 +5,21 @@ ::---------------------------------------------------------------------- :: --------------------------------------------------------------------- -:: Locate a JDK installation directory which will be used to ruin the IDE. -:: Try (in order): @@product_uc@@_JDK, JDK_HOME, JAVA_HOME. +:: Locate a JDK installation directory which will be used to run the IDE. +:: Try (in order): @@product_uc@@_JDK, ..\jre, JDK_HOME, JAVA_HOME. :: --------------------------------------------------------------------- -SET JDK=%@@product_uc@@_JDK% -IF "%JDK%" == "" SET JDK=%JDK_HOME% -IF "%JDK%" == "" SET JDK=%JAVA_HOME% +IF EXIST "%@@product_uc@@_JDK%" SET JDK=%@@product_uc@@_JDK% +IF NOT "%JDK%" == "" GOTO jdk +IF EXIST "%~dp0\..\jre" SET JDK=%~dp0\..\jre +IF NOT "%JDK%" == "" GOTO jdk +IF EXIST "%JDK_HOME%" SET JDK=%JDK_HOME% +IF NOT "%JDK%" == "" GOTO jdk +IF EXIST "%JAVA_HOME%" SET JDK=%JAVA_HOME% IF "%JDK%" == "" GOTO error +:jdk SET JAVA_EXE=%JDK%\bin\java.exe +IF NOT EXIST "%JAVA_EXE%" SET JAVA_EXE=%JDK%\jre\bin\java.exe IF NOT EXIST "%JAVA_EXE%" GOTO error :: --------------------------------------------------------------------- diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java index 8abbe757472b..ced65cfc37f5 100644 --- a/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/CompileServerManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -191,6 +191,14 @@ public class CompileServerManager implements ApplicationComponent{ sendNotification(paths, true); } + @Nullable + private static String getProjectPath(final Project project) { + final String path = project.getPresentableUrl(); + if (path == null) return path; + final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(path); + return vFile != null ? vFile.getPath() : null; + } + public void sendReloadRequest(final Project project) { if (!project.isDefault() && project.isOpen()) { myTaskExecutor.submit(new Runnable() { @@ -200,7 +208,7 @@ public class CompileServerManager implements ApplicationComponent{ if (!project.isDisposed()) { final CompileServerClient client = ensureServerRunningAndClientConnected(false); if (client != null) { - client.sendProjectReloadRequest(Collections.singletonList(project.getLocation())); + client.sendProjectReloadRequest(Collections.singletonList(getProjectPath(project))); } } } @@ -251,7 +259,7 @@ public class CompileServerManager implements ApplicationComponent{ } for (Project project : openProjects) { try { - client.sendFSEvent(project.getLocation(), changed, deleted); + client.sendFSEvent(getProjectPath(project), changed, deleted); } catch (Exception e) { LOG.info(e); @@ -317,7 +325,7 @@ public class CompileServerManager implements ApplicationComponent{ final Collection modules, final Collection artifacts, final Collection paths, final Map userData, final JpsServerResponseHandler handler) { - final String projectId = project.getLocation(); + final String projectId = getProjectPath(project); final Ref futureRef = new Ref(null); final RunnableFuture future = myTaskExecutor.submit(new Runnable() { public void run() { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java index 8d6d0f39f63d..36a1aa9a2ab0 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java @@ -431,23 +431,22 @@ public class CompileDriver { final MessageBus messageBus = myProject.getMessageBus(); csManager.cancelAutoMakeTasks(myProject); final CompileScope scope = compileContext.getCompileScope(); - final Map userData; // need to pass scope's user data to server - if (scope instanceof UserDataHolderBase) { // hack - userData = new HashMap(); - ((UserDataHolderBase)scope).copyUserDataTo(new UserDataHolderBase() { - @Override - public void putUserData(@NotNull Key key, @Nullable T value) { - final String _key = key.toString(); - final String _value = value != null? value.toString() : ""; - userData.put(_key, _value); - } - }); + final Map exported = scope.exportUserData(); + final Map builderParams; + if (!exported.isEmpty()) { + builderParams = new HashMap(); + for (Map.Entry entry : exported.entrySet()) { + final String _key = entry.getKey().toString(); + final String _value = entry.getValue().toString(); + builderParams.put(_key, _value); + } } else { - userData = Collections.emptyMap(); + builderParams = Collections.emptyMap(); } - return csManager.submitCompilationTask(myProject, compileContext.isRebuild(), compileContext.isMake(), moduleNames, artifactNames, paths, userData, new JpsServerResponseHandler() { + return csManager.submitCompilationTask(myProject, compileContext.isRebuild(), compileContext.isMake(), moduleNames, artifactNames, paths, + builderParams, new JpsServerResponseHandler() { @Override public void handleCompileMessage(JpsRemoteProto.Message.Response.CompileMessage compilerMessage) { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompositeScope.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompositeScope.java index 9150c49c7a5a..2d18e44931e9 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/CompositeScope.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompositeScope.java @@ -22,10 +22,10 @@ package com.intellij.compiler.impl; import com.intellij.openapi.compiler.CompileScope; +import com.intellij.openapi.compiler.ExportableUserDataHolderBase; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; @@ -34,7 +34,7 @@ import org.jetbrains.annotations.NotNull; import java.util.*; -public class CompositeScope extends UserDataHolderBase implements CompileScope{ +public class CompositeScope extends ExportableUserDataHolderBase implements CompileScope{ private final List myScopes = new ArrayList(); public CompositeScope(CompileScope scope1, CompileScope scope2) { diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/FileIndexCompileScope.java b/java/compiler/impl/src/com/intellij/compiler/impl/FileIndexCompileScope.java index 9b6058469279..8f1f2dd3d560 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/FileIndexCompileScope.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/FileIndexCompileScope.java @@ -16,9 +16,9 @@ package com.intellij.compiler.impl; import com.intellij.openapi.compiler.CompileScope; +import com.intellij.openapi.compiler.ExportableUserDataHolderBase; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.roots.FileIndex; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; @@ -30,7 +30,7 @@ import java.util.List; * @author Eugene Zhuravlev * Date: Dec 18, 2003 */ -public abstract class FileIndexCompileScope extends UserDataHolderBase implements CompileScope { +public abstract class FileIndexCompileScope extends ExportableUserDataHolderBase implements CompileScope { protected abstract FileIndex[] getFileIndices(); diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/FileSetCompileScope.java b/java/compiler/impl/src/com/intellij/compiler/impl/FileSetCompileScope.java index 38ab59e6ee7b..ffa703b7215e 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/FileSetCompileScope.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/FileSetCompileScope.java @@ -23,10 +23,10 @@ package com.intellij.compiler.impl; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.compiler.CompileScope; +import com.intellij.openapi.compiler.ExportableUserDataHolderBase; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.module.Module; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -34,7 +34,7 @@ import org.jetbrains.annotations.NotNull; import java.util.*; -public class FileSetCompileScope extends UserDataHolderBase implements CompileScope { +public class FileSetCompileScope extends ExportableUserDataHolderBase implements CompileScope { private final Set myRootFiles = new HashSet(); private final Set myDirectoryUrls = new HashSet(); private Set myUrls = null; // urls caching diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/OneProjectItemCompileScope.java b/java/compiler/impl/src/com/intellij/compiler/impl/OneProjectItemCompileScope.java index d85b28af44e8..4b0b653e3723 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/OneProjectItemCompileScope.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/OneProjectItemCompileScope.java @@ -16,6 +16,7 @@ package com.intellij.compiler.impl; import com.intellij.openapi.compiler.CompileScope; +import com.intellij.openapi.compiler.ExportableUserDataHolderBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; @@ -24,7 +25,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.roots.FileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -33,7 +33,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class OneProjectItemCompileScope extends UserDataHolderBase implements CompileScope{ +public class OneProjectItemCompileScope extends ExportableUserDataHolderBase implements CompileScope{ private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.OneProjectItemCompileScope"); private final Project myProject; private final VirtualFile myFile; diff --git a/java/compiler/impl/src/com/intellij/compiler/options/ValidationConfiguration.java b/java/compiler/impl/src/com/intellij/compiler/options/ValidationConfiguration.java new file mode 100644 index 000000000000..09ec3197ab47 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/options/ValidationConfiguration.java @@ -0,0 +1,74 @@ +package com.intellij.compiler.options; + +import com.intellij.openapi.compiler.CompileContext; +import com.intellij.openapi.compiler.Compiler; +import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration; +import com.intellij.openapi.components.*; +import com.intellij.openapi.project.Project; +import com.intellij.util.xmlb.XmlSerializerUtil; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Dmitry Avdeev + */ +@State( + name = "ValidationConfiguration", + storages = { + @Storage( file = "$WORKSPACE_FILE$"), + @Storage( file = "$PROJECT_CONFIG_DIR$/validation.xml", scheme = StorageScheme.DIRECTORY_BASED) + } +) +public class ValidationConfiguration implements PersistentStateComponent { + + public boolean VALIDATE_ON_BUILD = false; + public Map VALIDATORS = new HashMap(); + + public static boolean shouldValidate(Compiler validator, CompileContext context) { + ValidationConfiguration configuration = getInstance(context.getProject()); + return (configuration.VALIDATE_ON_BUILD) && configuration.isSelected(validator); + } + + public boolean isSelected(Compiler validator) { + return isSelected(validator.getDescription()); + } + + public boolean isSelected(String validatorDescription) { + final Boolean selected = VALIDATORS.get(validatorDescription); + return selected == null || selected.booleanValue(); + } + + public void setSelected(Compiler validator, boolean selected) { + setSelected(validator.getDescription(), selected); + } + + public void setSelected(String validatorDescription, boolean selected) { + VALIDATORS.put(validatorDescription, selected); + } + + public static ValidationConfiguration getInstance(Project project) { + return ServiceManager.getService(project, ValidationConfiguration.class); + } + + public static ExcludedEntriesConfiguration getExcludedEntriesConfiguration(Project project) { + return ServiceManager.getService(project, ExcludedFromValidationConfiguration.class); + } + + public ValidationConfiguration getState() { + return this; + } + + public void loadState(final ValidationConfiguration state) { + XmlSerializerUtil.copyBean(state, this); + } + + @State( + name = "ExcludeFromValidation", + storages = { + @Storage( file = "$PROJECT_FILE$"), + @Storage( file = "$PROJECT_CONFIG_DIR$/excludeFromValidation.xml", scheme = StorageScheme.DIRECTORY_BASED) + } + ) + public static class ExcludedFromValidationConfiguration extends ExcludedEntriesConfiguration {} +} diff --git a/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java new file mode 100644 index 000000000000..13847effb15f --- /dev/null +++ b/java/compiler/impl/src/com/intellij/openapi/compiler/util/InspectionValidatorWrapper.java @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2000-2007 JetBrains s.r.o. All Rights Reserved. + */ +package com.intellij.openapi.compiler.util; + +import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; +import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.actions.CleanupInspectionIntention; +import com.intellij.compiler.options.ValidationConfiguration; +import com.intellij.lang.ExternalLanguageAnnotators; +import com.intellij.lang.StdLanguages; +import com.intellij.lang.annotation.Annotation; +import com.intellij.lang.annotation.AnnotationSession; +import com.intellij.lang.annotation.ExternalAnnotator; +import com.intellij.lang.annotation.HighlightSeverity; +import com.intellij.openapi.application.AccessToken; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.application.ReadActionProcessor; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.compiler.*; +import com.intellij.openapi.compiler.options.ExcludedEntriesConfiguration; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.xml.XmlFile; +import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.hash.LinkedHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.DataInput; +import java.io.IOException; +import java.util.*; + +/** + * @author peter + */ +public class InspectionValidatorWrapper implements Validator { + private final InspectionValidator myValidator; + private final PsiManager myPsiManager; + private final CompilerManager myCompilerManager; + private final InspectionManager myInspectionManager; + private final InspectionProjectProfileManager myProfileManager; + private final PsiDocumentManager myPsiDocumentManager; + private static final ThreadLocal ourCompilationThreads = new ThreadLocal() { + protected Boolean initialValue() { + return Boolean.FALSE; + } + }; + + public InspectionValidatorWrapper(final CompilerManager compilerManager, final InspectionManager inspectionManager, + final InspectionProjectProfileManager profileManager, final PsiDocumentManager psiDocumentManager, + final PsiManager psiManager, final InspectionValidator validator) { + myCompilerManager = compilerManager; + myInspectionManager = inspectionManager; + myProfileManager = profileManager; + myPsiDocumentManager = psiDocumentManager; + myPsiManager = psiManager; + myValidator = validator; + } + + public static boolean isCompilationThread() { + return ourCompilationThreads.get().booleanValue(); + } + + private class MyValidatorProcessingItem implements ProcessingItem { + private final VirtualFile myVirtualFile; + private final PsiFile myPsiFile; + private PsiElementsValidityState myValidityState; + + public MyValidatorProcessingItem(@NotNull final PsiFile psiFile) { + myPsiFile = psiFile; + myVirtualFile = psiFile.getVirtualFile(); + } + + @NotNull + public VirtualFile getFile() { + return myVirtualFile; + } + + @Nullable + public ValidityState getValidityState() { + if (myValidityState == null) { + myValidityState = computeValidityState(); + } + return myValidityState; + } + + private PsiElementsValidityState computeValidityState() { + final PsiElementsValidityState state = new PsiElementsValidityState(); + for (PsiElement psiElement : myValidator.getDependencies(myPsiFile)) { + state.addDependency(psiElement); + } + return state; + } + + public PsiFile getPsiFile() { + return myPsiFile; + } + } + + @NotNull + public ProcessingItem[] getProcessingItems(final CompileContext context) { + final Project project = context.getProject(); + if (!ValidationConfiguration.shouldValidate(this, context)) { + return ProcessingItem.EMPTY_ARRAY; + } + final ExcludedEntriesConfiguration excludedEntriesConfiguration = ValidationConfiguration.getExcludedEntriesConfiguration(project); + final List items = new ReadAction>() { + protected void run(final Result> result) { + final CompileScope compileScope = context.getCompileScope(); + if (!myValidator.isAvailableOnScope(compileScope)) return; + + final ArrayList items = new ArrayList(); + + final Processor processor = new ReadActionProcessor() { + @Override + public boolean processInReadAction(VirtualFile file) { + if (!file.isValid()) { + return true; + } + + if (myCompilerManager.isExcludedFromCompilation(file) || + excludedEntriesConfiguration.isExcluded(file)) { + return true; + } + + final Module module = context.getModuleByFile(file); + if (module != null) { + final PsiFile psiFile = myPsiManager.findFile(file); + if (psiFile != null) { + items.add(new MyValidatorProcessingItem(psiFile)); + } + } + return true; + } + }; + ContainerUtil.process(myValidator.getFilesToProcess(myPsiManager.getProject(), context), processor); + + result.setResult(items); + } + }.execute().getResultObject(); + if (items == null) return ProcessingItem.EMPTY_ARRAY; + + return items.toArray(new ProcessingItem[items.size()]); + } + + public ProcessingItem[] process(final CompileContext context, final ProcessingItem[] items) { + context.getProgressIndicator().setText(myValidator.getProgressIndicatorText()); + + final List processedItems = new ArrayList(); + final List inspections = new ArrayList(); + for (final Class aClass : myValidator.getInspectionToolClasses(context)) { + try { + inspections.add((LocalInspectionTool)aClass.newInstance()); + } + catch (RuntimeException e) { + throw e; + } + catch (Exception e) { + throw new Error(e); + } + } + for (int i = 0; i < items.length; i++) { + final MyValidatorProcessingItem item = (MyValidatorProcessingItem)items[i]; + context.getProgressIndicator().checkCanceled(); + context.getProgressIndicator().setFraction((double)i / items.length); + + try { + ourCompilationThreads.set(Boolean.TRUE); + + if (checkFile(inspections, item.getPsiFile(), context)) { + processedItems.add(item); + } + } + finally { + ourCompilationThreads.set(Boolean.FALSE); + } + } + + return processedItems.toArray(new ProcessingItem[processedItems.size()]); + } + + private boolean checkFile(List inspections, final PsiFile file, CompileContext context) { + if (!checkUnderReadAction(file, context, new Computable>() { + @Override + public Map compute() { + return myValidator.checkAdditionally(file); + } + })) { + return false; + } + + if (!checkUnderReadAction(file, context, new Computable>() { + @Override + public Map compute() { + if (file instanceof XmlFile) { + return runXmlFileSchemaValidation((XmlFile)file); + } + return Collections.emptyMap(); + } + })) return false; + + + final InspectionProfile inspectionProfile = myProfileManager.getInspectionProfile(); + for (final LocalInspectionTool inspectionTool : inspections) { + if (!checkUnderReadAction(file, context, new Computable>() { + @Override + public Map compute() { + if (getHighlightDisplayLevel(inspectionTool, inspectionProfile, file) != HighlightDisplayLevel.DO_NOT_SHOW) { + return runInspectionTool(file, inspectionTool, getHighlightDisplayLevel(inspectionTool, inspectionProfile, file)); + } + return Collections.emptyMap(); + } + })) return false; + } + return true; + } + + private boolean checkUnderReadAction(PsiFile file, CompileContext context, Computable> runnable) { + AccessToken token = ReadAction.start(); + try { + if (!file.isValid()) return false; + + final Document document = myPsiDocumentManager.getCachedDocument(file); + if (document != null && myPsiDocumentManager.isUncommited(document)) { + final String url = file.getViewProvider().getVirtualFile().getUrl(); + context.addMessage(CompilerMessageCategory.WARNING, CompilerBundle.message("warning.text.file.has.been.changed"), url, -1, -1); + return false; + } + + if (reportProblems(context, runnable.compute())) return false; + } + finally { + token.finish(); + } + return true; + } + + private boolean reportProblems(CompileContext context, Map problemsMap) { + if (problemsMap.isEmpty()) { + return false; + } + + for (Map.Entry entry : problemsMap.entrySet()) { + ProblemDescriptor problemDescriptor = entry.getKey(); + final PsiElement element = problemDescriptor.getPsiElement(); + final PsiFile psiFile = element.getContainingFile(); + if (psiFile == null) continue; + + final VirtualFile virtualFile = psiFile.getVirtualFile(); + if (virtualFile == null) continue; + + final CompilerMessageCategory category = myValidator.getCategoryByHighlightDisplayLevel(entry.getValue(), virtualFile, context); + final Document document = myPsiDocumentManager.getDocument(psiFile); + + final int offset = problemDescriptor.getStartElement().getTextOffset(); + assert document != null; + final int line = document.getLineNumber(offset); + final int column = offset - document.getLineStartOffset(line); + context.addMessage(category, problemDescriptor.getDescriptionTemplate(), virtualFile.getUrl(), line + 1, column + 1); + } + return true; + } + + private static Map runInspectionTool(final PsiFile file, + final LocalInspectionTool inspectionTool, + final HighlightDisplayLevel level) { + Map problemsMap = new LinkedHashMap(); + for (CommonProblemDescriptor descriptor : CleanupInspectionIntention.runInspectionOnFile(file, inspectionTool)) { + if (descriptor instanceof ProblemDescriptor) { + problemsMap.put((ProblemDescriptor)descriptor, level); + } + } + return problemsMap; + } + + private static HighlightDisplayLevel getHighlightDisplayLevel(final LocalInspectionTool inspectionTool, + final InspectionProfile inspectionProfile, PsiElement file) { + final HighlightDisplayKey key = HighlightDisplayKey.find(inspectionTool.getShortName()); + return inspectionProfile.isToolEnabled(key, file) ? inspectionProfile.getErrorLevel(key, file) : HighlightDisplayLevel.DO_NOT_SHOW; + } + + private Map runXmlFileSchemaValidation(@NotNull XmlFile xmlFile) { + final AnnotationHolderImpl holder = new AnnotationHolderImpl(new AnnotationSession(xmlFile)); + + final List annotators = ExternalLanguageAnnotators.allForFile(StdLanguages.XML, xmlFile); + for (ExternalAnnotator annotator : annotators) { + annotator.annotate(xmlFile, holder); + } + + if (!holder.hasAnnotations()) return Collections.emptyMap(); + + Map problemsMap = new LinkedHashMap(); + for (final Annotation annotation : holder) { + final HighlightInfo info = HighlightInfo.fromAnnotation(annotation); + if (info.getSeverity() == HighlightSeverity.INFORMATION) continue; + + final PsiElement startElement = xmlFile.findElementAt(info.startOffset); + final PsiElement endElement = info.startOffset == info.endOffset ? startElement : xmlFile.findElementAt(info.endOffset - 1); + if (startElement == null || endElement == null) continue; + + final ProblemDescriptor descriptor = + myInspectionManager.createProblemDescriptor(startElement, endElement, info.description, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + false); + final HighlightDisplayLevel level = info.getSeverity() == HighlightSeverity.ERROR? HighlightDisplayLevel.ERROR: HighlightDisplayLevel.WARNING; + problemsMap.put(descriptor, level); + } + return problemsMap; + } + + + @NotNull + public String getDescription() { + return myValidator.getDescription(); + } + + public boolean validateConfiguration(final CompileScope scope) { + return true; + } + + public ValidityState createValidityState(final DataInput in) throws IOException { + return PsiElementsValidityState.load(in); + } + +} diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompileScope.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompileScope.java index f1329adae1e5..5e1c30445f89 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompileScope.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompileScope.java @@ -17,7 +17,6 @@ package com.intellij.openapi.compiler; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; -import com.intellij.openapi.util.UserDataHolder; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +27,7 @@ import org.jetbrains.annotations.Nullable; * * @see CompilerManager#compile(CompileScope, CompileStatusNotification) */ -public interface CompileScope extends UserDataHolder { +public interface CompileScope extends ExportableUserDataHolder { CompileScope[] EMPTY_ARRAY = new CompileScope[0]; /** * Returns the list of files within the scope. diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerPaths.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerPaths.java index 7f21c224225f..b366bc5a443d 100644 --- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerPaths.java +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerPaths.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -96,13 +96,17 @@ public class CompilerPaths { return new File(getCompilerSystemDirectory(), projectName + "." + project.getLocationHash()); } + @Nullable private static String getPresentableName(final Project project) { if (project.isDefault()) { return project.getName(); } - String location = project.getLocation(); - if (location == null) return null; + String location = project.getPresentableUrl(); + if (location == null) { + return null; + } + String projectName = FileUtil.toSystemIndependentName(location); if (projectName.endsWith("/")) { projectName = projectName.substring(0, projectName.length() - 1); diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolder.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolder.java new file mode 100644 index 000000000000..1dda010557ea --- /dev/null +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolder.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.compiler; + +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolder; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +/** + * @author Eugene Zhuravlev + * Date: 2/21/12 + */ +public interface ExportableUserDataHolder extends UserDataHolder{ + + @NotNull + Map exportUserData(); + +} diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolderBase.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolderBase.java new file mode 100644 index 000000000000..4f4e20d569dd --- /dev/null +++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/ExportableUserDataHolderBase.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.compiler; + +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderBase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class ExportableUserDataHolderBase extends UserDataHolderBase implements ExportableUserDataHolder{ + private final Set myKeys = Collections.synchronizedSet(new HashSet()); + + @NotNull + public final Map exportUserData() { + final Map result = new HashMap(); + synchronized (myKeys) { + for (Key k : myKeys) { + final Object data = getUserData(k); + if (data != null) { + result.put(k, data); + } + } + } + return result; + } + + @Override + public final void putUserData(@NotNull Key key, @Nullable T value) { + if (value != null) { + myKeys.add(key); + } + else { + myKeys.remove(key); + } + super.putUserData(key, value); + } + +} diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/UpdatableDebuggerView.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/UpdatableDebuggerView.java index f042bf22a7c2..450161bd661a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/UpdatableDebuggerView.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/UpdatableDebuggerView.java @@ -35,7 +35,7 @@ public abstract class UpdatableDebuggerView extends JPanel implements DebuggerVi private final DebuggerStateManager myStateManager; private volatile boolean myRefreshNeeded = true; private final java.util.List myDisposables = new ArrayList(); - private boolean myUpdateEnabled; + private volatile boolean myUpdateEnabled; protected UpdatableDebuggerView(final Project project, final DebuggerStateManager stateManager) { setLayout(new BorderLayout()); diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java index e28c2a3041ef..cd5861f2d579 100644 --- a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java +++ b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java @@ -27,10 +27,12 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.awt.*; +import java.util.Map; /** * @author gregsh @@ -62,38 +64,48 @@ public class ExceptionExFilterFactory implements ExceptionFilterFactory { final int startOffset, int startLineNumber, final Consumer consumer) { + Map> visited = new THashMap>(); + final Trinity emptyInfo = Trinity.create(null, null, null); + + final ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope); for (int i = 0; i < copiedFragment.getLineCount(); i++) { final int lineStartOffset = copiedFragment.getLineStartOffset(i); final int lineEndOffset = copiedFragment.getLineEndOffset(i); - final ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope); - Result result = null; - AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); - try { - String text = copiedFragment.getText(new TextRange(lineStartOffset, lineEndOffset)); - worker.execute(text, lineEndOffset); - result = worker.getResult(); - if (result == null) continue; - int offset = result.hyperlinkInfo instanceof OpenFileHyperlinkInfo - ? ((OpenFileHyperlinkInfo)result.hyperlinkInfo).getDescriptor().getOffset() - : -1; - PsiFile psiFile = worker.getFile(); - if (offset <= 0 || psiFile == null) continue; - PsiElement element = psiFile.findElementAt(offset); - PsiTryStatement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, true, PsiClass.class); - PsiCodeBlock tryBlock = parent != null? parent.getTryBlock() : null; - if (tryBlock == null || !tryBlock.getTextRange().contains(offset)) continue; + + String text = copiedFragment.getText(new TextRange(lineStartOffset, lineEndOffset)); + if (!text.contains(".java:")) continue; + Trinity info = visited.get(text); + if (info == emptyInfo) continue; + + if (info == null) { + info = emptyInfo; + AccessToken token = ApplicationManager.getApplication().acquireReadActionLock(); + try { + worker.execute(text, lineEndOffset); + Result result = worker.getResult(); + if (result == null) continue; + int offset = result.hyperlinkInfo instanceof OpenFileHyperlinkInfo + ? ((OpenFileHyperlinkInfo)result.hyperlinkInfo).getDescriptor().getOffset() + : -1; + PsiFile psiFile = worker.getFile(); + if (offset <= 0 || psiFile == null) continue; + PsiElement element = psiFile.findElementAt(offset); + PsiTryStatement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, true, PsiClass.class); + PsiCodeBlock tryBlock = parent != null? parent.getTryBlock() : null; + if (tryBlock == null || !tryBlock.getTextRange().contains(offset)) continue; + info = worker.getInfo(); + } + finally { + token.finish(); + visited.put(text, info); + } } - finally { - token.finish(); - } - Trinity info = worker.getInfo(); int off = startOffset + lineStartOffset; - final TextAttributes attributes = result.highlightAttributes; - attributes.setEffectColor(UIUtil.getInactiveTextColor()); + final Color color = UIUtil.getInactiveTextColor(); consumer.consume(new AdditionalHighlight(off + info.first.getStartOffset(), off + info.second.getEndOffset()) { @Override public TextAttributes getTextAttributes(@Nullable TextAttributes source) { - return new TextAttributes(null, null, attributes.getEffectColor(), EffectType.BOLD_DOTTED_LINE, Font.PLAIN); + return new TextAttributes(null, null, color, EffectType.BOLD_DOTTED_LINE, Font.PLAIN); } }); } @@ -101,7 +113,7 @@ public class ExceptionExFilterFactory implements ExceptionFilterFactory { @Override public String getUpdateMessage() { - return "Checking try/finally blocks"; + return "Highlighting try blocks"; } } } diff --git a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java index c3ff4043ae1e..cd5a83b0d706 100644 --- a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java +++ b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.util.messages.MessageBus; -import java.io.File; - @State( name = "RecentProjectsManager", roamingType = RoamingType.DISABLED, @@ -39,8 +37,7 @@ public class RecentProjectsManager extends RecentProjectsManagerBase { } protected String getProjectPath(Project project) { - final String location = project.getLocation(); - return location == null ? null : location.replace('/', File.separatorChar); + return project.getPresentableUrl(); } protected void doOpenProject(final String projectPath, Project projectToClose, final boolean forceOpenInNewFrame) { diff --git a/java/idea-ui/src/com/intellij/openapi/wm/IdeaFrameTitleBuilder.java b/java/idea-ui/src/com/intellij/openapi/wm/IdeaFrameTitleBuilder.java index b82da4da9fd1..9796f9e8db3b 100644 --- a/java/idea-ui/src/com/intellij/openapi/wm/IdeaFrameTitleBuilder.java +++ b/java/idea-ui/src/com/intellij/openapi/wm/IdeaFrameTitleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +20,14 @@ import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.impl.PlatformFrameTitleBuilder; +import org.jetbrains.annotations.NotNull; /** * @author yole */ public class IdeaFrameTitleBuilder extends PlatformFrameTitleBuilder { - public String getFileTitle(final Project project, final VirtualFile file) { + @Override + public String getFileTitle(@NotNull final Project project, @NotNull final VirtualFile file) { return ProjectUtil.calcRelativeToProjectPath(file, project, !SystemInfo.isMac); } } diff --git a/java/idea-ui/src/com/intellij/projectImport/ImportChooserStep.java b/java/idea-ui/src/com/intellij/projectImport/ImportChooserStep.java index ca6a78393e69..08b6334ea172 100644 --- a/java/idea-ui/src/com/intellij/projectImport/ImportChooserStep.java +++ b/java/idea-ui/src/com/intellij/projectImport/ImportChooserStep.java @@ -32,6 +32,8 @@ import javax.swing.*; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -85,6 +87,14 @@ public class ImportChooserStep extends ProjectImportWizardStep { } } } + myList.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { + context.requestNextStep(); + } + } + }); } private static List sorted(ProjectImportProvider[] providers) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java index a70318059c7c..a52716124bf7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java @@ -18,11 +18,9 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.completion.impl.CamelHumpMatcher; import com.intellij.codeInsight.lookup.AutoCompletionPolicy; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiJavaCodeReferenceElement; -import com.intellij.psi.PsiReferenceExpression; -import com.intellij.psi.PsiType; +import com.intellij.psi.*; import com.intellij.psi.filters.ElementFilter; +import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.util.CollectConsumer; import com.intellij.util.Consumer; @@ -92,6 +90,11 @@ public class JavaNoVariantsDelegator extends NoVariantsDelegator { PrefixMatcher qMatcher = new CamelHumpMatcher(referenceName); Set plainVariants = JavaSmartCompletionContributor.completeReference(qualifier, qualifier, filter, true, true, parameters, qMatcher); + + for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { + plainVariants.add(JavaClassNameCompletionContributor.createClassLookupItem(aClass, true)); + } + if (!plainVariants.isEmpty()) { return plainVariants; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java index 7401ad126927..ddce0ac7c902 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ChangeMethodSignatureFromUsageFix.java @@ -178,11 +178,27 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP final PsiMethod method = SuperMethodWarningUtil.checkSuperMethod(myTargetMethod, RefactoringBundle.message("to.refactor")); if (method == null) return; - if (!CodeInsightUtilBase.prepareFileForWrite(method.getContainingFile())) return; + myNewParametersInfo = getNewParametersInfo(myExpressions, myTargetMethod, mySubstitutor); + final List parameterInfos = + performChange(project, editor, file, method, myMinUsagesNumberToShowDialog, myNewParametersInfo, myChangeAllUsages, false); + if (parameterInfos != null) { + myNewParametersInfo = parameterInfos.toArray(new ParameterInfoImpl[parameterInfos.size()]); + } + } + + public static List performChange(final Project project, + final Editor editor, + final PsiFile file, + final PsiMethod method, + final int minUsagesNumber, + final ParameterInfoImpl[] newParametersInfo, + final boolean changeAllUsages, + final boolean allowDelegation) { + if (!CodeInsightUtilBase.prepareFileForWrite(method.getContainingFile())) return null; final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager(); final FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(method, false); - if (handler == null) return; //on failure or cancel (e.g. cancel of super methods dialog) + if (handler == null) return null;//on failure or cancel (e.g. cancel of super methods dialog) final JavaMethodFindUsagesOptions options = new JavaMethodFindUsagesOptions(project); options.isImplementingMethods = true; @@ -196,7 +212,7 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP Processor processor = new Processor() { @Override public boolean process(final UsageInfo t) { - return ++usagesFound[0] < myMinUsagesNumberToShowDialog; + return ++usagesFound[0] < minUsagesNumber; } }; @@ -204,21 +220,20 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP } }; String progressTitle = QuickFixBundle.message("searching.for.usages.progress.title"); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, progressTitle, true, project)) return; + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(runnable, progressTitle, true, project)) return null; - myNewParametersInfo = getNewParametersInfo(myExpressions, myTargetMethod, mySubstitutor); - if (ApplicationManager.getApplication().isUnitTestMode() || usagesFound[0] < myMinUsagesNumberToShowDialog) { + if (ApplicationManager.getApplication().isUnitTestMode() || usagesFound[0] < minUsagesNumber) { ChangeSignatureProcessor processor = new ChangeSignatureProcessor( project, method, false, null, method.getName(), method.getReturnType(), - myNewParametersInfo){ + newParametersInfo){ @Override @NotNull protected UsageInfo[] findUsages() { - return myChangeAllUsages ? super.findUsages() : UsageInfo.EMPTY_ARRAY; + return changeAllUsages ? super.findUsages() : UsageInfo.EMPTY_ARRAY; } }; processor.run(); @@ -230,25 +245,21 @@ public class ChangeMethodSignatureFromUsageFix implements IntentionAction, HighP }); } else { - List parameterInfos = myNewParametersInfo != null - ? new ArrayList(Arrays.asList(myNewParametersInfo)) + List parameterInfos = newParametersInfo != null + ? new ArrayList(Arrays.asList(newParametersInfo)) : new ArrayList(); final PsiReferenceExpression refExpr = TargetElementUtil.findReferenceExpression(editor); - JavaChangeSignatureDialog dialog = new JavaChangeSignatureDialog(project, method, allowDelegate(), refExpr); + JavaChangeSignatureDialog dialog = new JavaChangeSignatureDialog(project, method, allowDelegation, refExpr); dialog.setParameterInfos(parameterInfos); dialog.show(); - List parameters = dialog.getParameters(); - myNewParametersInfo = parameters.toArray(new ParameterInfoImpl[parameters.size()]); + return dialog.getParameters(); } + return null; } - protected boolean allowDelegate() { - return false; - } - - public String getNewParameterNameByOldIndex(int oldIndex) { - if (myNewParametersInfo == null) return null; - for (ParameterInfoImpl info : myNewParametersInfo) { + public static String getNewParameterNameByOldIndex(int oldIndex, final ParameterInfoImpl[] parametersInfo) { + if (parametersInfo == null) return null; + for (ParameterInfoImpl info : parametersInfo) { if (info.oldParameterIndex == oldIndex) { return info.getName(); } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java index 01b775f16b30..1f4e18cb3a7e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java @@ -19,28 +19,33 @@ import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil; +import com.intellij.codeInsight.generation.PsiElementClassMember; +import com.intellij.codeInsight.generation.PsiFieldMember; import com.intellij.codeInsight.generation.PsiMethodMember; -import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.impl.AssignFieldFromParameterAction; +import com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction; import com.intellij.ide.util.MemberChooser; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.impl.source.jsp.jspJava.JspClass; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.changeSignature.ParameterInfoImpl; import com.intellij.refactoring.util.RefactoringUtil; -import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ConcurrentWeakHashMap; import org.jetbrains.annotations.NotNull; @@ -143,25 +148,40 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { } else if (!constrs.isEmpty()) { final Collection> fieldsToFix = getFieldsToFix(); - final PsiMethod constructor = constrs.get(0); - final List fields = new ArrayList(); - for (SmartPsiElementPointer elementPointer : fieldsToFix) { - final PsiField field = elementPointer.getElement(); - if (field != null && isAvailable(field) && filterConstructorsIfFieldAlreadyAssigned(new PsiMethod[]{constructor}, field).contains(constructor)) { - fields.add(field); + try { + final PsiMethod constructor = constrs.get(0); + final List fields = new ArrayList(); + for (SmartPsiElementPointer elementPointer : fieldsToFix) { + final PsiField field = elementPointer.getElement(); + if (field != null && isAvailable(field) && filterConstructorsIfFieldAlreadyAssigned(new PsiMethod[]{constructor}, field).contains(constructor)) { + fields.add(field); + } + } + if (constrs.size() == constructors.length && fields.size() > 1 && !ApplicationManager.getApplication().isUnitTestMode()) { + PsiFieldMember[] members = new PsiFieldMember[fields.size()]; + int i = 0; + for (PsiField field : fields) { + members[i++] = new PsiFieldMember(field); + } + MemberChooser chooser = new MemberChooser(members, false, true, project); + chooser.setTitle("Choose Fields to Generate Constructor Parameters for"); + chooser.show(); + if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return; + final List selectedElements = chooser.getSelectedElements(); + if (selectedElements == null) return; + fields.clear(); + for (PsiElementClassMember member : selectedElements) { + fields.add((PsiField)member.getElement()); + } } - } - Collections.sort(fields, new Comparator() { - @Override - public int compare(PsiField o1, PsiField o2) { - return o1.getTextOffset() - o2.getTextOffset(); - } - }); - addParameterToConstructor(project, file, editor, constructor, constrs.size() == constructors.length - ? fields.toArray(new PsiField[fields.size()]) - : new PsiField[]{getField()}); - fieldsToFix.clear(); + addParameterToConstructor(project, file, editor, constructor, constrs.size() == constructors.length + ? fields.toArray(new PsiField[fields.size()]) + : new PsiField[]{getField()}); + } + finally { + fieldsToFix.clear(); + } } } @@ -211,45 +231,81 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { final Editor editor, final PsiMethod constructor, final PsiField[] fields) throws IncorrectOperationException { - final PsiParameter[] parameters = constructor.getParameterList().getParameters(); - PsiExpression[] expressions = new PsiExpression[parameters.length+fields.length]; - PsiElementFactory factory = JavaPsiFacade.getInstance(file.getProject()).getElementFactory(); + final PsiParameterList parameterList = constructor.getParameterList(); + final PsiParameter[] parameters = parameterList.getParameters(); + ParameterInfoImpl[] newParamInfos = new ParameterInfoImpl[parameters.length + fields.length]; + final List params = new ArrayList(Arrays.asList(parameters)); + Collections.addAll(params, fields); + Collections.sort(params, new FieldParameterComparator(parameterList)); + int i = 0; - for (; i < parameters.length; i++) { - PsiParameter parameter = parameters[i]; - String value = PsiTypesUtil.getDefaultValueOfType(parameter.getType()); - expressions[i] = factory.createExpressionFromText(value, parameter); - } - for (PsiField field : fields) { - expressions[i++] = factory.createExpressionFromText(field.getName(), constructor); - } - if (constructor.isVarArgs()) { - ArrayUtil.rotateLeft(expressions, parameters.length - 1, expressions.length - 1); + for (PsiVariable param : params) { + final PsiType paramType = param.getType(); + if (param instanceof PsiParameter) { + newParamInfos[i++] = new ParameterInfoImpl(parameterList.getParameterIndex((PsiParameter)param), param.getName(), paramType, param.getName()); + } else { + final String uniqueParameterName = getUniqueParameterName(parameters, param); + newParamInfos[i++] = new ParameterInfoImpl(-1, uniqueParameterName, paramType, uniqueParameterName); + } } final SmartPointerManager manager = SmartPointerManager.getInstance(project); final SmartPsiElementPointer constructorPointer = manager.createSmartPsiElementPointer(constructor); - final ChangeMethodSignatureFromUsageFix addParamFix = new ChangeMethodSignatureFromUsageFix(constructor, expressions, PsiSubstitutor.EMPTY, constructor, true, 1){ - @Override - protected boolean allowDelegate() { - return true; - } - }; - if (addParamFix.isAvailable(project, editor, file)) { - addParamFix.invoke(project, editor, file); - } else if (addParamFix.isMethodSignatureExists() && !ApplicationManager.getApplication().isUnitTestMode()) { - HintManager.getInstance().showErrorHint(editor, "Constructor with corresponding signature already exist"); - } + final PsiMethod fromText = JavaPsiFacade.getElementFactory(project).createMethodFromText(createDummyMethod(constructor, newParamInfos), + constructor); + final PsiClass containingClass = constructor.getContainingClass(); + if (containingClass == null) return false; + final int minUsagesNumber = containingClass.findMethodsBySignature(fromText, false).length > 0 ? 0 : 1; + final List parameterInfos = + ChangeMethodSignatureFromUsageFix.performChange(project, editor, file, constructor, minUsagesNumber, newParamInfos, true, true); + + final ParameterInfoImpl[] resultParams = parameterInfos != null ? parameterInfos.toArray(new ParameterInfoImpl[parameterInfos.size()]) : + newParamInfos; return ApplicationManager.getApplication().runWriteAction(new Computable() { @Override public Boolean compute() { - return doCreate(project, editor, parameters, constructorPointer, addParamFix, fields); + return doCreate(project, editor, parameters, constructorPointer, resultParams, fields); } }); } + private static String createDummyMethod(PsiMethod constructor, ParameterInfoImpl[] newParamInfos) { + return constructor.getName() + "(" + StringUtil.join(newParamInfos, new Function() { + @Override + public String fun(ParameterInfoImpl info) { + return info.getTypeText() + " " + info.getName(); + } + }, ", ") + "){}"; + } + + private static String getUniqueParameterName(PsiParameter[] parameters, PsiVariable variable) { + final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(variable.getProject()); + final SuggestedNameInfo nameInfo = styleManager + .suggestVariableName(VariableKind.PARAMETER, + styleManager.variableNameToPropertyName(variable.getName(), VariableKind.FIELD), + null, variable.getType()); + String newName = nameInfo.names[0]; + int n = 1; + while (true) { + if (isUnique(parameters, newName)) { + break; + } + newName = nameInfo.names[0] + n++; + } + return newName; + } + + private static boolean isUnique(PsiParameter[] params, String newName) { + for (PsiParameter parameter : params) { + if (Comparing.strEqual(parameter.getName(), newName)) { + return false; + } + } + return true; + } + private static boolean doCreate(Project project, Editor editor, PsiParameter[] parameters, SmartPsiElementPointer constructorPointer, - ChangeMethodSignatureFromUsageFix addParamFix, PsiField[] fields) { + ParameterInfoImpl[] parameterInfos, PsiField[] fields) { PsiMethod constructor = (PsiMethod)constructorPointer.getElement(); assert constructor != null; PsiParameter[] newParameters = constructor.getParameterList().getParameters(); @@ -265,7 +321,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { field.getType()).names[0]; PsiParameter parameter = findParamByName(defaultParamName, newParameters); if (parameter == null) { - parameter = fields.length == 1 ? findParamByName(addParamFix.getNewParameterNameByOldIndex(-1), newParameters) : null; + parameter = fields.length == 1 ? findParamByName(ChangeMethodSignatureFromUsageFix.getNewParameterNameByOldIndex(-1, parameterInfos), newParameters) : null; if (parameter == null) { continue; } @@ -306,4 +362,39 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { public boolean startInWriteAction() { return false; } + + private static class FieldParameterComparator implements Comparator { + private final PsiParameterList myParameterList; + + public FieldParameterComparator(PsiParameterList parameterList) { + myParameterList = parameterList; + } + + @Override + public int compare(PsiVariable o1, PsiVariable o2) { + + if (o1 instanceof PsiParameter && ((PsiParameter)o1).isVarArgs()) return 1; + if (o2 instanceof PsiParameter && ((PsiParameter)o2).isVarArgs()) return -1; + + if (o1 instanceof PsiField && o2 instanceof PsiField) { + return o1.getTextOffset() - o2.getTextOffset(); + } + if (o1 instanceof PsiParameter && o2 instanceof PsiParameter) { + return myParameterList.getParameterIndex((PsiParameter)o1) - myParameterList.getParameterIndex((PsiParameter)o2); + } + + if (o1 instanceof PsiField && o2 instanceof PsiParameter) { + final PsiField field = CreateFieldFromParameterAction.getParameterAssignedToField((PsiParameter)o2); + if (field == null) return 1; + return o1.getTextOffset() - field.getTextOffset(); + } + if (o1 instanceof PsiParameter && o2 instanceof PsiField) { + final PsiField field = CreateFieldFromParameterAction.getParameterAssignedToField((PsiParameter)o1); + if (field == null) return -1; + return field.getTextOffset() - o2.getTextOffset(); + } + + return 0; + } + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java index 2d4a27faa3c6..c74f1c7e59e8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFieldFromUsageFix.java @@ -54,7 +54,7 @@ public class CreateFieldFromUsageFix extends CreateVarFromUsageFix { @Override protected boolean canBeTargetClass(PsiClass psiClass) { - return super.canBeTargetClass(psiClass) && !psiClass.isInterface() && !psiClass.isAnnotationType(); + return psiClass.getManager().isInProject(psiClass) && !psiClass.isInterface() && !psiClass.isAnnotationType(); } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateVarFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateVarFromUsageFix.java index 1c86d8b35993..cbf51536f407 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateVarFromUsageFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateVarFromUsageFix.java @@ -24,6 +24,7 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethodCallExpression; import com.intellij.psi.PsiReferenceExpression; @@ -41,6 +42,11 @@ public abstract class CreateVarFromUsageFix extends CreateFromUsageBaseFix { return CreateFromUsageUtils.isValidReference(expression, false); } + @Override + protected boolean canBeTargetClass(PsiClass psiClass) { + return false; + } + @Override protected PsiElement getElement() { if (!myReferenceExpression.isValid() || !myReferenceExpression.getManager().isInProject(myReferenceExpression)) return null; diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AssignFieldFromParameterAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AssignFieldFromParameterAction.java index d38aa38b6d86..7ae40fc1ad26 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/AssignFieldFromParameterAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/AssignFieldFromParameterAction.java @@ -58,7 +58,7 @@ public class AssignFieldFromParameterAction extends BaseIntentionAction { || !type.isValid() || targetClass == null || targetClass.isInterface() - || CreateFieldFromParameterAction.isParameterAssignedToField(myParameter)) { + || CreateFieldFromParameterAction.getParameterAssignedToField(myParameter) != null) { return false; } PsiField field = findFieldToAssign(myParameter); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java index 01741ad97d18..38dda39044e0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterAction.java @@ -18,13 +18,17 @@ package com.intellij.codeInsight.intention.impl; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.NullableNotNullManager; +import com.intellij.codeInsight.generation.*; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.ide.util.MemberChooser; import com.intellij.lang.StdLanguages; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.TextRange; @@ -39,17 +43,24 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.ui.SimpleColoredComponent; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ConcurrentWeakHashMap; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.*; public class CreateFieldFromParameterAction implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.CreateFieldFromParameterAction"); + private static final Key, Boolean>> PARAMS = Key.create("FIELDS_FROM_PARAMS"); + private String myName = ""; @Nullable @@ -85,30 +96,74 @@ public class CreateFieldFromParameterAction implements IntentionAction { @NotNull public String getText() { + if (myName == null) return CodeInsightBundle.message("intention.create.fields.from.parameters.text"); return CodeInsightBundle.message("intention.create.field.from.parameter.text", myName); } public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - PsiParameter myParameter = findParameterAtCursor(file, editor); - if (myParameter == null) return false; - myName = myParameter.getName(); - final PsiType[] types = getTypes(myParameter); - PsiClass targetClass = PsiTreeUtil.getParentOfType(myParameter, PsiClass.class); - return - myParameter.isValid() - && myParameter.getLanguage().isKindOf(StdLanguages.JAVA) - && myParameter.getDeclarationScope() instanceof PsiMethod - && ((PsiMethod)myParameter.getDeclarationScope()).getBody() != null - && myParameter.getManager().isInProject(myParameter) - && types != null - && types[0].isValid() - && !isParameterAssignedToField(myParameter) - && targetClass != null - && !targetClass.isInterface() + PsiParameter psiParameter = findParameterAtCursor(file, editor); + if (psiParameter == null) return false; + final Collection> params = getUnboundedParams(psiParameter); + params.clear(); + final PsiParameter[] parameters = ((PsiMethod)psiParameter.getDeclarationScope()).getParameterList().getParameters(); + for (PsiParameter parameter : parameters) { + params.add(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(parameter)); + } + myName = params.size() > 1 && !ApplicationManager.getApplication().isUnitTestMode() ? null : psiParameter.getName(); + return isAvailable(psiParameter); + } + + private static boolean isAvailable(PsiParameter psiParameter) { + final PsiType[] types = getTypes(psiParameter); + PsiClass targetClass = PsiTreeUtil.getParentOfType(psiParameter, PsiClass.class); + return psiParameter.isValid() + && psiParameter.getLanguage().isKindOf(StdLanguages.JAVA) + && psiParameter.getDeclarationScope() instanceof PsiMethod + && ((PsiMethod)psiParameter.getDeclarationScope()).getBody() != null + && psiParameter.getManager().isInProject(psiParameter) + && types != null + && types[0].isValid() + && getParameterAssignedToField(psiParameter) == null + && targetClass != null + && !targetClass.isInterface() ; } - static boolean isParameterAssignedToField(final PsiParameter parameter) { + @NotNull + private static Collection> getUnboundedParams(PsiParameter parameter) { + final PsiElement psiElement = parameter.getDeclarationScope(); + if (!(psiElement instanceof PsiMethod)) return Collections.emptyList(); + final PsiMethod psiMethod = (PsiMethod)psiElement; + Map, Boolean> params = psiMethod.getUserData(PARAMS); + if (params == null) psiMethod.putUserData(PARAMS, params = new ConcurrentWeakHashMap, Boolean>(1)); + final Map, Boolean> finalParams = params; + return new AbstractCollection>() { + @Override + public boolean add(SmartPsiElementPointer psiVariable) { + PsiParameter psiParameter = psiVariable.getElement(); + if (psiParameter == null || !isAvailable(psiParameter)) return false; + return finalParams.put(psiVariable, Boolean.TRUE) == null; + } + + @Override + public Iterator> iterator() { + return finalParams.keySet().iterator(); + } + + @Override + public int size() { + return finalParams.size(); + } + + @Override + public void clear() { + finalParams.clear(); + } + }; + } + + @Nullable + public static PsiField getParameterAssignedToField(final PsiParameter parameter) { for (PsiReference reference : ReferencesSearch.search(parameter, new LocalSearchScope(parameter.getDeclarationScope()), false)) { if (!(reference instanceof PsiReferenceExpression)) continue; final PsiReferenceExpression expression = (PsiReferenceExpression)reference; @@ -118,10 +173,9 @@ public class CreateFieldFromParameterAction implements IntentionAction { final PsiExpression lExpression = assignmentExpression.getLExpression(); if (!(lExpression instanceof PsiReferenceExpression)) continue; final PsiElement element = ((PsiReferenceExpression)lExpression).resolve(); - if (!(element instanceof PsiField)) continue; - return true; + if (element instanceof PsiField) return (PsiField)element; } - return false; + return null; } @Nullable @@ -149,7 +203,56 @@ public class CreateFieldFromParameterAction implements IntentionAction { private static void invoke(final Project project, Editor editor, PsiFile file, boolean isInteractive) { final PsiParameter myParameter = findParameterAtCursor(file, editor); if (!CodeInsightUtilBase.prepareFileForWrite(myParameter.getContainingFile())) return; + final Collection> unboundedParams = getUnboundedParams(myParameter); + if (unboundedParams.size() > 1 && !ApplicationManager.getApplication().isUnitTestMode()) { + ClassMember[] members = new ClassMember[unboundedParams.size()]; + ClassMember selection = null; + int i = 0; + for (SmartPsiElementPointer pointer : unboundedParams) { + final PsiParameter parameter = pointer.getElement(); + final ParameterClassMember classMember = new ParameterClassMember(parameter); + members[i++] = classMember; + if (parameter == myParameter) { + selection = classMember; + } + } + final PsiParameterList parameterList = ((PsiMethod)myParameter.getDeclarationScope()).getParameterList(); + Arrays.sort(members, new Comparator() { + @Override + public int compare(ClassMember o1, ClassMember o2) { + return parameterList.getParameterIndex(((ParameterClassMember)o1).getParameter()) - + parameterList.getParameterIndex(((ParameterClassMember)o2).getParameter()); + } + }); + final MemberChooser chooser = new MemberChooser(members, false, true, project); + if (selection != null) { + chooser.selectElements(new ClassMember[] {selection}); + } + chooser.setTitle("Choose Constructor Parameters to Generate Fields"); + chooser.setCopyJavadocVisible(false); + chooser.show(); + if (chooser.getExitCode() != DialogWrapper.OK_EXIT_CODE) return; + final List selectedElements = chooser.getSelectedElements(); + if (selectedElements == null) return; + if (selectedElements.size() == 1) { + processParameter(project, ((ParameterClassMember)selectedElements.get(0)).getParameter(), isInteractive); + } else { + //do not ask for names in batch + for (ClassMember selectedElement : selectedElements) { + processParameter(project, ((ParameterClassMember)selectedElement).getParameter(), false); + } + } + } + else { + processParameter(project, myParameter, isInteractive); + } + unboundedParams.clear(); + } + + private static void processParameter(final Project project, + final PsiParameter myParameter, + boolean isInteractive) { IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace(); final PsiType[] types = getTypes(myParameter); final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project); @@ -344,4 +447,32 @@ public class CreateFieldFromParameterAction implements IntentionAction { public boolean startInWriteAction() { return false; } + + private static class ParameterClassMember implements ClassMember { + private PsiParameter myParameter; + + private ParameterClassMember(PsiParameter parameter) { + myParameter = parameter; + } + + @Override + public MemberChooserObject getParentNodeDelegate() { + return new PsiMethodMember((PsiMethod)myParameter.getDeclarationScope()); + } + + @Override + public void renderTreeNode(SimpleColoredComponent component, JTree tree) { + SpeedSearchUtil.appendFragmentsForSpeedSearch(tree, getText(), SimpleTextAttributes.REGULAR_ATTRIBUTES, false, component); + component.setIcon(myParameter.getIcon(0)); + } + + @Override + public String getText() { + return myParameter.getName(); + } + + public PsiParameter getParameter() { + return myParameter; + } + } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/AllAssertClassesMethods.java b/java/java-tests/testData/codeInsight/completion/normal/AllAssertClassesMethods.java new file mode 100644 index 000000000000..d244868f05f6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/AllAssertClassesMethods.java @@ -0,0 +1,5 @@ +class Foo { + { + Assert. + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/after3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/after3.java index b74263a1f326..d3be807be02c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/after3.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/after3.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Change 'new TTT[0][]' to 'new TTT[]'" "true" public class TTT { void f() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/afterNonPrimitiveArrayDimensions.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/afterNonPrimitiveArrayDimensions.java index 895a33236f5d..658edf310d24 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/afterNonPrimitiveArrayDimensions.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/afterNonPrimitiveArrayDimensions.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Change 'new X[42]' to 'new long[]'" "true" class X { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/beforeNonPrimitiveArrayDimensions.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/beforeNonPrimitiveArrayDimensions.java index d1067c2c7a2a..b698ee9f798c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/beforeNonPrimitiveArrayDimensions.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeNewOperatorType/beforeNonPrimitiveArrayDimensions.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Change 'new X[42]' to 'new long[]'" "true" class X { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java index 830383e3a2ee..582c4ce5907e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createConstructorParameterFromField/afterChainedCalls.java @@ -4,11 +4,11 @@ class A { private int j; A(int field) { - this(0, field); + this(field, 0); } - A(int j, int field) { - this.j = j; + A(int field, int j) { this.field = field; + this.j = j; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/afterProtectedMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/afterProtectedMethod.java index c00be390d07a..d5f20a3c5b26 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/afterProtectedMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/afterProtectedMethod.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Override method 'foo'" "true" class Test { protected void foo(){} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforePrivateMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforePrivateMethod.java index 18629818d098..f06ad320ba49 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforePrivateMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforePrivateMethod.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Override method 'foo'" "false" class Test { private void foo(){} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforeProtectedMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforeProtectedMethod.java index fa5bc2c68ff7..239d85010ad7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforeProtectedMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod/beforeProtectedMethod.java @@ -1,19 +1,3 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - // "Override method 'foo'" "true" class Test { protected void foo(){} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index 47542b0b1266..1246b02cb2bc 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -989,7 +989,7 @@ class Foo { myFixture.configureByText "a.java", "class Foo {{ }}" type 'Arrays.' myFixture.checkResult "class Foo {{ Arrays. }}" - assert !lookup + assert 'Arrays.asList' in myFixture.lookupElementStrings } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index eeb6589257e7..d5e1599cb3d8 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1290,4 +1290,11 @@ public class ListUtils { checkResult() } + public void testAllAssertClassesMethods() { + myFixture.addClass 'package foo; public class Assert { public static void foo() {} }' + myFixture.addClass 'package bar; public class Assert { public static void bar() {} }' + configure() + assert myFixture.lookupElementStrings == ['Assert.bar', 'Assert.foo'] + } + } diff --git a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java index d1877bd01d70..cd2cf6890ac3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/UpdateCacheTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.intellij.psi.search; import com.intellij.JavaTestUtil; @@ -139,7 +154,8 @@ public class UpdateCacheTest extends PsiTestCase{ checkUsages(objectClass, new String[]{}); FileBasedIndex.getInstance().getContainingFiles(TodoIndex.NAME, new TodoIndexEntry("todo", true), GlobalSearchScope.allScope(getProject())); - final String projectLocation = myProject.getLocation(); + final String projectLocation = myProject.getPresentableUrl(); + assert projectLocation != null : myProject; myProject.save(); final VirtualFile content = ModuleRootManager.getInstance(getModule()).getContentRoots()[0]; ProjectUtil.closeAndDispose(myProject); diff --git a/java/openapi/src/com/intellij/psi/util/PsiFormatUtil.java b/java/openapi/src/com/intellij/psi/util/PsiFormatUtil.java index 07f974b9fa29..08b8deb0f0e4 100644 --- a/java/openapi/src/com/intellij/psi/util/PsiFormatUtil.java +++ b/java/openapi/src/com/intellij/psi/util/PsiFormatUtil.java @@ -393,7 +393,7 @@ public class PsiFormatUtil extends PsiFormatUtilBase { return builder.toString(); } final PsiClass psiClass = PsiTreeUtil.getParentOfType(owner, PsiClass.class, false); - assert psiClass != null; + if (psiClass == null) return null; ClassUtil.formatClassName(psiClass, builder); if (owner instanceof PsiMethod) { builder.append(" "); @@ -406,24 +406,22 @@ public class PsiFormatUtil extends PsiFormatUtilBase { } else if (owner instanceof PsiParameter) { final PsiElement declarationScope = ((PsiParameter)owner).getDeclarationScope(); - if (declarationScope instanceof PsiMethod) { - final PsiMethod psiMethod = (PsiMethod)declarationScope; + if (!(declarationScope instanceof PsiMethod)) { + return null; + } + final PsiMethod psiMethod = (PsiMethod)declarationScope; - builder.append(" "); - formatMethod(psiMethod, PsiSubstitutor.EMPTY, - SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES, - showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, maxParamsToShow, builder); - builder.append(" "); + builder.append(" "); + formatMethod(psiMethod, PsiSubstitutor.EMPTY, + SHOW_NAME | SHOW_FQ_NAME | SHOW_TYPE | SHOW_PARAMETERS | SHOW_FQ_CLASS_NAMES, + showParamName ? SHOW_NAME | SHOW_TYPE | SHOW_FQ_CLASS_NAMES : SHOW_TYPE | SHOW_FQ_CLASS_NAMES, maxParamsToShow, builder); + builder.append(" "); - if (showParamName) { - formatVariable((PsiVariable)owner, SHOW_NAME, PsiSubstitutor.EMPTY, builder); - } - else { - builder.append(psiMethod.getParameterList().getParameterIndex((PsiParameter)owner)); - } + if (showParamName) { + formatVariable((PsiVariable)owner, SHOW_NAME, PsiSubstitutor.EMPTY, builder); } else { - return null; + builder.append(psiMethod.getParameterList().getParameterIndex((PsiParameter)owner)); } } else { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleRootsIndex.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleRootsIndex.java index 02c381241955..4ff358de25f8 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleRootsIndex.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleRootsIndex.java @@ -63,6 +63,23 @@ public class ModuleRootsIndex { return myRootToModuleMap.get(root); } + @NotNull + public RootDescriptor associateRoot(File root, Module module, boolean isTestRoot) { + final RootDescriptor d = myRootToModuleMap.get(root); + if (d != null) { + return d; + } + List moduleRoots = myModuleToRootsMap.get(module); + if (moduleRoots == null) { + moduleRoots = new ArrayList(); + myModuleToRootsMap.put(module, moduleRoots); + } + final RootDescriptor descriptor = new RootDescriptor(module, root, false); + myRootToModuleMap.put(root, descriptor); + moduleRoots.add(descriptor); + return descriptor; + } + @Nullable public RootDescriptor getModuleAndRoot(File file) { File current = file; diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java index b87db92df1ee..588d0da4620f 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java @@ -14,6 +14,7 @@ import java.util.*; * Date: 1/21/12 */ public class JavacMain { + private static final boolean IS_VM_6_VERSION = System.getProperty("java.version", "1.6").contains("1.6"); private static final Set FILTERED_OPTIONS = new HashSet(Arrays.asList( "-d", "-classpath", "-cp", "-bootclasspath" )); @@ -69,8 +70,13 @@ public class JavacMain { final JavaCompiler.CompilationTask task = compiler.getTask( out, fileManager, outConsumer, _options, null, fileManager.toJavaFileObjects(sources) ); - final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options)); - task.setProcessors(Collections.singleton(analyzer)); + + if (!IS_VM_6_VERSION) { + // Do not add the processor for JDK 1.6 because of the bugs in javac + // The processor's presence may lead to NPE and resolve bugs in compiler + final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, shouldSuppressAnnotationProcessing(options)); + task.setProcessors(Collections.singleton(analyzer)); + } return task.call(); } catch(IllegalArgumentException e) { diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java index 9d4e522c83e4..cc67d6620648 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/Mappings.java @@ -1605,7 +1605,7 @@ public class Mappings { } } - if (delta.isDifferentiated()) { + if (delta.isDifferentiated() && false) { for (DependencyContext.S c : delta.getChangedClasses()) { myClassToSubclasses.remove(c); @@ -1651,9 +1651,9 @@ public class Mappings { } } else { - mySourceFileToClasses.putAll(delta.mySourceFileToClasses); - mySourceFileToUsages.putAll(delta.mySourceFileToUsages); - mySourceFileToAnnotationUsages.putAll(delta.mySourceFileToAnnotationUsages); + mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses); + mySourceFileToUsages.replaceAll(delta.mySourceFileToUsages); + mySourceFileToAnnotationUsages.replaceAll(delta.mySourceFileToAnnotationUsages); } final Collection compiledSet = new HashSet(compiled.size()); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java index 68b1f350dd68..a7152b3684dc 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/MultiMaplet.java @@ -30,7 +30,8 @@ interface MultiMaplet { Collection get(final K key); void put(final K key, final V value); void put(final K key, final Collection value); - void putAll(MultiMaplet m); + void putAll(MultiMaplet m); + void replaceAll(MultiMaplet m); void remove(final K key); void removeFrom(final K key, final V value); void removeAll(final K key, final Collection value); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java index 3cfc2966da50..f1d288696244 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/PersistentMultiMaplet.java @@ -141,6 +141,13 @@ class PersistentMultiMaplet implements MultiMaplet { @Override public void putAll(MultiMaplet m) { + for (Map.Entry> entry : m.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void replaceAll(MultiMaplet m) { for (Map.Entry> entry : m.entrySet()) { final K key = entry.getKey(); remove(key); diff --git a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java index 2177cfdbd44b..7a5f2b85eb90 100644 --- a/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java +++ b/jps/model/src/org/jetbrains/ether/dependencyView/TransientMultiMaplet.java @@ -54,6 +54,13 @@ class TransientMultiMaplet implements MultiMaplet { return myMap.get(key); } + @Override + public void putAll(final MultiMaplet m) { + for (Map.Entry> e : m.entrySet()) { + put(e.getKey(), e.getValue()); + } + } + @Override public void put(final K key, final Collection value) { final Collection x = myMap.get(key); @@ -102,7 +109,7 @@ class TransientMultiMaplet implements MultiMaplet { } @Override - public void putAll(MultiMaplet m) { + public void replaceAll(MultiMaplet m) { for (Map.Entry> e : m.entrySet()) { remove(e.getKey()); put(e.getKey(), e.getValue()); diff --git a/platform/core-api/src/com/intellij/openapi/project/Project.java b/platform/core-api/src/com/intellij/openapi/project/Project.java index b05098b9c086..f70e4025e64b 100644 --- a/platform/core-api/src/com/intellij/openapi/project/Project.java +++ b/platform/core-api/src/com/intellij/openapi/project/Project.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,38 +22,101 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; - /** * Project interface class. */ public interface Project extends ComponentManager, AreaInstance { @NonNls String DIRECTORY_STORE_FOLDER = ".idea"; - @Nullable - VirtualFile getProjectFile(); - - @Nullable - VirtualFile getWorkspaceFile(); - - @NotNull - String getProjectFilePath(); - - @Nullable - VirtualFile getBaseDir(); - + /** + * Returns a name ot the project. For a directory-based project it's an arbitrary string specified by user at project creation + * or later in a project settings. For a file-based project it's a name of a project file without extension. + * + * @return project name + */ @NotNull @NonNls String getName(); + /** + *

Returns a project base directory - a parent directory of a .ipr file or .idea directory.
+ * Returns null for default project.

+ * + *

Please note that returned file is always de-referenced, so you have to use use {@linkplain #getBasePath()} + * if it's desired to keep symlinks in original path.

+ * + * @return project base directory, or null for default project + */ + @Nullable + VirtualFile getBaseDir(); + + /** + * Returns a system-dependent path to a project base directory (see {@linkplain #getBaseDir()}).
+ * Returns null for default project. + * + * @return a path to a project base directory, or empty string for default project + */ + @Nullable + @NonNls + String getBasePath(); + + /** + *

Returns project descriptor file: + *

    + *
  • path/to/project/project.ipr - for file-based projects
  • + *
  • path/to/project/.idea/misc.xml - for directory-based projects
  • + *
+ * Returns null for default project.

+ * + *

Please note that returned file is always de-referenced, so you have to use use {@linkplain #getProjectFilePath()} + * if it's desired to keep symlinks in original path.

+ * + * @return project descriptor file, or null for default project + */ + @Nullable + VirtualFile getProjectFile(); + + /** + * Returns a system-dependent path to project descriptor file (see {@linkplain #getProjectFile()}).
+ * Returns empty string ("") for default project. + * + * @return project descriptor file, or empty string for default project + */ + @NotNull + @NonNls + String getProjectFilePath(); + + /** + * Returns presentable project path: + * {@linkplain #getProjectFilePath()} for file-based projects, {@linkplain #getBasePath()} for directory-based ones.
+ * Note: the word "presentable" here implies file system presentation, not a UI one. + * + * @return presentable project path + */ @Nullable @NonNls String getPresentableUrl(); + /** + *

Returns a workspace file: + *

    + *
  • path/to/project/project.iws - for file-based projects
  • + *
  • path/to/project/.idea/workspace.xml - for directory-based ones
  • + *
+ * Returns null for default project. + * + * @return workspace file, or null for default project + */ + @Nullable + VirtualFile getWorkspaceFile(); + @NotNull @NonNls String getLocationHash(); - + /** + * @deprecated please use {@linkplain #getPresentableUrl()} or {@linkplain #getBasePath()} (to remove in IDEA 13). + */ @Nullable @NonNls String getLocation(); diff --git a/platform/core-impl/src/com/intellij/mock/MockProject.java b/platform/core-impl/src/com/intellij/mock/MockProject.java index 86d618118281..e06167f2ae0a 100644 --- a/platform/core-impl/src/com/intellij/mock/MockProject.java +++ b/platform/core-impl/src/com/intellij/mock/MockProject.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -117,6 +117,11 @@ public class MockProject extends MockComponentManager implements Project { return null; } + @Override + public String getBasePath() { + return null; + } + @Override public void save() { } diff --git a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java index 2358db74dd8e..8d0539de8f66 100644 --- a/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/lang-api/src/com/intellij/analysis/AnalysisScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -429,15 +429,13 @@ public class AnalysisScope { return AnalysisScopeBundle.message("scope.module.list", modules, Integer.valueOf(myModules.size())); case PROJECT: - return AnalysisScopeBundle.message("scope.project", pathToName(myProject.getPresentableUrl())); + return AnalysisScopeBundle.message("scope.project", myProject.getName()); case FILE: - final VirtualFile virtualFile = ((PsiFileSystemItem)myElement).getVirtualFile(); - LOG.assertTrue(virtualFile != null); - return AnalysisScopeBundle.message("scope.file", virtualFile.getPresentableUrl()); + return AnalysisScopeBundle.message("scope.file", getPresentableUrl((PsiFileSystemItem)myElement)); case DIRECTORY: - return AnalysisScopeBundle.message("scope.directory", ((PsiFileSystemItem)myElement).getVirtualFile().getPresentableUrl()); + return AnalysisScopeBundle.message("scope.directory", getPresentableUrl((PsiFileSystemItem)myElement)); case VIRTUAL_FILES: return AnalysisScopeBundle.message("scope.virtual.files"); @@ -446,6 +444,12 @@ public class AnalysisScope { return ""; } + private static String getPresentableUrl(final PsiFileSystemItem element) { + final VirtualFile virtualFile = element.getVirtualFile(); + assert virtualFile != null : element; + return virtualFile.getPresentableUrl(); + } + public String getShortenName(){ switch (myType) { case CUSTOM: diff --git a/platform/lang-api/src/com/intellij/execution/filters/FilterMixin.java b/platform/lang-api/src/com/intellij/execution/filters/FilterMixin.java index b84d43e4cec3..059c6f65879f 100644 --- a/platform/lang-api/src/com/intellij/execution/filters/FilterMixin.java +++ b/platform/lang-api/src/com/intellij/execution/filters/FilterMixin.java @@ -28,7 +28,6 @@ import org.jetbrains.annotations.Nullable; */ public interface FilterMixin { boolean shouldRunHeavy(); - @Nullable void applyHeavyFilter(Document copiedFragment, int startOffset, int startLineNumber, Consumer consumer); String getUpdateMessage(); diff --git a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java index cd22a9b403f6..8683342f873e 100644 --- a/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/project/ProjectUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.openapi.project; import com.intellij.ide.DataManager; @@ -40,24 +36,29 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; +/** + * @author max + */ public class ProjectUtil { @NonNls public static final String DIRECTORY_BASED_PROJECT_DIR = ".idea"; - private ProjectUtil() { - } + private ProjectUtil() { } @Nullable public static String getProjectLocationString(@NotNull final Project project) { - String projectPath = project.getLocation(); - return FileUtil.getLocationRelativeToUserHome(projectPath); + return FileUtil.getLocationRelativeToUserHome(project.getBasePath()); } - public static String calcRelativeToProjectPath(final VirtualFile file, final Project project, final boolean includeFilePath) { + @NotNull + public static String calcRelativeToProjectPath(@NotNull final VirtualFile file, + @Nullable final Project project, + final boolean includeFilePath) { return calcRelativeToProjectPath(file, project, includeFilePath, false); } - public static String calcRelativeToProjectPath(final VirtualFile file, - final Project project, + @NotNull + public static String calcRelativeToProjectPath(@NotNull final VirtualFile file, + @Nullable final Project project, final boolean includeFilePath, final boolean keepModuleAlwaysOnTheLeft) { if (file instanceof VirtualFilePathWrapper) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java index 7dc21a333c96..b13222bb406b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -389,7 +389,7 @@ public abstract class AbstractLayoutCodeProcessor { private static Set getIgnoreRoots(@NotNull Project project) { Set result = new HashSet(); - String location = project.getLocation(); + String location = project.getBasePath(); if (location != null) { File projectDir = new File(location, Project.DIRECTORY_STORE_FOLDER); if (projectDir.isDirectory()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java index 0bea98defd19..2bb9c4139e92 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionPhase.java @@ -26,6 +26,7 @@ import com.intellij.openapi.actionSystem.ex.AnActionListener; import com.intellij.openapi.application.ApplicationAdapter; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.actionSystem.TypedAction; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.fileEditor.FileEditorManagerAdapter; import com.intellij.openapi.fileEditor.FileEditorManagerEvent; @@ -284,7 +285,6 @@ public abstract class CompletionPhase implements Disposable { private final CaretListener caretListener; private final DocumentAdapter documentListener; private final PropertyChangeListener lookupListener; - private boolean changeGuard = false; private final SelectionListener selectionListener; public EmptyAutoPopup(CompletionProgressIndicator indicator) { @@ -309,7 +309,7 @@ public abstract class CompletionPhase implements Disposable { caretListener = new CaretListener() { @Override public void caretPositionChanged(CaretEvent e) { - if (!changeGuard) { + if (!TypedAction.isTypedActionInProgress()) { stopAutoPopup(); } } @@ -323,7 +323,7 @@ public abstract class CompletionPhase implements Disposable { documentListener = new DocumentAdapter() { @Override public void documentChanged(DocumentEvent e) { - if (!changeGuard) { + if (!TypedAction.isTypedActionInProgress()) { stopAutoPopup(); } } @@ -351,16 +351,6 @@ public abstract class CompletionPhase implements Disposable { LookupManager.getInstance(project).removePropertyChangeListener(lookupListener); } - public void handleTyping(char c) { - changeGuard = true; - try { - EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, String.valueOf(c), true); - } - finally { - changeGuard = false; - } - } - private static void stopAutoPopup() { CompletionServiceImpl.setCompletionPhase(NoCompletion); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index aa557f43fc0e..d0a8ae4db1c3 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -27,7 +27,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorModificationUtil; -import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiDocumentManager; @@ -42,25 +41,6 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler"); public static volatile boolean ourTestingAutopopup = false; - @Override - public Result beforeCharTyped(char c, - Project project, - Editor editor, - PsiFile file, - FileType fileType) { - CompletionPhase phase = CompletionServiceImpl.getCompletionPhase(); - /* - if (phase instanceof CompletionPhase.EmptyAutoPopup) { - long modificationStampBeforeTyping = editor.getDocument().getModificationStamp(); - ((CompletionPhase.EmptyAutoPopup)phase).handleTyping(c); - AutoHardWrapHandler.getInstance().wrapLineIfNecessary(editor, DataManager.getInstance().getDataContext(editor.getContentComponent()), modificationStampBeforeTyping); - return Result.STOP; - } - */ - - return Result.CONTINUE; - } - @Override public Result checkAutoPopup(char charTyped, final Project project, final Editor editor, final PsiFile file) { CompletionPhase oldPhase = CompletionServiceImpl.getCompletionPhase(); diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java index 9702c5bf0c67..7b1a93ef7733 100644 --- a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -295,7 +295,9 @@ public class ConversionServiceImpl extends ConversionService { @NotNull public ConversionResult convertModule(@NotNull final Project project, @NotNull final File moduleFile) { final IProjectStore stateStore = ((ProjectImpl)project).getStateStore(); - String projectPath = FileUtil.toSystemDependentName(stateStore.getLocation()); + final String url = stateStore.getPresentableUrl(); + assert url != null : project; + final String projectPath = FileUtil.toSystemDependentName(url); if (!isConversionNeeded(projectPath, moduleFile)) { return ConversionResultImpl.CONVERSION_NOT_NEEDED; @@ -322,7 +324,7 @@ public class ConversionServiceImpl extends ConversionService { } } context.saveFiles(Collections.singletonList(moduleFile)); - Messages.showInfoMessage(project, IdeBundle.message("message.your.module.was.succesfully.converted.br.old.version.was.saved.to.0", backupFile.getAbsolutePath()), + Messages.showInfoMessage(project, IdeBundle.message("message.your.module.was.successfully.converted.br.old.version.was.saved.to.0", backupFile.getAbsolutePath()), IdeBundle.message("dialog.title.convert.module")); return new ConversionResultImpl(runners); } diff --git a/platform/lang-impl/src/com/intellij/execution/TerminateRemoteProcessDialog.java b/platform/lang-impl/src/com/intellij/execution/TerminateRemoteProcessDialog.java index 98f79a623b7f..58bb0148b255 100644 --- a/platform/lang-impl/src/com/intellij/execution/TerminateRemoteProcessDialog.java +++ b/platform/lang-impl/src/com/intellij/execution/TerminateRemoteProcessDialog.java @@ -20,78 +20,60 @@ */ package com.intellij.execution; +import com.intellij.CommonBundle; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.util.ui.UIUtil; +import com.intellij.openapi.ui.Messages; -import javax.swing.*; -import javax.swing.border.Border; -import java.awt.*; - -public class TerminateRemoteProcessDialog extends DialogWrapper { - private static final int ICON_TEXT_GAP = 7; - private JCheckBox myTerminateCheckBox; - private final String mySessionName; - private final boolean myDetachIsDefault; - private final boolean myAlwaysUseDefault; - - public TerminateRemoteProcessDialog(final Project project, - final String configurationName, - final boolean detachIsDefault, - boolean alwaysUseDefault) { - super(project, true); - mySessionName = configurationName; - myDetachIsDefault = detachIsDefault; - myAlwaysUseDefault = alwaysUseDefault; - setTitle(ExecutionBundle.message("process.is.running.dialog.title", mySessionName)); - setOKButtonText(alwaysUseDefault && !detachIsDefault ? ExecutionBundle.message("button.terminate") - : ExecutionBundle.message("button.disconnect")); - setButtonsAlignment(SwingUtilities.CENTER); - this.init(); +public class TerminateRemoteProcessDialog { + public static int show(final Project project, + final String sessionName, + final TerminateOption option) { + final String message = option.myAlwaysUseDefault && !option.myDetachIsDefault ? + ExecutionBundle.message("terminate.process.confirmation.text", sessionName) : + ExecutionBundle.message("disconnect.process.confirmation.text", sessionName); + final String okButtonText = option.myAlwaysUseDefault && !option.myDetachIsDefault ? + ExecutionBundle.message("button.terminate") : + ExecutionBundle.message("button.disconnect"); + final String[] options = new String[] {okButtonText, CommonBundle.getCancelButtonText()}; + return Messages.showDialog(project, message, ExecutionBundle.message("process.is.running.dialog.title", sessionName), + options, 0, Messages.getWarningIcon(), + option); } - protected Action[] createActions(){ - return new Action[]{getOKAction(), getCancelAction()}; - } + public static class TerminateOption implements DialogWrapper.DoNotAskOption { + private final boolean myDetachIsDefault; + private final boolean myAlwaysUseDefault; + private boolean myDontTerminate = false; - protected JComponent createNorthPanel() { - final String message = myAlwaysUseDefault && !myDetachIsDefault ? - ExecutionBundle.message("terminate.process.confirmation.text", mySessionName) : - ExecutionBundle.message("disconnect.process.confirmation.text", mySessionName); - final JLabel label = new JLabel(message); - final JPanel panel = new JPanel(new BorderLayout()); - panel.add(label, BorderLayout.CENTER); - final Icon icon = UIUtil.getOptionPanelWarningIcon(); - if (icon != null) { - label.setIcon(icon); - label.setIconTextGap(ICON_TEXT_GAP); + public TerminateOption(boolean detachIsDefault, boolean alwaysUseDefault) { + myDetachIsDefault = detachIsDefault; + myAlwaysUseDefault = alwaysUseDefault; } - return panel; - } - protected JComponent createCenterPanel() { - final JPanel panel = new JPanel(new BorderLayout()); - if (!myAlwaysUseDefault) { - myTerminateCheckBox = new JCheckBox(ExecutionBundle.message("terminate.after.disconnect.checkbox")); - myTerminateCheckBox.setSelected(!myDetachIsDefault); - final Icon icon = UIUtil.getOptionPanelWarningIcon(); - if (icon != null) { - final Border border = myTerminateCheckBox.getBorder(); - if (border != null) { - final Insets insets = border.getBorderInsets(myTerminateCheckBox); - final Border emptyBorder = BorderFactory.createEmptyBorder(0, icon.getIconWidth()+ICON_TEXT_GAP-insets.left, 0, 0); - myTerminateCheckBox.setBorder(BorderFactory.createCompoundBorder(emptyBorder, border)); - } - else { - myTerminateCheckBox.setBorder(BorderFactory.createEmptyBorder(0, icon.getIconWidth()+ICON_TEXT_GAP, 0, 0)); - } - } - panel.add(myTerminateCheckBox, BorderLayout.WEST); + @Override + public boolean isToBeShown() { + return myAlwaysUseDefault ? !myDetachIsDefault : myDontTerminate; } - return panel; - } - public boolean forceTermination() { - return myAlwaysUseDefault ? !myDetachIsDefault : myTerminateCheckBox.isSelected(); + @Override + public void setToBeShown(boolean value, int exitCode) { + myDontTerminate = value; + } + + @Override + public boolean canBeHidden() { + return !myAlwaysUseDefault; + } + + @Override + public boolean shouldSaveOptionsOnCancel() { + return false; + } + + @Override + public String getDoNotShowMessage() { + return ExecutionBundle.message("terminate.after.disconnect.checkbox"); + } } } diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java index 3806e0ff9656..29b8a89c4645 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,7 +75,7 @@ public class ConsoleHistoryController { @NotNull final LanguageConsoleImpl console, @NotNull final ConsoleHistoryModel model) { myType = type; - myId = StringUtil.isEmpty(persistenceId)? console.getProject().getLocation() : persistenceId; + myId = StringUtil.isEmpty(persistenceId)? console.getProject().getPresentableUrl() : persistenceId; myConsole = console; myModel = model; } diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java index 18f0c22cd82c..4dc491c76175 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -38,6 +38,8 @@ import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.impl.EditorFactoryImpl; +import com.intellij.openapi.editor.impl.EditorHeaderComponent; +import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; @@ -551,7 +553,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { @Override public void fileClosed(FileEditorManager source, VirtualFile file) { if (file != myFile.getVirtualFile()) return; - if (myUiUpdateRunnable != null) { + if (myUiUpdateRunnable != null && !Boolean.TRUE.equals(file.getUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN))) { ApplicationManager.getApplication().runReadAction(myUiUpdateRunnable); } } @@ -600,10 +602,13 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider { private void configureFullEditor(final Editor editor) { if (editor == null || myFullEditorActions == null || editor == myConsoleEditor) return; - final JPanel header = new JPanel(new BorderLayout()); + final JPanel header = new EditorHeaderComponent(); final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, myFullEditorActions, true); actionToolbar.setTargetComponent(editor.getContentComponent()); - header.add(actionToolbar.getComponent(), BorderLayout.EAST); + JComponent component = actionToolbar.getComponent(); + component.setOpaque(false); + header.add(component, BorderLayout.EAST); + editor.putUserData(EditorImpl.PERMANENT_HEADER, header); editor.setHeaderComponent(header); editor.getSettings().setLineMarkerAreaShown(false); } diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index e9e587a2205f..acf3baf1e804 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -480,7 +480,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo flushDeferredUserInput(); } } - if (myFlushAlarm.getActiveRequestCount() == 0 && myEditor != null && !myFlushAlarm.isDisposed()) { + if (myEditor != null && !myFlushAlarm.isDisposed()) { final boolean shouldFlushNow = myBuffer.isUseCyclicBuffer() && myBuffer.getLength() >= myBuffer.getCyclicBufferSize(); myFlushAlarm.addRequest(myFlushDeferredRunnable, shouldFlushNow ? 0 : FLUSH_DELAY, getStateForUpdate()); } @@ -541,6 +541,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myEditor.getMarkupModel().removeAllHighlighters(); document = myEditor.getDocument(); myFoldingAlarm.cancelAllRequests(); + cancelHeavyAlarm(); } CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { public void run() { @@ -862,21 +863,25 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo @Override public void run() { if (! myPredefinedMessageFilter.shouldRunHeavy()) return; - myPredefinedMessageFilter.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer() { - @Override - public void consume(final FilterMixin.AdditionalHighlight additionalHighlight) { - if (myFlushAlarm.isDisposed()) return; - myFlushAlarm.addRequest(new Runnable() { - @Override - public void run() { - if (myHeavyUpdateTicket != currentValue) return; - myHyperlinks.adjustHighlighters(Collections.singletonList(additionalHighlight)); - } - }, 0, getStateForUpdate()); + try { + myPredefinedMessageFilter.applyHeavyFilter(documentCopy, startOffset, startLine, new Consumer() { + @Override + public void consume(final FilterMixin.AdditionalHighlight additionalHighlight) { + if (myFlushAlarm.isDisposed()) return; + myFlushAlarm.addRequest(new Runnable() { + @Override + public void run() { + if (myHeavyUpdateTicket != currentValue) return; + myHyperlinks.adjustHighlighters(Collections.singletonList(additionalHighlight)); + } + }, 0, getStateForUpdate()); + } + }); + } + finally { + if (myHeavyAlarm.getActiveRequestCount() == 0) { + SwingUtilities.invokeLater(myFinishProgress); } - }); - if (myHeavyAlarm.getActiveRequestCount() == 0) { - SwingUtilities.invokeLater(myFinishProgress); } } }, 0); diff --git a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java index a9db26f1d957..3eabbebd9db1 100644 --- a/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/ui/RunContentManagerImpl.java @@ -48,7 +48,6 @@ import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.ui.content.*; -import com.intellij.ui.content.impl.ContentImpl; import com.intellij.ui.docking.DockManager; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.containers.ContainerUtil; @@ -616,12 +615,10 @@ public class RunContentManagerImpl implements RunContentManager, Disposable { else { //todo[nik] this is a temporary solution for the following problem: some configurations should not allow user to choose between 'terminating' and 'detaching' final boolean useDefault = Boolean.TRUE.equals(processHandler.getUserData(ALWAYS_USE_DEFAULT_STOPPING_BEHAVIOUR_KEY)); - final TerminateRemoteProcessDialog terminateDialog = new TerminateRemoteProcessDialog(myProject, descriptor.getDisplayName(), - processHandler.detachIsDefault(), - useDefault); - terminateDialog.show(); - if (terminateDialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) return false; - destroyProcess = terminateDialog.forceTermination(); + final TerminateRemoteProcessDialog.TerminateOption option = new TerminateRemoteProcessDialog.TerminateOption(processHandler.detachIsDefault(), useDefault); + final int rc = TerminateRemoteProcessDialog.show(myProject, descriptor.getDisplayName(), option); + if (rc != DialogWrapper.OK_EXIT_CODE) return false; + destroyProcess = !option.isToBeShown(); } if (destroyProcess) { processHandler.destroyProcess(); diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java index 80a9869883e1..4f94c701fcd8 100644 --- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java +++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java @@ -31,6 +31,7 @@ import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.event.SelectionEvent; import com.intellij.openapi.editor.event.SelectionListener; +import com.intellij.openapi.editor.impl.EditorHeaderComponent; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.IconLoader; @@ -38,7 +39,6 @@ import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.ui.Gray; import com.intellij.ui.LightColors; import com.intellij.ui.components.JBList; import com.intellij.ui.components.JBScrollPane; @@ -61,7 +61,7 @@ import java.util.regex.Pattern; /** * @author max, andrey.zaytsev */ -public class EditorSearchComponent extends JPanel implements DataProvider, SelectionListener, SearchResults.SearchResultsListener, +public class EditorSearchComponent extends EditorHeaderComponent implements DataProvider, SelectionListener, SearchResults.SearchResultsListener, LivePreviewControllerBase.ReplaceListener { private static final int MATCHES_LIMIT = 10000; @@ -104,10 +104,6 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec private JButton myReplaceAllButton; private JButton myExcludeButton; - private final Color GRADIENT_C1; - private final Color GRADIENT_C2; - - private static final Color BORDER_COLOR = Gray._135; public static final Color COMPLETION_BACKGROUND_COLOR = new Color(235, 244, 254); private static final Color FOCUS_CATCHER_COLOR = new Color(0x9999ff); @@ -222,12 +218,8 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec public void editorChanged(SearchResults sr, Editor oldEditor) { } public EditorSearchComponent(final Editor editor, final Project project, FindModel findModel) { - super(new BorderLayout(0, 0)); myFindModel = findModel; - GRADIENT_C1 = getBackground(); - GRADIENT_C2 = new Color(Math.max(0, GRADIENT_C1.getRed() - 0x18), Math.max(0, GRADIENT_C1.getGreen() - 0x18), Math.max(0, GRADIENT_C1.getBlue() - 0x18)); - myProject = project; myEditor = editor; @@ -876,21 +868,6 @@ public class EditorSearchComponent extends JPanel implements DataProvider, Selec return insets; } - @Override - protected void paintComponent(Graphics g) { - super.paintComponent(g); - final Graphics2D g2d = (Graphics2D) g; - - if (!UIUtil.isUnderGTKLookAndFeel()) { - g2d.setPaint(new GradientPaint(0, 0, GRADIENT_C1, 0, getHeight(), GRADIENT_C2)); - g2d.fillRect(1, 1, getWidth(), getHeight() - 1); - g2d.setPaint(null); - } - - g.setColor(BORDER_COLOR); - g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); - } - private class MyLivePreviewController extends LivePreviewControllerBase { public MyLivePreviewController() { super(EditorSearchComponent.this.mySearchResults, EditorSearchComponent.this.myLivePreview); diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java index 0fa5a5592674..df92c28ff1cb 100644 --- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java +++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java @@ -31,6 +31,7 @@ import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorLocation; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.keymap.KeymapUtil; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.ui.popup.JBPopup; @@ -468,23 +469,23 @@ public class ShowUsagesAction extends AnAction implements PopupAction { KeyboardShortcut shortcut = getSettingsShortcut(); if (shortcut != null) { - builder.registerKeyboardAction(shortcut.getFirstKeyStroke(), new ActionListener() { + new DumbAwareAction() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(AnActionEvent e) { popup[0].cancel(); showDialogAndFindUsages(handler, popupPosition, editor, maxUsages); } - }); + }.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table); } shortcut = getShowUsagesShortcut(); if (shortcut != null) { - builder.registerKeyboardAction(shortcut.getFirstKeyStroke(), new ActionListener() { + new DumbAwareAction() { @Override - public void actionPerformed(ActionEvent e) { + public void actionPerformed(AnActionEvent e) { popup[0].cancel(); searchEverywhere(options, handler, editor, popupPosition, maxUsages); } - }); + }.registerCustomShortcutSet(new CustomShortcutSet(shortcut.getFirstKeyStroke()), table); } InplaceButton button = createSettingsButton(handler, popupPosition, editor, maxUsages, new Runnable() { diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java index 1e5bdc1ddfd6..af462f597adc 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -509,15 +509,7 @@ public class FindInProjectUtil { fast |= findModel.isWholeWordsOnly() && findModel.getStringToFind().indexOf('$') < 0; - List words = StringUtil.getWordsIn(findModel.getStringToFind()); - - // hope long words are rare - Collections.sort(words, new Comparator() { - @Override - public int compare(final String o1, final String o2) { - return o2.length() - o1.length(); - } - }); + List words = StringUtil.getWordsInStringLongestFirst(findModel.getStringToFind()); for (int i = 0; i < words.size(); i++) { String word = words.get(i); diff --git a/platform/lang-impl/src/com/intellij/ide/actions/WeighingActionGroup.java b/platform/lang-impl/src/com/intellij/ide/actions/WeighingActionGroup.java index 4a50e1393e74..ca71de4447ef 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/WeighingActionGroup.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/WeighingActionGroup.java @@ -18,6 +18,7 @@ package com.intellij.ide.actions; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.PresentationFactory; import com.intellij.openapi.actionSystem.impl.Utils; +import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,6 +30,7 @@ import java.util.ArrayList; * @author peter */ public abstract class WeighingActionGroup extends ActionGroup { + private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.WeighingActionGroup"); private final PresentationFactory myPresentationFactory = new PresentationFactory(); @Override @@ -40,9 +42,13 @@ public abstract class WeighingActionGroup extends ActionGroup { private static void getAllChildren(@Nullable AnActionEvent e, ActionGroup group, List result) { for (final AnAction action : group.getChildren(e)) { - if (action instanceof ActionGroup && !((ActionGroup) action).isPopup()) { - getAllChildren(e, (ActionGroup) action, result); - } else { + if (action == null) { + LOG.error("Null child for " + group); + } + if (action instanceof ActionGroup && !((ActionGroup)action).isPopup()) { + getAllChildren(e, (ActionGroup)action, result); + } + else { result.add(action); } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 1f18a4de9dcd..73589cae29d7 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.ServiceManager; @@ -61,7 +60,6 @@ import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.ui.SplitterProportionsData; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.*; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; @@ -75,6 +73,7 @@ import com.intellij.openapi.wm.impl.content.ToolWindowContentUi; import com.intellij.psi.*; import com.intellij.psi.impl.file.PsiDirectoryFactory; import com.intellij.psi.util.PsiUtilBase; +import com.intellij.psi.util.PsiUtilCore; import com.intellij.ui.AutoScrollFromSourceHandler; import com.intellij.ui.AutoScrollToSourceHandler; import com.intellij.ui.GuiUtils; @@ -157,7 +156,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo @Deprecated static final String PROJECT_VIEW_DATA_CONSTANT = DATA_KEY.getName(); private DefaultActionGroup myActionGroup; - private final Runnable myTreeChangeListener; private String mySavedPaneId = ProjectViewPane.ID; private String mySavedPaneSubId; //private static final Icon COMPACT_EMPTY_MIDDLE_PACKAGES_ICON = IconLoader.getIcon("/objectBrowser/compactEmptyPackages.png"); @@ -200,11 +198,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo Disposer.register(myProject, this); myFileEditorManager = fileEditorManager; - myTreeChangeListener = new Runnable() { - public void run() { - updateToolWindowTitle(); - } - }; myConnection = project.getMessageBus().connect(); myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { @@ -474,15 +467,13 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo createToolbarActions(); updateTitleActions(); - newPane.setTreeChangeListener(myTreeChangeListener); myAutoScrollToSourceHandler.install(newPane.myTree); IdeFocusManager.getInstance(myProject).requestFocus(newPane.getComponentToFocus(), false); - updateToolWindowTitle(); newPane.restoreExpandedPaths(); if (selectedPsiElement != null) { - final VirtualFile virtualFile = PsiUtilBase.getVirtualFile(selectedPsiElement); + final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(selectedPsiElement); if (virtualFile != null && ((ProjectViewSelectInTarget)newPane.createSelectInTarget()).isSubIdSelectable(newSubId, new SelectInContext() { @NotNull public Project getProject() { @@ -754,49 +745,6 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo return myCurrentViewId; } - private void updateToolWindowTitle() { - if (true) return; - ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); - ToolWindow toolWindow = toolWindowManager == null ? null : toolWindowManager.getToolWindow(ToolWindowId.PROJECT_VIEW); - if (toolWindow == null) return; - String title = null; - final AbstractProjectViewPane pane = getCurrentProjectViewPane(); - if (pane != null) { - final DefaultMutableTreeNode selectedNode = pane.getSelectedNode(); - if (selectedNode != null) { - final Object o = selectedNode.getUserObject(); - if (o instanceof ProjectViewNode) { - title = ((ProjectViewNode)o).getTitle(); - } - } - } - if (title == null) { - if (true) return; - - final PsiElement element = (PsiElement)myDataProvider.getData(LangDataKeys.PSI_ELEMENT.getName()); - if (element != null) { - PsiFile file = element.getContainingFile(); - if (file != null) { - title = FileUtil.getLocationRelativeToUserHome(file.getVirtualFile().getPresentableUrl()); - } - else if (element instanceof PsiDirectory) { - title = PsiDirectoryFactory.getInstance(myProject).getQualifiedName((PsiDirectory) element, true); - } - else { - title = element.toString(); - } - } - else { - title = ""; - if (myProject != null) { - title = FileUtil.getLocationRelativeToUserHome(myProject.getPresentableUrl()); - } - } - } - - toolWindow.setTitle(title); - } - public PsiElement getParentOfCurrentSelection() { final AbstractProjectViewPane viewPane = getCurrentProjectViewPane(); if (viewPane == null) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index addd3ad3365d..04449a9d5d78 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -781,7 +781,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { if (scope instanceof LocalSearchScope) { registerRequest(locals, primitive, processor); } else { - final List words = StringUtil.getWordsIn(primitive.word); + final List words = StringUtil.getWordsInStringLongestFirst(primitive.word); final Set key = new HashSet(words.size() * 2); for (String word : words) { key.add(new IdIndexEntry(word, primitive.caseSensitive)); @@ -857,7 +857,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } private static ArrayList getWordEntries(String name, boolean caseSensitively) { - List words = StringUtil.getWordsIn(name); + List words = StringUtil.getWordsInStringLongestFirst(name); final ArrayList keys = new ArrayList(); for (String word : words) { keys.add(new IdIndexEntry(word, caseSensitively)); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 44234f494e30..05d68cf0016e 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -199,10 +199,13 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe index.getReadLock().lock(); final ValueContainer container = index.getData(key); + final FileBasedIndex.ProjectIndexableFilesFilter projectFilesFilter = FileBasedIndex.getInstance().projectIndexableFiles(project); + container.forEach(new ValueContainer.ContainerAction() { @Override public void perform(final int id, final TIntArrayList value) { ProgressManager.checkCanceled(); + if (projectFilesFilter != null && !projectFilesFilter.contains(id)) return; final VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); if (file == null || scope != null && !scope.contains(file)) { return; diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java index f8ce88ae536d..5594a35166ae 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndex.java @@ -77,6 +77,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.*; +import java.lang.ref.SoftReference; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; @@ -122,6 +123,7 @@ public class FileBasedIndex implements ApplicationComponent { private final boolean myIsUnitTestMode; private ScheduledFuture myFlushingFuture; private volatile int myLocalModCount; + private volatile int myFilesModCount; public void requestReindex(final VirtualFile file) { myChangedFilesCollector.invalidateIndices(file, true); @@ -860,7 +862,7 @@ public class FileBasedIndex implements ApplicationComponent { private R processExceptions(final ID indexId, - @Nullable final VirtualFile restrictToFile, + @Nullable final VirtualFile restrictToFile, final GlobalSearchScope filter, ThrowableConvertor, R, StorageException> computable) { try { @@ -921,10 +923,12 @@ public class FileBasedIndex implements ApplicationComponent { } else { final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); + ProjectIndexableFilesFilter projectFilesSet = projectIndexableFiles(filter.getProject()); VALUES_LOOP: for (final Iterator valueIt = container.getValueIterator(); valueIt.hasNext();) { final V value = valueIt.next(); for (final ValueContainer.IntIterator inputIdsIterator = container.getInputIdsIterator(value); inputIdsIterator.hasNext();) { final int id = inputIdsIterator.next(); + if (projectFilesSet != null && !projectFilesSet.contains(id)) continue; VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); if (file != null && filter.accept(file)) { shouldContinue = processor.process(file, value); @@ -944,24 +948,70 @@ public class FileBasedIndex implements ApplicationComponent { final Boolean result = processExceptions(indexId, restrictToFile, filter, keyProcessor); return result == null || result.booleanValue(); } - + public boolean processFilesContainingAllKeys(final ID indexId, final Collection dataKeys, final GlobalSearchScope filter, @Nullable Condition valueChecker, final Processor processor) { - final TIntHashSet set = collectFileIdsContainingAllKeys(indexId, dataKeys, filter, valueChecker); + ProjectIndexableFilesFilter filesSet = projectIndexableFiles(filter.getProject()); + final TIntHashSet set = collectFileIdsContainingAllKeys(indexId, dataKeys, filter, valueChecker, filesSet); if (set == null) { return false; } return processVirtualFiles(set, filter, processor); } + private static final Key> ourProjectFilesSetKey = Key.create("projectFiles"); + + public static final class ProjectIndexableFilesFilter extends BloomFilterBase { + private static final int MAGIC = 0x278DDE6D; + private final int myModificationCount; + + private ProjectIndexableFilesFilter(TIntHashSet set, int modificationCount) { + super(set.size(), 0.005d); + myModificationCount = modificationCount; + set.forEach(new TIntProcedure() { + @Override + public boolean execute(int value) { + addIt(value, value * MAGIC); + return true; + } + }); + } + + public boolean contains(int id) { + return maybeContains(id, id * MAGIC); + } + } + + public @Nullable ProjectIndexableFilesFilter projectIndexableFiles(Project project) { + if (project == null) return null; + + SoftReference reference = project.getUserData(ourProjectFilesSetKey); + ProjectIndexableFilesFilter data = reference != null ? reference.get() : null; + if (data != null && data.myModificationCount == myFilesModCount) return data; + + final TIntHashSet filesSet = new TIntHashSet(); + iterateIndexableFiles(new ContentIterator() { + @Override + public boolean processFile(VirtualFile fileOrDir) { + filesSet.add(((VirtualFileWithId)fileOrDir).getId()); + return true; + } + }, project, ProgressManager.getInstance().getProgressIndicator()); + ProjectIndexableFilesFilter files = new ProjectIndexableFilesFilter(filesSet, myFilesModCount); + project.putUserData(ourProjectFilesSetKey, new SoftReference(files)); + return files; + } + @Nullable private TIntHashSet collectFileIdsContainingAllKeys(final ID indexId, final Collection dataKeys, final GlobalSearchScope filter, - @Nullable final Condition valueChecker) { + @Nullable final Condition valueChecker, + @Nullable final ProjectIndexableFilesFilter projectFilesFilter + ) { final ThrowableConvertor, TIntHashSet, StorageException> convertor = new ThrowableConvertor, TIntHashSet, StorageException>() { @Nullable @@ -981,7 +1031,8 @@ public class FileBasedIndex implements ApplicationComponent { } for (final ValueContainer.IntIterator inputIdsIterator = container.getInputIdsIterator(value); inputIdsIterator.hasNext(); ) { final int id = inputIdsIterator.next(); - if (mainIntersection == null || mainIntersection.contains(id)) { + if ((mainIntersection == null || mainIntersection.contains(id)) && + (projectFilesFilter == null || projectFilesFilter.contains(id))) { copy.add(id); } } @@ -1063,8 +1114,10 @@ public class FileBasedIndex implements ApplicationComponent { final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); TIntIterator ids = join(locals).iterator(); + ProjectIndexableFilesFilter projectIndexableFilesFilter = projectIndexableFiles(project); while (ids.hasNext()) { int id = ids.next(); + if (projectIndexableFilesFilter != null && !projectIndexableFilesFilter.contains(id)) continue; //VirtualFile file = IndexInfrastructure.findFileById(fs, id); VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); if (file != null && filter.accept(file)) { @@ -1611,7 +1664,7 @@ public class FileBasedIndex implements ApplicationComponent { @Override public void fileCreated(final VirtualFileEvent event) { - markDirty(event); + markDirty(event, false); } @Override @@ -1621,7 +1674,7 @@ public class FileBasedIndex implements ApplicationComponent { @Override public void fileCopied(final VirtualFileCopyEvent event) { - markDirty(event); + markDirty(event, false); } @Override @@ -1636,7 +1689,7 @@ public class FileBasedIndex implements ApplicationComponent { @Override public void contentsChanged(final VirtualFileEvent event) { - markDirty(event); + markDirty(event, true); } @Override @@ -1657,17 +1710,18 @@ public class FileBasedIndex implements ApplicationComponent { if (event.getPropertyName().equals(VirtualFile.PROP_NAME)) { // indexes may depend on file name if (!event.getFile().isDirectory()) { - markDirty(event); + markDirty(event, false); } } } - private void markDirty(final VirtualFileEvent event) { + private void markDirty(final VirtualFileEvent event, final boolean contentChange) { final VirtualFile eventFile = event.getFile(); cleanProcessedFlag(eventFile); iterateIndexableFiles(eventFile, new Processor() { @Override public boolean process(final VirtualFile file) { + if (!contentChange) ++myFilesModCount; FileContent fileContent = null; // handle 'content-less' indices separately for (ID indexId : myNotRequiringContentIndices) { @@ -2041,6 +2095,7 @@ public class FileBasedIndex implements ApplicationComponent { } public CollectingContentIterator createContentIterator() { + ++myFilesModCount; return new UnindexedFilesFinder(); } diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java index 3c7bc750ad1a..075d32b1ccce 100644 --- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java +++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/TypedAction.java @@ -100,26 +100,42 @@ public class TypedAction { public final void actionPerformed(final Editor editor, final char charTyped, final DataContext dataContext) { if (editor == null) return; - Runnable command = new Runnable() { - public void run() { - ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(editor.getDocument(),editor.getProject()) { - public void run() { - Document doc = editor.getDocument(); - doc.startGuardedBlockChecking(); - try { - getHandler().execute(editor, charTyped, dataContext); - } - catch (ReadOnlyFragmentModificationException e) { - EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e); - } - finally { - doc.stopGuardedBlockChecking(); - } - } - }); - } - }; + Runnable command = new TypingCommand(editor, charTyped, dataContext); CommandProcessor.getInstance().executeCommand(PlatformDataKeys.PROJECT.getData(dataContext), command, "", editor.getDocument(), UndoConfirmationPolicy.DEFAULT, editor.getDocument()); } + + public static boolean isTypedActionInProgress() { + return CommandProcessor.getInstance().getCurrentCommand() instanceof TypingCommand; + } + + private class TypingCommand implements Runnable { + private final Editor myEditor; + private final char myCharTyped; + private final DataContext myDataContext; + + public TypingCommand(Editor editor, char charTyped, DataContext dataContext) { + myEditor = editor; + myCharTyped = charTyped; + myDataContext = dataContext; + } + + public void run() { + ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(myEditor.getDocument(), myEditor.getProject()) { + public void run() { + Document doc = myEditor.getDocument(); + doc.startGuardedBlockChecking(); + try { + getHandler().execute(myEditor, myCharTyped, myDataContext); + } + catch (ReadOnlyFragmentModificationException e) { + EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e); + } + finally { + doc.stopGuardedBlockChecking(); + } + } + }); + } + } } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java index dea9d7c6d452..8ddf512c3376 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java @@ -1186,6 +1186,10 @@ public abstract class DialogWrapper { myPeer.setModal(modal); } + public boolean isModal() { + return myPeer.isModal(); + } + protected void setOKActionEnabled(boolean isEnabled) { myOKAction.setEnabled(isEnabled); } diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeer.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeer.java index d3dbb39a238a..5fbb3aa20c58 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeer.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapperPeer.java @@ -94,6 +94,8 @@ public abstract class DialogWrapperPeer { public abstract void setModal(boolean modal); + public abstract boolean isModal(); + /** * @see java.awt.Component#isVisible */ diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java index b9118e713be8..32414c68eaa7 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.java @@ -116,7 +116,7 @@ public class Messages { if (canShowMacSheetPanel()) { return MacMessages.getInstance() - .showMessageDialog(title, message, options, false, WindowManager.getInstance().suggestParentWindow(project), defaultOptionIndex, defaultOptionIndex, null); + .showMessageDialog(title, message, options, false, WindowManager.getInstance().suggestParentWindow(project), defaultOptionIndex, defaultOptionIndex, doNotAskOption); } return showIdeaMessageDialog(project, message, title, options, defaultOptionIndex, icon, doNotAskOption); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java index 9dcd06843d5a..838a6a1e5095 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/ActionPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,14 +27,11 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public class ActionPanel extends NonOpaquePanel { - private final ActionGroup myGroup; private final List myButtons = new ArrayList(); - private final TabInfo myTabInfo; private final JBTabsImpl myTabs; private boolean myAutoHide; @@ -44,9 +41,8 @@ public class ActionPanel extends NonOpaquePanel { public ActionPanel(JBTabsImpl tabs, TabInfo tabInfo, Pass pass) { myTabs = tabs; - myTabInfo = tabInfo; - myGroup = tabInfo.getTabLabelActions() != null ? tabInfo.getTabLabelActions() : new DefaultActionGroup(); - AnAction[] children = myGroup.getChildren(null); + ActionGroup group = tabInfo.getTabLabelActions() != null ? tabInfo.getTabLabelActions() : new DefaultActionGroup(); + AnAction[] children = group.getChildren(null); final NonOpaquePanel wrapper = new NonOpaquePanel(new BorderLayout()); wrapper.add(Box.createHorizontalStrut(myGap), BorderLayout.WEST); @@ -96,8 +92,7 @@ public class ActionPanel extends NonOpaquePanel { public void setAutoHide(final boolean autoHide) { myAutoHide = autoHide; - for (Iterator iterator = myButtons.iterator(); iterator.hasNext();) { - ActionButton each = iterator.next(); + for (ActionButton each : myButtons) { each.setAutoHide(myAutoHide); } } @@ -108,8 +103,7 @@ public class ActionPanel extends NonOpaquePanel { } public void toggleShowActions(final boolean show) { - for (Iterator iterator = myButtons.iterator(); iterator.hasNext();) { - ActionButton each = iterator.next(); + for (ActionButton each : myButtons) { each.toggleShowActions(show); } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java index f651f7fabcb0..d7db0511d9e8 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/JBTabsImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class JBTabsImpl extends JComponent implements JBTabs, PropertyChangeListener, TimerListener, DataProvider, PopupMenuListener, Disposable, JBTabsPresentation, Queryable, QuickActionProvider { - static DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); + public static DataKey NAVIGATION_ACTIONS_KEY = DataKey.create("JBTabs"); public static final String EDITOR_TABS = "main.editor.tabs"; public static final Color MAC_AQUA_BG_COLOR = Gray._200; @@ -114,7 +114,7 @@ public class JBTabsImpl extends JComponent public boolean myForcedRelayout; private UiDecorator myUiDecorator; - static final UiDecorator ourDefaultDecorator = new DefautDecorator(); + static final UiDecorator ourDefaultDecorator = new DefaultDecorator(); private boolean myPaintFocus; @@ -518,13 +518,22 @@ public class JBTabsImpl extends JComponent } } - private void showMorePopup(final MouseEvent e) { + public boolean canShowMorePopup() { + final SingleRowPassInfo lastLayout = mySingleRowLayout.myLastSingRowLayout; + return lastLayout != null && lastLayout.moreRect != null; + } + + public void showMorePopup(@Nullable final MouseEvent e) { + final SingleRowPassInfo lastLayout = mySingleRowLayout.myLastSingRowLayout; + if (lastLayout == null) { + return; + } mySingleRowLayout.myMorePopup = new JPopupMenu(); for (final TabInfo each : myVisibleInfos) { final JCheckBoxMenuItem item = new JCheckBoxMenuItem(each.getText()); Color color = UIManager.getColor("MenuItem.background"); if (color != null) { - if (mySingleRowLayout.myLastSingRowLayout.toDrop.contains(each)) { + if (lastLayout.toDrop.contains(each)) { color = new Color((int) (color.getRed() * 0.85f), (int) (color.getGreen() * 0.85f), (int) (color.getBlue() * 0.85f)); } @@ -555,7 +564,15 @@ public class JBTabsImpl extends JComponent } }); - mySingleRowLayout.myMorePopup.show(this, e.getX(), e.getY()); + if (e != null) { + mySingleRowLayout.myMorePopup.show(this, e.getX(), e.getY()); + } + else { + final Rectangle rect = lastLayout.moreRect; + if (rect != null) { + mySingleRowLayout.myMorePopup.show(this, rect.x, rect.y+rect.height); + } + } } @@ -3010,7 +3027,7 @@ public class JBTabsImpl extends JComponent } - private static class DefautDecorator implements UiDecorator { + private static class DefaultDecorator implements UiDecorator { @NotNull public UiDecoration getDecoration() { return new UiDecoration(null, new Insets(0, 4, 0, 5)); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java index 8f9e657350fb..7dd868299501 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/LayoutPassInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.intellij.ui.tabs.impl; import com.intellij.ui.tabs.TabInfo; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.List; @@ -28,15 +29,19 @@ public abstract class LayoutPassInfo { myVisibleInfos = visibleInfos; } + @Nullable public abstract TabInfo getPreviousFor(TabInfo info); + @Nullable public abstract TabInfo getNextFor(TabInfo info); - public TabInfo getPrevious(List list, int i) { + @Nullable + public static TabInfo getPrevious(List list, int i) { return i > 0 ? list.get(i - 1) : null; } - public TabInfo getNext(List list, int i) { + @Nullable + public static TabInfo getNext(List list, int i) { return i < list.size() - 1 ? list.get(i + 1) : null; } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java index a35f05d2f2c3..0889323cc8d7 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/TabLabel.java @@ -81,7 +81,7 @@ public class TabLabel extends JPanel { myLabelPlaceholder.setOpaque(false); add(myLabelPlaceholder, BorderLayout.CENTER); - setAligmentToCenter(true); + setAlignmentToCenter(true); myIcon = new LayeredIcon(2); @@ -124,7 +124,7 @@ public class TabLabel extends JPanel { return insets; } - public void setAligmentToCenter(boolean toCenter) { + public void setAlignmentToCenter(boolean toCenter) { if (myCentered == toCenter && myLabel.getParent() != null) return; myLabelPlaceholder.removeAll(); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java index 800708bed20c..e19ceefb8486 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayout.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import com.intellij.ui.tabs.JBTabsPosition; import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.TabsUtil; import com.intellij.ui.tabs.impl.*; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -105,7 +106,7 @@ public class SingleRowLayout extends TabLayout { } private boolean checkLayoutLabels(SingleRowPassInfo data) { - boolean layoutLabels = true; + boolean layoutLabels = true; if (!myTabs.myForcedRelayout && myLastSingRowLayout != null && @@ -191,7 +192,6 @@ public class SingleRowLayout extends TabLayout { private void layoutLabelsAndGhosts(final SingleRowPassInfo data) { final int fixedPosition = getStrategy().getFixedPosition(data); - boolean reachedBounds = false; if (data.firstGhostVisible || myTabs.isGhostsAlwaysVisible()) { data.firstGhost = getStrategy().getLayoutRec(data.position, fixedPosition, myTabs.getGhostTabLength(), getStrategy().getFixedFitLength(data)); @@ -224,7 +224,7 @@ public class SingleRowLayout extends TabLayout { myTabs.layout(label, rec); } - label.setAligmentToCenter((deltaToFit > 0 || myTabs.isEditorTabs()) && getStrategy().isToCenterTextWhenStretched()); + label.setAlignmentToCenter((deltaToFit > 0 || myTabs.isEditorTabs()) && getStrategy().isToCenterTextWhenStretched()); data.position = getStrategy().getMaxPosition(label.getBounds()); data.position += myTabs.getInterTabSpaceLength(); @@ -233,7 +233,7 @@ public class SingleRowLayout extends TabLayout { } for (TabInfo eachInfo : data.toDrop) { - myTabs.resetLayout(myTabs.myInfo2Label.get(eachInfo)); + JBTabsImpl.resetLayout(myTabs.myInfo2Label.get(eachInfo)); } if (data.lastGhostVisible || myTabs.isGhostsAlwaysVisible()) { @@ -326,13 +326,13 @@ public class SingleRowLayout extends TabLayout { }); } - public void setInfo(final TabInfo info) { + public void setInfo(@Nullable final TabInfo info) { myInfo = info; setToolTipText(info != null ? info.getTooltipText() : null); } public void reset() { - myTabs.resetLayout(this); + JBTabsImpl.resetLayout(this); setInfo(null); } } @@ -367,7 +367,7 @@ public class SingleRowLayout extends TabLayout { Component c = myTabs.getComponentAt(point); - if (c instanceof JBTabsImpl && !(c instanceof TabLabel)) { + if (c instanceof JBTabsImpl) { for (int i = 0; i < myLastSingRowLayout.myVisibleInfos.size() - 1; i++) { TabLabel first = myTabs.myInfo2Label.get(myLastSingRowLayout.myVisibleInfos.get(i)); TabLabel second = myTabs.myInfo2Label.get(myLastSingRowLayout.myVisibleInfos.get(i + 1)); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java index 8919f8cdf8e2..f859fb14f71f 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/singleRow/SingleRowLayoutStrategy.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package com.intellij.ui.tabs.impl.singleRow; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.ShapeTransform; import com.intellij.ui.tabs.impl.TabLabel; -import com.intellij.ui.tabs.impl.table.TableLayout; +import com.intellij.ui.tabs.impl.TabLayout; import java.awt.*; @@ -83,7 +83,7 @@ public abstract class SingleRowLayoutStrategy { @Override public boolean isDragOut(TabLabel tabLabel, int deltaX, int deltaY) { - return Math.abs(deltaY) > tabLabel.getHeight() * TableLayout.getDragOutMultiplier(); + return Math.abs(deltaY) > tabLabel.getHeight() * TabLayout.getDragOutMultiplier(); } public int getMoreRectAxisSize() { @@ -230,7 +230,7 @@ public abstract class SingleRowLayoutStrategy { @Override public boolean isDragOut(TabLabel tabLabel, int deltaX, int deltaY) { - return Math.abs(deltaX) > tabLabel.getHeight() * TableLayout.getDragOutMultiplier(); + return Math.abs(deltaX) > tabLabel.getHeight() * TabLayout.getDragOutMultiplier(); } public boolean isToCenterTextWhenStretched() { diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java index d28f6b4eb91c..f2cdf9b374ef 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TableLayout.java @@ -158,7 +158,7 @@ public class TableLayout extends TabLayout { } myTabs.layout(label, eachX, eachY, width, row < data.table.size() - 1 ? myTabs.myHeaderFitSize.height - tabUnderlineFix : myTabs.myHeaderFitSize.height); - label.setAligmentToCenter(deltaToFit > 0); + label.setAlignmentToCenter(deltaToFit > 0); boolean lastCell = i == eachRow.myColumns.size() - 1; eachX += width + (lastCell ? 0 : myTabs.getInterTabSpaceLength()); diff --git a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java index b2abc5056845..d29ced04e289 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/impl/table/TablePassInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.intellij.ui.tabs.impl.table; import com.intellij.ui.tabs.TabInfo; import com.intellij.ui.tabs.impl.JBTabsImpl; import com.intellij.ui.tabs.impl.LayoutPassInfo; +import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.ArrayList; @@ -36,16 +37,18 @@ public class TablePassInfo extends LayoutPassInfo { JBTabsImpl myTabs; - TablePassInfo(final JBTabsImpl tabs, java.util.List visibleInfos) { + TablePassInfo(final JBTabsImpl tabs, List visibleInfos) { super(visibleInfos); myTabs = tabs; } + @Nullable public TabInfo getPreviousFor(final TabInfo info) { final TableRow row = myInfo2Row.get(info); return row != null ? getPrevious(row.myColumns, row.myColumns.indexOf(info)) : null; } + @Nullable public TabInfo getNextFor(final TabInfo info) { final TableRow row = myInfo2Row.get(info); return row != null ? getNext(row.myColumns, row.myColumns.indexOf(info)) : null; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java new file mode 100644 index 000000000000..a91f5bbc13fc --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/TabListAction.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.ide.actions; + +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.ui.tabs.impl.JBTabsImpl; + +/** + * Shows the popup of all tabs when single row editor tab layout is used and all tabs don't fit on the screen. + * + * @author yole + */ +public class TabListAction extends AnAction { + @Override + public void actionPerformed(AnActionEvent e) { + JBTabsImpl tabs = e.getData(JBTabsImpl.NAVIGATION_ACTIONS_KEY); + if (tabs != null) { + tabs.showMorePopup(null); + } + } + + @Override + public void update(AnActionEvent e) { + e.getPresentation().setEnabled(isTabListAvailable(e)); + } + + private static boolean isTabListAvailable(AnActionEvent e) { + JBTabsImpl tabs = e.getData(JBTabsImpl.NAVIGATION_ACTIONS_KEY); + if (tabs == null || !tabs.isEditorTabs()) { + return false; + } + return tabs.canShowMorePopup(); + } +} 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 f304cf85b715..8d1732e88c5a 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,12 @@ package com.intellij.ide.impl; import com.intellij.CommonBundle; import com.intellij.ide.GeneralSettings; import com.intellij.ide.IdeBundle; -import com.intellij.ide.highlighter.InternalFileType; 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; -import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ex.ProjectEx; @@ -53,13 +51,12 @@ import java.io.IOException; public class ProjectUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.ide.impl.ProjectUtil"); - private ProjectUtil() { - } + private ProjectUtil() { } public static void updateLastProjectLocation(final String projectFilePath) { File lastProjectLocation = new File(projectFilePath); if (lastProjectLocation.isFile()) { - lastProjectLocation = lastProjectLocation.getParentFile(); //for directory based project storages + lastProjectLocation = lastProjectLocation.getParentFile(); // for directory-based project storage } if (lastProjectLocation == null) { // the immediate parent of the ipr file return; @@ -141,7 +138,7 @@ public class ProjectUtil { } @Nullable - public static Project openProject(final String path, Project projectToClose, boolean forceOpenInNewFrame) { + public static Project openProject(final String path, @Nullable Project projectToClose, boolean forceOpenInNewFrame) { File file = new File(path); if (!file.exists()) { Messages.showErrorDialog(IdeBundle.message("error.project.file.does.not.exist", path), CommonBundle.getErrorTitle()); @@ -164,7 +161,8 @@ public class ProjectUtil { if (!forceOpenInNewFrame && openProjects.length > 0) { int exitCode = confirmOpenNewProject(false); if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) { - if (!closeAndDispose(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null; + final Project toClose = projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]; + if (!closeAndDispose(toClose)) return null; } else if (exitCode != GeneralSettings.OPEN_PROJECT_NEW_WINDOW) { return null; @@ -205,19 +203,23 @@ public class ProjectUtil { if (confirmOpenNewProject == GeneralSettings.OPEN_PROJECT_ASK) { if (isNewProject) { int exitCode = Messages.showYesNoDialog(IdeBundle.message("prompt.open.project.in.new.frame"), - IdeBundle.message("title.new.project"), - IdeBundle.message("button.existingframe"), - IdeBundle.message("button.newframe"), - Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption()); + IdeBundle.message("title.new.project"), + IdeBundle.message("button.existingframe"), + IdeBundle.message("button.newframe"), + Messages.getQuestionIcon(), + new ProjectNewWindowDoNotAskOption()); return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW; } else { int exitCode = Messages.showYesNoCancelDialog(IdeBundle.message("prompt.open.project.in.new.frame"), - IdeBundle.message("title.open.project"), - IdeBundle.message("button.existingframe"), IdeBundle.message("button.newframe"), - CommonBundle.getCancelButtonText(), Messages.getQuestionIcon(), - new ProjectNewWindowDoNotAskOption()); - return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : exitCode == 1 ? GeneralSettings.OPEN_PROJECT_NEW_WINDOW : Messages.CANCEL; + IdeBundle.message("title.open.project"), + IdeBundle.message("button.existingframe"), + IdeBundle.message("button.newframe"), + CommonBundle.getCancelButtonText(), + Messages.getQuestionIcon(), + new ProjectNewWindowDoNotAskOption()); + return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : + exitCode == 1 ? GeneralSettings.OPEN_PROJECT_NEW_WINDOW : Messages.CANCEL; } } return confirmOpenNewProject; @@ -265,6 +267,10 @@ public class ProjectUtil { } } + /** + * @deprecated use {@linkplain com.intellij.openapi.project.ProjectUtil#isProjectOrWorkspaceFile(com.intellij.openapi.vfs.VirtualFile)} (to remove in IDEA 13) + */ + @SuppressWarnings("UnusedDeclaration") public static boolean isProjectOrWorkspaceFile(final VirtualFile file) { return com.intellij.openapi.project.ProjectUtil.isProjectOrWorkspaceFile(file); } diff --git a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java index f4b45cd6f86c..89490155d5db 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLogConsole.java @@ -48,6 +48,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.event.MouseEvent; +import java.util.*; +import java.util.List; /** * @author peter @@ -142,6 +144,8 @@ class EventLogConsole { String date = DateFormatUtil.formatTimeWithSeconds(notificationTime) + " "; append(document, date); + int startLine = document.getLineCount() - 1; + EventLog.LogEntry pair = EventLog.formatForLog(notification, StringUtil.repeatSymbol(' ', date.length())); final NotificationType type = notification.getType(); @@ -172,34 +176,44 @@ class EventLogConsole { } if (notification.isImportant()) { - highlightNotification(notification, pair.status, document.getLineCount() - 2); + highlightNotification(notification, pair.status, startLine, document.getLineCount() - 1); } } private void highlightNotification(final Notification notification, - String message, final int line) { + String message, final int line1, final int line2) { final MarkupModel markupModel = myLogEditor.getValue().getMarkupModel(); TextAttributes bold = new TextAttributes(null, null, null, null, Font.BOLD); - final RangeHighlighter lineHighlighter = markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, bold); - Color color = notification.getType() == NotificationType.ERROR - ? Color.red - : notification.getType() == NotificationType.WARNING ? Color.yellow : Color.green; - lineHighlighter.setErrorStripeMarkColor(color); - lineHighlighter.setErrorStripeTooltip(message); + final List lineColors = new ArrayList(); + for (int line = line1; line < line2; line++) { + final RangeHighlighter lineHighlighter = markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, bold); + Color color = notification.getType() == NotificationType.ERROR + ? Color.red + : notification.getType() == NotificationType.WARNING ? Color.yellow : Color.green; + lineHighlighter.setErrorStripeMarkColor(color); + lineHighlighter.setErrorStripeTooltip(message); + lineColors.add(lineHighlighter); + } myProjectModel.removeHandlers.put(notification, new Runnable() { @Override public void run() { - markupModel.removeHighlighter(lineHighlighter); + for (RangeHighlighter color : lineColors) { + markupModel.removeHighlighter(color); + } TextAttributes attributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(ConsoleViewContentType.LOG_EXPIRED_ENTRY); - markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, attributes); + for (int line = line1; line < line2; line++) { + markupModel.addLineHighlighter(line, HighlighterLayer.CARET_ROW + 1, attributes); + } TextAttributes italic = new TextAttributes(null, null, null, null, Font.ITALIC); - for (RangeHighlighter highlighter : myHyperlinkSupport.getValue().findAllHyperlinksOnLine(line)) { - markupModel.addRangeHighlighter(highlighter.getStartOffset(), highlighter.getEndOffset(), HighlighterLayer.CARET_ROW + 2, italic, HighlighterTargetArea.EXACT_RANGE); - myHyperlinkSupport.getValue().removeHyperlink(highlighter); + for (int line = line1; line < line2; line++) { + for (RangeHighlighter highlighter : myHyperlinkSupport.getValue().findAllHyperlinksOnLine(line)) { + markupModel.addRangeHighlighter(highlighter.getStartOffset(), highlighter.getEndOffset(), HighlighterLayer.CARET_ROW + 2, italic, HighlighterTargetArea.EXACT_RANGE); + myHyperlinkSupport.getValue().removeHyperlink(highlighter); + } } } }); diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java index 2a00aec29da8..22c40fe0176a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java +++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionMenu.java @@ -24,8 +24,8 @@ import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.impl.actionholder.ActionRef; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.wm.IdeFrame; import com.intellij.openapi.wm.StatusBar; -import com.intellij.openapi.wm.impl.IdeFrameImpl; import com.intellij.ui.plaf.beg.IdeaMenuUI; import com.intellij.ui.plaf.gtk.GtkMenuUI; import com.intellij.util.ui.UIUtil; @@ -198,9 +198,9 @@ public final class ActionMenu extends JMenu { } public static void showDescriptionInStatusBar(boolean isIncluded, Component component, String description) { - IdeFrameImpl frame = component instanceof IdeFrameImpl - ? (IdeFrameImpl)component - : (IdeFrameImpl)SwingUtilities.getAncestorOfClass(IdeFrameImpl.class, component); + IdeFrame frame = component instanceof IdeFrame + ? (IdeFrame)component + : (IdeFrame)SwingUtilities.getAncestorOfClass(IdeFrame.class, component); if (frame != null) { StatusBar statusBar = frame.getStatusBar(); if (isIncluded) { diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java index c8587a70e4c3..156c0dbaa2e0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -86,6 +86,11 @@ public class DummyProject extends UserDataHolderBase implements Project { return null; } + @Override + public String getBasePath() { + return null; + } + public void save() { } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java index 1edab5c1bf5a..356244d76a30 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package com.intellij.openapi.components.impl.stores; - import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; @@ -28,7 +27,7 @@ import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.options.StreamProvider; import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileAdapter; @@ -78,6 +77,7 @@ public class FileBasedStorage extends XmlElementStorage { syncRefreshPathRecursively(PathManager.getConfigPath(true), "componentVersions"); } finally { + //noinspection AssignmentToStaticFieldFromInstanceMethod myConfigDirectoryRefreshed = true; } } @@ -125,10 +125,6 @@ public class FileBasedStorage extends XmlElementStorage { } } - private static boolean isOptionsFile(final String filePath) { - return FileUtil.isAncestor(new File(PathManager.getOptionsPath()), new File(filePath), false); - } - protected MySaveSession createSaveSession(final MyExternalizationSession externalizationSession) { return new FileSaveSession(externalizationSession); } @@ -162,7 +158,7 @@ public class FileBasedStorage extends XmlElementStorage { protected void doSave() throws StateStorageException { if (!myBlockSavingTheContent) { - if (ApplicationManager.getApplication().isUnitTestMode() && myFile != null && myFile.getPath().startsWith("$")) { + if (ApplicationManager.getApplication().isUnitTestMode() && myFile != null && StringUtil.startsWithChar(myFile.getPath(), '$')) { throw new StateStorageException("It seems like some macros were not expanded for path: " + myFile.getPath()); } @@ -228,9 +224,8 @@ public class FileBasedStorage extends XmlElementStorage { return StorageUtil.getVirtualFile(myFile); } - - public IFile getFile() { - return myFile; + public File getFile() { + return new File(myFile.getPath()); } @Nullable @@ -254,6 +249,7 @@ public class FileBasedStorage extends XmlElementStorage { } } + @Nullable private Document processReadException(final Exception e) { myBlockSavingTheContent = isProjectOrModuleFile(); if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java index 376c64a10ff1..abc3fbe30928 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,8 +31,6 @@ import java.io.IOException; import java.util.Set; public interface IProjectStore extends IComponentStore { - - boolean checkVersion(); void setProjectFilePath(final String filePath); @@ -40,6 +38,12 @@ public interface IProjectStore extends IComponentStore { @Nullable VirtualFile getProjectBaseDir(); + @Nullable + String getProjectBasePath(); + + /** + * @deprecated please use {@linkplain #getPresentableUrl()} or {@linkplain #getProjectBasePath()} (to remove in IDEA 13). + */ @Nullable String getLocation(); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java index fc45c3d4d4b1..6b49310d49fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,10 +35,8 @@ import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.ReadonlyStatusHandler; -import com.intellij.openapi.vfs.VfsUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.*; import com.intellij.util.containers.OrderedSet; import com.intellij.util.io.fs.FileSystem; import com.intellij.util.io.fs.IFile; @@ -46,7 +44,6 @@ import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.annotation.Annotation; @@ -57,30 +54,31 @@ import java.util.Set; class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProjectStore { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.ProjectStoreImpl"); + @NonNls private static final String OLD_PROJECT_SUFFIX = "_old."; @NonNls static final String OPTION_WORKSPACE = "workspace"; - - protected ProjectImpl myProject; - @NonNls static final String PROJECT_FILE_MACRO = "PROJECT_FILE"; @NonNls static final String WS_FILE_MACRO = "WORKSPACE_FILE"; @NonNls private static final String PROJECT_CONFIG_DIR = "PROJECT_CONFIG_DIR"; - static final String PROJECT_FILE_STORAGE = "$" + PROJECT_FILE_MACRO + "$"; - static final String WS_FILE_STORAGE = "$" + WS_FILE_MACRO + "$"; - static final String DEFAULT_STATE_STORAGE = PROJECT_FILE_STORAGE; + @NonNls static final String PROJECT_FILE_STORAGE = "$" + PROJECT_FILE_MACRO + "$"; + @NonNls static final String WS_FILE_STORAGE = "$" + WS_FILE_MACRO + "$"; + @NonNls static final String DEFAULT_STATE_STORAGE = PROJECT_FILE_STORAGE; static final Storage DEFAULT_STORAGE_ANNOTATION = new MyStorage(); private static int originalVersion = -1; + protected ProjectImpl myProject; private StorageScheme myScheme = StorageScheme.DEFAULT; private String myCachedLocation; + private String myPresentableUrl; ProjectStoreImpl(final ProjectImpl project) { super(project); myProject = project; } + @Override public boolean checkVersion() { final ApplicationNamesInfo appNamesInfo = ApplicationNamesInfo.getInstance(); if (originalVersion >= 0 && originalVersion < ProjectManagerImpl.CURRENT_FORMAT_VERSION) { @@ -130,10 +128,10 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject private void backup(final VirtualFile projectDir, final VirtualFile vile) throws IOException { final String oldName = vile.getNameWithoutExtension() + OLD_PROJECT_SUFFIX + vile.getExtension(); - VirtualFile oldFile = projectDir.findOrCreateChildData(this, oldName); - VfsUtil.saveText(oldFile, VfsUtil.loadText(vile)); + final VirtualFile oldFile = projectDir.findOrCreateChildData(this, oldName); + assert oldFile != null : projectDir + ", " + oldName; + VfsUtil.saveText(oldFile, VfsUtilCore.loadText(vile)); } - }); } @@ -147,6 +145,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return true; } + @Override public TrackingPathMacroSubstitutor[] getSubstitutors() { return new TrackingPathMacroSubstitutor[] {getStateStorageManager().getMacroSubstitutor()}; } @@ -161,79 +160,77 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return myProject; } + @Override public void setProjectFilePath(final String filePath) { if (filePath == null) { return; } - final IFile iFile = FileSystem.FILE_SYSTEM.createFile(filePath); final StateStorageManager stateStorageManager = getStateStorageManager(); - - if (!isIprPath(iFile)) { - final IFile dir_store = - iFile.isDirectory() - ? iFile.getChild(Project.DIRECTORY_STORE_FOLDER) - : iFile.getParentFile().getChild(Project.DIRECTORY_STORE_FOLDER); - FileBasedStorage.syncRefreshPathRecursively(dir_store.getPath(), null); + final File file = new File(filePath); + if (!isIprPath(file)) { + final File dirStore = file.isDirectory() ? new File(file, Project.DIRECTORY_STORE_FOLDER) + : new File(file.getParentFile(), Project.DIRECTORY_STORE_FOLDER); + FileBasedStorage.syncRefreshPathRecursively(dirStore.getPath(), null); myScheme = StorageScheme.DIRECTORY_BASED; + stateStorageManager.addMacro(PROJECT_FILE_MACRO, new File(dirStore, "misc.xml").getPath()); - stateStorageManager.addMacro(PROJECT_FILE_MACRO, dir_store.getChild("misc.xml").getPath()); - final IFile ws = dir_store.getChild("workspace.xml"); + final File ws = new File(dirStore, "workspace.xml"); stateStorageManager.addMacro(WS_FILE_MACRO, ws.getPath()); - if (!ws.exists() && !iFile.isDirectory()) { + if (!ws.exists() && !file.isDirectory()) { useOldWsContent(filePath, ws); } - stateStorageManager.addMacro(PROJECT_CONFIG_DIR, dir_store.getPath()); - } else { + stateStorageManager.addMacro(PROJECT_CONFIG_DIR, dirStore.getPath()); + } + else { + LocalFileSystem.getInstance().refreshAndFindFileByPath(filePath); + myScheme = StorageScheme.DEFAULT; stateStorageManager.addMacro(PROJECT_FILE_MACRO, filePath); - LocalFileSystem.getInstance().refreshAndFindFileByPath(filePath); - - int lastDot = filePath.lastIndexOf("."); - final String filePathWithoutExt = lastDot > 0 ? filePath.substring(0, lastDot) : filePath; - String workspacePath = filePathWithoutExt + WorkspaceFileType.DOT_DEFAULT_EXTENSION; - + final String workspacePath = composeWsPath(filePath); LocalFileSystem.getInstance().refreshAndFindFileByPath(workspacePath); stateStorageManager.addMacro(WS_FILE_MACRO, workspacePath); } myCachedLocation = null; - } - - private static boolean isIprPath(final IFile file) { - return file.getName().indexOf(".") > 0 && ProjectFileType.DEFAULT_EXTENSION.equals(FileUtil.getExtension(file.getName())); + myPresentableUrl = null; } - private static void useOldWsContent(final String filePath, final IFile ws) { - int lastDot = filePath.lastIndexOf("."); + private static boolean isIprPath(final File file) { + final String name = file.getName(); + return name.indexOf(".") > 0 && ProjectFileType.DEFAULT_EXTENSION.equals(FileUtil.getExtension(name)); + } + + private static String composeWsPath(String filePath) { + final int lastDot = filePath.lastIndexOf("."); final String filePathWithoutExt = lastDot > 0 ? filePath.substring(0, lastDot) : filePath; - String workspacePath = filePathWithoutExt + WorkspaceFileType.DOT_DEFAULT_EXTENSION; - IFile oldWs = FileSystem.FILE_SYSTEM.createFile(workspacePath); + return filePathWithoutExt + WorkspaceFileType.DOT_DEFAULT_EXTENSION; + } + + private static void useOldWsContent(final String filePath, final File ws) { + final File oldWs = new File(composeWsPath(filePath)); if (oldWs.exists()) { try { - final InputStream is = oldWs.openInputStream(); - final byte[] bytes; - + final InputStream is = new FileInputStream(oldWs); try { - bytes = FileUtil.loadBytes(is, (int)oldWs.length()); + final byte[] bytes = FileUtil.loadBytes(is, (int)oldWs.length()); + + final OutputStream os = new FileOutputStream(ws); + try { + os.write(bytes); + } + finally { + os.close(); + } } finally { is.close(); } - - final OutputStream os = ws.openOutputStream(); - try { - os.write(bytes); - } - finally { - os.close(); - } - } catch (IOException e) { LOG.error(e); @@ -241,24 +238,37 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } } - @Nullable + @Override public VirtualFile getProjectBaseDir() { - final VirtualFile projectFile = getProjectFile(); - if (projectFile != null) return myScheme == StorageScheme.DEFAULT ? projectFile.getParent() : projectFile.getParent().getParent(); + if (myProject.isDefault()) return null; + + final String path = getProjectBasePath(); + if (path == null) return null; + + return LocalFileSystem.getInstance().findFileByPath(path); + } + + @Override + public String getProjectBasePath() { + if (myProject.isDefault()) return null; + + final String path = getProjectFilePath(); + if (!StringUtil.isEmptyOrSpaces(path)) { + return myScheme == StorageScheme.DEFAULT ? new File(path).getParent() : new File(path).getParentFile().getParent(); + } //we are not yet initialized completely ("open directory", etc) final StateStorage s = getStateStorageManager().getFileStateStorage(PROJECT_FILE_STORAGE); if (!(s instanceof FileBasedStorage)) return null; final FileBasedStorage storage = (FileBasedStorage)s; - final IFile file = storage.getFile(); + final File file = storage.getFile(); if (file == null) return null; - return LocalFileSystem.getInstance() - .findFileByIoFile(myScheme == StorageScheme.DEFAULT ? file.getParentFile() : file.getParentFile().getParentFile()); + return myScheme == StorageScheme.DEFAULT ? file.getParent() : file.getParentFile().getParent(); } - @Nullable + @Override public String getLocation() { if (myCachedLocation == null) { if (myScheme == StorageScheme.DEFAULT) { @@ -274,79 +284,70 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } @NotNull + @Override public String getProjectName() { if (myScheme == StorageScheme.DIRECTORY_BASED) { final VirtualFile baseDir = getProjectBaseDir(); - assert baseDir != null : "project file: " + (getProjectFile() == null ? "[NULL]" : getProjectFile().getPath()); + assert baseDir != null : "project file: " + getProjectFile(); final VirtualFile ideaDir = baseDir.findChild(".idea"); if (ideaDir != null && ideaDir.isValid()) { final VirtualFile nameFile = ideaDir.findChild(".name"); if (nameFile != null && nameFile.isValid()) { - BufferedReader in = null; try { - in = new BufferedReader(new InputStreamReader(nameFile.getInputStream(), "UTF-8")); - final String name = in.readLine(); - if (name != null && name.length() > 0) return name.trim(); - } - catch (IOException e) { - // ignore - } - finally { - if (in != null) { - try { - in.close(); - } - catch (IOException e) { - // ignore + BufferedReader in = new BufferedReader(new InputStreamReader(nameFile.getInputStream(), "UTF-8")); + try { + final String name = in.readLine(); + if (name != null && name.length() > 0) { + return name.trim(); } } + finally { + in.close(); + } } + catch (IOException ignored) { } } } - return baseDir.getName().replace(":", ""); } - - String temp = getProjectFileName(); - FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(temp); - if (fileType instanceof ProjectFileType) { - temp = temp.substring(0, temp.length() - fileType.getDefaultExtension().length()-1); + else { + String temp = getProjectFileName(); + FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(temp); + if (fileType instanceof ProjectFileType) { + temp = temp.substring(0, temp.length() - fileType.getDefaultExtension().length() - 1); + } + final int i = temp.lastIndexOf(File.separatorChar); + if (i >= 0) { + temp = temp.substring(i + 1, temp.length() - i + 1); + } + return temp; } - final int i = temp.lastIndexOf(File.separatorChar); - if (i >= 0) { - temp = temp.substring(i + 1, temp.length() - i + 1); - } - return temp; } @NotNull + @Override public StorageScheme getStorageScheme() { return myScheme; } - @Nullable + @Override public String getPresentableUrl() { if (myProject.isDefault()) return null; - if (myScheme == StorageScheme.DIRECTORY_BASED) { - final VirtualFile baseDir = getProjectBaseDir(); - return baseDir != null ? baseDir.getPresentableUrl() : null; - } - else { - if (myProject.isDefault()) return null; - final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(PROJECT_FILE_STORAGE); - assert storage != null; - return storage.getFilePath().replace('/', File.separatorChar); + if (myPresentableUrl == null) { + final String url = myScheme == StorageScheme.DIRECTORY_BASED ? getProjectBasePath() : getProjectFilePath(); + myPresentableUrl = url != null ? FileUtil.toSystemDependentName(url) : url; } + return myPresentableUrl; } + @Override public void loadProject() throws IOException, JDOMException, InvalidDataException, StateStorageException { - //load(); myProject.init(); } - @Nullable + @Override public VirtualFile getProjectFile() { if (myProject.isDefault()) return null; final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(PROJECT_FILE_STORAGE); @@ -354,7 +355,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return storage.getVirtualFile(); } - @Nullable + @Override public VirtualFile getWorkspaceFile() { if (myProject.isDefault()) return null; final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(WS_FILE_STORAGE); @@ -362,6 +363,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return storage.getVirtualFile(); } + @Override public void loadProjectFromTemplate(final ProjectImpl defaultProject) { final StateStorage stateStorage = getStateStorageManager().getFileStateStorage(DEFAULT_STATE_STORAGE); @@ -379,6 +381,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } @NotNull + @Override public String getProjectFileName() { final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(PROJECT_FILE_STORAGE); assert storage != null; @@ -386,20 +389,22 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } @NotNull + @Override public String getProjectFilePath() { if (myProject.isDefault()) return ""; - final FileBasedStorage storage = (FileBasedStorage)getStateStorageManager().getFileStateStorage(PROJECT_FILE_STORAGE); assert storage != null; return storage.getFilePath(); } + @Override protected XmlElementStorage getMainStorage() { final XmlElementStorage storage = (XmlElementStorage)getStateStorageManager().getFileStateStorage(DEFAULT_STATE_STORAGE); assert storage != null; return storage; } + @Override protected StateStorageManager createStateStorageManager() { return new ProjectStateStorageManager(PathMacroManager.getInstance(getComponentManager()).createTrackingSubstitutor(), myProject); } @@ -424,7 +429,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } static class WsStorageData extends ProjectStorageData { - WsStorageData(final String rootElementName, final Project project) { super(rootElementName, project); } @@ -449,6 +453,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject protected void load(@NotNull final Element root) throws IOException { final String v = root.getAttributeValue(VERSION_OPTION); + //noinspection AssignmentToStaticFieldFromInstanceMethod originalVersion = v != null ? Integer.parseInt(v) : 0; if (originalVersion != ProjectManagerImpl.CURRENT_FORMAT_VERSION) { @@ -466,12 +471,12 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } } + @Override protected SaveSessionImpl createSaveSession() throws StateStorageException { return new ProjectSaveSession(); } protected class ProjectSaveSession extends SaveSessionImpl { - ProjectSaveSession() throws StateStorageException { } @@ -533,7 +538,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject List readonlyFiles = new ArrayList(); - if (((ProjectImpl)myProject).isToSaveProjectName()) { + if (myProject.isToSaveProjectName()) { final VirtualFile baseDir = getProjectBaseDir(); if (baseDir != null && baseDir.isValid()) { filesToSave.add(FileSystem.FILE_SYSTEM @@ -627,14 +632,15 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } }; - @Nullable + @Override protected StateStorageChooser getDefaultStateStorageChooser() { return myStateStorageChooser; } @NotNull - protected Storage[] getComponentStorageSpecs(@NotNull final PersistentStateComponent persistentStateComponent, final StateStorageOperation operation) throws - StateStorageException { + @Override + protected Storage[] getComponentStorageSpecs(@NotNull final PersistentStateComponent persistentStateComponent, + final StateStorageOperation operation) throws StateStorageException { Storage[] result = super.getComponentStorageSpecs(persistentStateComponent, operation); if (operation == StateStorageOperation.READ) { @@ -647,6 +653,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject return result; } + @SuppressWarnings("ClassExplicitlyAnnotation") private static class MyStorage implements Storage { public String id() { return "___Default___"; @@ -716,7 +723,6 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject } } - return true; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java index c6ff42153029..d94ebcef085b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/CompareJarsAction.java @@ -19,6 +19,7 @@ import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.ide.diff.DirDiffSettings; import com.intellij.ide.diff.JarFileDiffElement; import com.intellij.ide.diff.VirtualFileDiffElement; +import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.PlatformDataKeys; @@ -26,7 +27,6 @@ import com.intellij.openapi.diff.DirDiffManager; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserFactory; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VirtualFile; /** @@ -42,21 +42,21 @@ public class CompareJarsAction extends AnAction { if (project != null && files != null) { VirtualFileDiffElement src = null; VirtualFileDiffElement trg = null; - if (files.length == 2 && isJar(files[0]) && isJar(files[1])) { + if (files.length == 2 && isArchive(files[0]) && isArchive(files[1])) { src = new JarFileDiffElement(files[0]); trg = new JarFileDiffElement(files[1]); - } else if (files.length == 1 && isJar(files[0])) { + } else if (files.length == 1 && isArchive(files[0])) { src = new JarFileDiffElement(files[0]); final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, true, true, false, false) { @Override public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) { return file.isDirectory() - || (!file.isDirectory() && JarFileSystem.PROTOCOL.equalsIgnoreCase(file.getExtension())); + || (!file.isDirectory() && isArchive(file)); } }; final VirtualFile[] result = FileChooserFactory.getInstance() .createFileChooser(descriptor, project).choose(project.getBaseDir(), project); - if (result.length == 1 && result[0] != null && isJar(result[0])) { + if (result.length == 1 && result[0] != null && isArchive(result[0])) { trg = new JarFileDiffElement(result[0]); } } @@ -71,10 +71,10 @@ public class CompareJarsAction extends AnAction { public void update(AnActionEvent e) { final VirtualFile[] files = e.getData(PlatformDataKeys.VIRTUAL_FILE_ARRAY); if (files != null && files.length > 0 && files.length < 3) { - if (isJar(files[0]) && (files.length == 1 || isJar(files[1]))) { + if (isArchive(files[0]) && (files.length == 1 || isArchive(files[1]))) { e.getPresentation().setEnabled(true); e.getPresentation().setVisible(true); - e.getPresentation().setText(files.length == 1 ? "Compare Jar File with..." : "Compare Jar Files"); + e.getPresentation().setText(files.length == 1 ? "Compare Archive File with..." : "Compare Archives"); return; } } @@ -83,7 +83,7 @@ public class CompareJarsAction extends AnAction { e.getPresentation().setVisible(false); } - private static boolean isJar(VirtualFile file) { - return JarFileSystem.PROTOCOL.equalsIgnoreCase(file.getExtension()); + private static boolean isArchive(VirtualFile file) { + return file.getFileType() instanceof ArchiveFileType; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java index 31232ef27eeb..a823d733d9cf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/CompositeDiffPanel.java @@ -71,6 +71,7 @@ public class CompositeDiffPanel implements DiffViewer { viewer.setDiffRequest(diffRequest); } else { final DiffViewer newViewer = myRequest.viewerForRequest(myWindow, myParentDisposable, key, diffRequest); + if (newViewer == null) continue; myMap.put(key, newViewer); final Content content = myUi.createContent(key, newViewer.getComponent(), key, null, newViewer.getPreferredFocusedComponent()); content.setCloseable(false); diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ArchiveDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ArchiveDiffTool.java new file mode 100644 index 000000000000..f05a80373062 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/ArchiveDiffTool.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.diff.impl.external; + +import com.intellij.ide.diff.JarFileDiffElement; +import com.intellij.ide.highlighter.ArchiveFileType; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.diff.*; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFocusManager; + +import java.awt.*; + +/** + * @author Konstantin Bulenkov + */ +public class ArchiveDiffTool implements DiffTool { + public static final ArchiveDiffTool INSTANCE = new ArchiveDiffTool(); + + private ArchiveDiffTool(){} + + @Override + public void show(DiffRequest request) { + final DiffContent[] contents = request.getContents(); + final VirtualFile file1 = contents[0].getFile(); + final VirtualFile file2 = contents[1].getFile(); + assert file1 != null && file2 != null; + final JarFileDiffElement element = new JarFileDiffElement(file1); + final JarFileDiffElement element1 = new JarFileDiffElement(file2); + DirDiffManager.getInstance(request.getProject()).showDiff(element, element1); + } + + @Override + public boolean canShow(DiffRequest request) { + final DiffContent[] contents = request.getContents(); + final DialogWrapper instance = DialogWrapper.findInstance(IdeFocusManager.getInstance(request.getProject()).getFocusOwner()); + if (instance != null && instance.isModal()) return false; + if (contents.length == 2) { + final VirtualFile file1 = contents[0].getFile(); + final VirtualFile file2 = contents[1].getFile(); + if (file1 != null && file2 != null) { + final FileType type1 = contents[0].getContentType(); + final FileType type2 = contents[1].getContentType(); + return type1 == type2 && type1 instanceof ArchiveFileType; + } + } + return false; + } + + @Override + public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { + return null; + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java index 6278a3d8df57..8d306a464b53 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/CompositeDiffTool.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.diff.impl.external; +import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diff.*; @@ -57,12 +58,17 @@ class CompositeDiffTool implements DiffTool { private DiffTool chooseTool(DiffRequest data) { final DiffContent[] contents = data.getContents(); - if (contents != null && contents.length == 2) { + if (contents.length == 2) { final FileType type1 = contents[0].getContentType(); final FileType type2 = contents[1].getContentType(); if (type1 == type2 && type1 instanceof UIBasedFileType) { return BinaryDiffTool.INSTANCE; } + + //todo[kb] register or not this instance in common diff tools ? + if (type1 == type2 && type1 instanceof ArchiveFileType) { + return ArchiveDiffTool.INSTANCE; + } } for (DiffTool tool : myTools) { diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java index d08f609b6457..c7d15dcbf4f3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java +++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/FrameDiffTool.java @@ -48,7 +48,7 @@ class FrameDiffTool implements DiffTool { boolean shouldOpenDialog = shouldOpenDialog(hints); if (shouldOpenDialog) { final DialogBuilder builder = new DialogBuilder(request.getProject()); - DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, builder.getWindow(), builder); + DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, builder.getWindow(), builder, true); if (diffPanel == null) { Disposer.dispose(builder); return; @@ -83,7 +83,7 @@ class FrameDiffTool implements DiffTool { } else { final FrameWrapper frameWrapper = new FrameWrapper(request.getProject(), request.getGroupKey()); - DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, frameWrapper.getFrame(), frameWrapper); + DiffPanelImpl diffPanel = createDiffPanelIfShouldShow(request, frameWrapper.getFrame(), frameWrapper, true); if (diffPanel == null) { Disposer.dispose(frameWrapper); return; @@ -134,9 +134,10 @@ class FrameDiffTool implements DiffTool { }*/ @Nullable - private static DiffPanelImpl createDiffPanelIfShouldShow(DiffRequest request, Window window, @NotNull Disposable parentDisposable) { + private static DiffPanelImpl createDiffPanelIfShouldShow(DiffRequest request, Window window, @NotNull Disposable parentDisposable, + final boolean showMessage) { DiffPanelImpl diffPanel = (DiffPanelImpl)DiffManagerImpl.createDiffPanel(request, window, parentDisposable); - if (checkNoDifferenceAndNotify(diffPanel, request, window)) { + if (checkNoDifferenceAndNotify(diffPanel, request, window, showMessage)) { Disposer.dispose(diffPanel); diffPanel = null; } @@ -154,7 +155,7 @@ class FrameDiffTool implements DiffTool { return KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow() instanceof JDialog; } - private static boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data, final Window window) { + private static boolean checkNoDifferenceAndNotify(DiffPanel diffPanel, DiffRequest data, final Window window, final boolean showMessage) { if (!diffPanel.hasDifferences() && !data.getHints().contains(HINT_ALLOW_NO_DIFFERENCES)) { DiffManagerImpl manager = (DiffManagerImpl) DiffManager.getInstance(); if (!Comparing.equal(manager.getComparisonPolicy(), ComparisonPolicy.DEFAULT)) { @@ -170,6 +171,9 @@ class FrameDiffTool implements DiffTool { if (hasDiffs) return false; } + if (! showMessage) { + return true; + } return !askForceOpenDiff(data); } return false; @@ -208,6 +212,6 @@ class FrameDiffTool implements DiffTool { @Override public DiffViewer createComponent(String title, DiffRequest request, Window window, Disposable parentDisposable) { - return createDiffPanelIfShouldShow(request, window, parentDisposable); + return createDiffPanelIfShouldShow(request, window, parentDisposable, false); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java new file mode 100644 index 000000000000..bb88c68dabf1 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHeaderComponent.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.editor.impl; + +import com.intellij.util.ui.UIUtil; + +import javax.swing.*; +import java.awt.*; + +/** + * @author gregsh + */ +public class EditorHeaderComponent extends JPanel { + private final Color GRADIENT_C1; + private final Color GRADIENT_C2; + + public EditorHeaderComponent() { + super(new BorderLayout(0, 0)); + GRADIENT_C1 = getBackground(); + GRADIENT_C2 = new Color(Math.max(0, GRADIENT_C1.getRed() - 0x18), Math.max(0, GRADIENT_C1.getGreen() - 0x18), + Math.max(0, GRADIENT_C1.getBlue() - 0x18)); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + final Graphics2D g2d = (Graphics2D)g; + + if (!UIUtil.isUnderGTKLookAndFeel()) { + g2d.setPaint(new GradientPaint(0, 0, GRADIENT_C1, 0, getHeight(), GRADIENT_C2)); + g2d.fillRect(1, 1, getWidth(), getHeight() - 1); + g2d.setPaint(null); + } + + g.setColor(UIUtil.getBorderColor()); + g.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 2bcdcec7613c..2bf69073673f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -127,6 +127,7 @@ import java.util.concurrent.TimeUnit; public final class EditorImpl extends UserDataHolderBase implements EditorEx, HighlighterClient, Queryable { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorImpl"); private static final Key DND_COMMAND_KEY = Key.create("DndCommand"); + public static final Key PERMANENT_HEADER = Key.create("PERMANENT_HEADER"); public static final Key DO_DOCUMENT_UPDATE_TEST = Key.create("DoDocumentUpdateTest"); public static final Key> EDITABLE_AREA_MARKER = Key.create("editable.area.marker"); private static final boolean HONOR_CAMEL_HUMPS_ON_TRIPLE_CLICK @@ -1682,6 +1683,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi graphics.setClip(rect.x, rect.y, rect.width, rect.height); paint(graphics); graphics.translate(rect.x, rect.y); + graphics.dispose(); putUserData(BUFFER, image); } @@ -1767,6 +1769,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi @Override public void setHeaderComponent(JComponent header) { myHeaderPanel.removeAll(); + header = header == null? getUserData(PERMANENT_HEADER) : header; if (header != null) { myHeaderPanel.add(header); } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java index b24815f3f014..a62d87b8f6da 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorTabbedContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.*; import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; +import com.intellij.ui.InplaceButton; import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.docking.DockManager; import com.intellij.ui.docking.DockableContent; @@ -474,6 +475,8 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget } private class TabMouseListener extends MouseAdapter { + private int myActionClickCount; + @Override public void mousePressed(final MouseEvent e) { if (UIUtil.isCloseClick(e, MouseEvent.MOUSE_PRESSED)) { @@ -485,9 +488,19 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget } } - if (UIUtil.isActionClick(e) && (e.getClickCount() % 2) == 0 && !isFloating()) { - final ActionManager mgr = ActionManager.getInstance(); - mgr.tryToExecute(mgr.getAction("HideAllWindows"), e, null, ActionPlaces.UNKNOWN, true); + if (UIUtil.isActionClick(e)) { + if (e.getClickCount() == 1) { + myActionClickCount = 0; + } + // clicks on the close window button don't count in determining whether we have a double-click on tab (IDEA-70403) + final Component deepestComponent = SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY()); + if (!(deepestComponent instanceof InplaceButton)) { + myActionClickCount++; + } + if (myActionClickCount == 2 && !isFloating()) { + final ActionManager mgr = ActionManager.getInstance(); + mgr.tryToExecute(mgr.getAction("HideAllWindows"), e, null, ActionPlaces.UNKNOWN, true); + } } } @@ -585,6 +598,7 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget public void dragOutFinished(MouseEvent event, TabInfo source) { boolean copy = event.isMetaDown() || (!SystemInfo.isMac && event.isControlDown()); if (!copy) { + myFile.putUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN, Boolean.TRUE); FileEditorManagerEx.getInstanceEx(myProject).closeFile(myFile, myWindow); } else { @@ -592,6 +606,9 @@ final class EditorTabbedContainer implements Disposable, CloseAction.CloseTarget } mySession.process(event); + if (!copy) { + myFile.putUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN, null); + } myFile = null; mySession = null; diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java index 0f1e765f909b..7e39542cf1fc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -464,6 +464,7 @@ public class EditorWindow { return myPanel.getSize(); } + @Nullable public EditorTabbedContainer getTabbedPane() { return myTabbedPane; } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 96dcc2ca08ae..3d9fb9834528 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -96,6 +96,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private static final FileEditor[] EMPTY_EDITOR_ARRAY = {}; private static final FileEditorProvider[] EMPTY_PROVIDER_ARRAY = {}; + public static final Key CLOSING_TO_REOPEN = Key.create("CLOSING_TO_REOPEN"); private volatile JPanel myPanels; private EditorsSplitters mySplitters; diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 8d3c6c24b150..5280652f8858 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,7 +71,6 @@ import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; - public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { private static final Logger LOG = Logger.getInstance("#com.intellij.project.impl.ProjectImpl"); private static final String PLUGIN_SETTINGS_ERROR = "Plugin Settings Error"; @@ -103,10 +102,14 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { myOptimiseTestLoadSpeed = isOptimiseTestLoadSpeed; myManager = manager; + myName = isDefault() ? TEMPLATE_PROJECT_NAME : projectName == null ? getStateStore().getProjectName() : projectName; - if (!isDefault() && projectName != null && getStateStore().getStorageScheme().equals(StorageScheme.DIRECTORY_BASED)) myOldName = ""; // new project + if (!isDefault() && projectName != null && getStateStore().getStorageScheme().equals(StorageScheme.DIRECTORY_BASED)) { + myOldName = ""; // new project + } } + @Override public void setProjectName(@NotNull String projectName) { if (!projectName.equals(myName)) { myOldName = myName; @@ -175,6 +178,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } @NotNull + @Override public synchronized IProjectStore getStateStore() { if (myComponentStore == null) { myComponentStore = (IProjectStore)getPicoContainer().getComponentInstance(IComponentStore.class); @@ -196,10 +200,12 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { getStateStore().initComponent(component, service); } + @Override public boolean isOpen() { return ProjectManagerEx.getInstanceEx().isProjectOpened(this); } + @Override public boolean isInitialized() { return isOpen() && !isDisposed() && StartupManagerEx.getInstanceEx(this).startupActivityPassed(); } @@ -217,40 +223,49 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return getStateStore().getProjectFilePath(); } - - @Nullable + @Override public VirtualFile getProjectFile() { return getStateStore().getProjectFile(); } - @Nullable + @Override public VirtualFile getBaseDir() { return getStateStore().getProjectBaseDir(); } + @Override + public String getBasePath() { + return getStateStore().getProjectBasePath(); + } + @NotNull + @Override public String getName() { return myName; } - @Nullable @NonNls + @Override public String getPresentableUrl() { + if (myName == null) return null; // not yet initialized return getStateStore().getPresentableUrl(); } @NotNull @NonNls + @Override public String getLocationHash() { String str = getPresentableUrl(); if (str == null) str = getName(); - final String prefix = getStateStore().getStorageScheme() == StorageScheme.DIRECTORY_BASED? "" : getName(); + final String prefix = getStateStore().getStorageScheme() == StorageScheme.DIRECTORY_BASED ? "" : getName(); return prefix + Integer.toHexString(str.hashCode()); } + @SuppressWarnings("deprecation") @Nullable @NonNls + @Override public String getLocation() { if (myName == null) return null; // was called before initialized return isDisposed() ? null : getStateStore().getLocation(); @@ -261,15 +276,17 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return getStateStore().getWorkspaceFile(); } + @Override public boolean isOptimiseTestLoadSpeed() { return myOptimiseTestLoadSpeed; } + @Override public void setOptimiseTestLoadSpeed(final boolean optimiseTestLoadSpeed) { myOptimiseTestLoadSpeed = optimiseTestLoadSpeed; } - + @Override public void init() { long start = System.currentTimeMillis(); // ProfilingUtil.startCPUProfiling(); @@ -297,6 +314,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return false; } + @Override public void save() { if (ApplicationManagerEx.getApplicationEx().isDoNotSave()) return; //no need to save @@ -327,11 +345,14 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } catch (PluginException e) { PluginManager.disablePlugin(e.getPluginId().getIdString()); - Notifications.Bus.notify(new Notification(PLUGIN_SETTINGS_ERROR, "Unable to save plugin settings!", - "

The plugin " + e.getPluginId() + " failed to save settings and has been disabled. Please restart" + - ApplicationNamesInfo.getInstance().getFullProductName() + "

" + - (ApplicationManagerEx.getApplicationEx().isInternal() ? "

" + StringUtil.getThrowableText(e) + "

": ""), - NotificationType.ERROR), NotificationDisplayType.BALLOON, this); + Notification notification = new Notification( + PLUGIN_SETTINGS_ERROR, + "Unable to save plugin settings!", + "

The plugin " + e.getPluginId() + " failed to save settings and has been disabled. Please restart" + + ApplicationNamesInfo.getInstance().getFullProductName() + "

" + + (ApplicationManagerEx.getApplicationEx().isInternal() ? "

" + StringUtil.getThrowableText(e) + "

" : ""), + NotificationType.ERROR); + Notifications.Bus.notify(notification, this); LOG.info("Unable to save plugin settings",e); } catch (IOException e) { @@ -344,6 +365,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } } + @Override public synchronized void dispose() { ApplicationEx application = ApplicationManagerEx.getApplicationEx(); assert application.isWriteAccessAllowed(); // dispose must be under write action @@ -382,7 +404,6 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } } } - private void projectClosed() { List components = new ArrayList(Arrays.asList(getComponents(ProjectComponent.class))); @@ -397,6 +418,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } } + @Override public T[] getExtensions(final ExtensionPointName extensionPointName) { return Extensions.getArea(this).getExtensionPoint(extensionPointName).getExtensions(); } @@ -423,10 +445,12 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return Extensions.getArea(this).getPicoContainer(); } + @Override public boolean isDefault() { return false; } + @Override public void checkUnknownMacros(final boolean showDialog) { final IProjectStore stateStore = getStateStore(); @@ -472,7 +496,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { }); } else { - if (Messages.showYesNoDialog(this, "Component could not be reloaded. Reload project?", "Configuration changed", + if (Messages.showYesNoDialog(this, "Component could not be reloaded. Reload project?", "Configuration Changed", Messages.getQuestionIcon()) == 0) { ProjectManagerEx.getInstanceEx().reloadProject(this); } @@ -483,13 +507,12 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { } @Override - public String toString() { - return "Project" - + (isDisposed() ? " (Disposed" + (temporarilyDisposed ? " temporarily" : "") + ")" - :isDefault() ? "" : " '" + getLocation()+"'") - + (isDefault() ? " (Default)" : "") - + " " + myName - ; + public String toString() { + return "Project" + + (isDisposed() ? " (Disposed" + (temporarilyDisposed ? " temporarily" : "") + ")" + : isDefault() ? "" : " '" + getPresentableUrl() + "'") + + (isDefault() ? " (Default)" : "") + + " " + myName; } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index faf376e92bd1..d957eca4d645 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -918,7 +918,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt ProjectImpl projectImpl = (ProjectImpl)project[0]; if (projectImpl.isDisposed()) return; IProjectStore projectStore = projectImpl.getStateStore(); - final String location = projectImpl.getLocation(); + final String location = projectImpl.getPresentableUrl(); final List original; try { diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java index e4d4b75d5fb6..72f32c0bfe90 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java @@ -335,6 +335,11 @@ public class DialogWrapperPeerImpl extends DialogWrapperPeer implements FocusTra myDialog.setModal(modal); } + @Override + public boolean isModal() { + return myDialog.isModal(); + } + public boolean isVisible() { return myDialog.isVisible(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java index b5eca8b1f0e4..e63593116543 100644 --- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java +++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java @@ -219,6 +219,11 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc LOG.assertTrue(modal, "Can't be non modal!"); } + @Override + public boolean isModal() { + return true; + } + public boolean isVisible() { return myDialog != null && myDialog.isVisible(); } 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 e28e5e496034..d5d81f96374e 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 @@ -222,6 +222,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { String childPath = child.getPath(); if (child.getFileSystem() == JarFileSystem.getInstance()) { VirtualFile local = JarFileSystem.getInstance().getVirtualFileForJar(child); + assert local != null : child; childPath = local.getPath(); } if (FileUtil.startsWith(childPath, root)) { @@ -238,13 +239,14 @@ 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: " + allowed; } } } } // null means we were unable to get roots, so do not check access + @Nullable private static Set allowedRoots() { if (insideGettingRoots) return null; Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); @@ -257,8 +259,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { String output = new File(outUrl.toURI()).getParentFile().getParentFile().getPath(); allowed.add(FileUtil.toSystemIndependentName(output)); } - catch (URISyntaxException ignored) { - } + catch (URISyntaxException ignored) { } String javaHome = SystemProperties.getJavaHome(); allowed.add(FileUtil.toSystemIndependentName(javaHome)); String tempDirectorySpecific = new File(FileUtil.getTempDirectory()).getParent(); @@ -277,7 +278,8 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { for (VirtualFile root : getAllRoots(project)) { allowed.add(StringUtil.trimEnd(root.getPath(), JarFileSystem.JAR_SEPARATOR)); } - String location = project.getLocation(); + String location = project.getBasePath(); + assert location != null : project; allowed.add(FileUtil.toSystemIndependentName(location)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FrameTitleBuilder.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FrameTitleBuilder.java index ce0250378b27..3432f48dbe73 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FrameTitleBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FrameTitleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.intellij.openapi.wm.impl; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; /** * @author yole @@ -27,7 +28,7 @@ public abstract class FrameTitleBuilder { return ServiceManager.getService(FrameTitleBuilder.class); } - public abstract String getFileTitle(final Project project, final VirtualFile file); + public abstract String getProjectTitle(@NotNull final Project project); - public abstract String getProjectTitle(final Project project); + public abstract String getFileTitle(@NotNull final Project project, @NotNull final VirtualFile file); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index 76422cc6e8e1..ddb0d4f6ad93 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,7 +256,7 @@ public class IdeFrameImpl extends JFrame implements IdeFrame, DataProvider { myUpdatingTitle = false; } } - + private static final class Builder { public StringBuilder sb = new StringBuilder(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java index 4a7ba3d5b456..236132d35c8e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java @@ -49,6 +49,7 @@ public class IdeMenuBar extends JMenuBar { private final DataManager myDataManager; private final ActionManagerEx myActionManager; private final Disposable myDisposable = Disposer.newDisposable(); + private boolean DISABLED = false; public IdeMenuBar(ActionManagerEx actionManager, DataManager dataManager) { myActionManager = actionManager; @@ -91,7 +92,9 @@ public class IdeMenuBar extends JMenuBar { myNewVisibleActions.clear(); final DataContext dataContext = ((DataManagerImpl)myDataManager).getDataContextTest(this); - expandActionGroup(dataContext, myNewVisibleActions, myActionManager); + if (!DISABLED) { + expandActionGroup(dataContext, myNewVisibleActions, myActionManager); + } if (!myNewVisibleActions.equals(myVisibleActions)) { // should rebuild UI @@ -165,6 +168,16 @@ public class IdeMenuBar extends JMenuBar { } } + public void disableUpdates() { + DISABLED = true; + updateMenuActions(); + } + + public void enableUpdates() { + DISABLED = false; + updateMenuActions(); + } + private final class MyTimerListener implements TimerListener { @Override public ModalityState getModalityState() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/PlatformFrameTitleBuilder.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/PlatformFrameTitleBuilder.java index cf824c6cf6f6..7f91b64d9cdf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/PlatformFrameTitleBuilder.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/PlatformFrameTitleBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,38 +21,45 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFilePathWrapper; import com.intellij.platform.ProjectBaseDirectory; +import org.jetbrains.annotations.NotNull; /** * @author yole */ public class PlatformFrameTitleBuilder extends FrameTitleBuilder { - public String getProjectTitle(final Project project) { - final VirtualFile baseDir = project.getBaseDir(); - if (baseDir != null) { - if (SystemInfo.isMac && baseDir.getName().equals(project.getName())) { - return "[" + FileUtil.getLocationRelativeToUserHome(baseDir.getPresentableUrl()) + "]"; - } - - return project.getName() + " - [" + FileUtil.getLocationRelativeToUserHome(baseDir.getPresentableUrl()) + "]"; + @Override + public String getProjectTitle(@NotNull final Project project) { + final String basePath = project.getBasePath(); + if (basePath == null) return project.getName(); + + if (basePath.equals(project.getName())) { + return "[" + FileUtil.getLocationRelativeToUserHome(basePath) + "]"; + } + else { + return project.getName() + " - [" + FileUtil.getLocationRelativeToUserHome(basePath) + "]"; } - return project.getName(); } - public String getFileTitle(final Project project, final VirtualFile file) { + @Override + public String getFileTitle(@NotNull final Project project, @NotNull final VirtualFile file) { if (SystemInfo.isMac) return file.getName(); if (file instanceof VirtualFilePathWrapper) { return ((VirtualFilePathWrapper)file).getPresentablePath(); } + String url = FileUtil.getLocationRelativeToUserHome(file.getPresentableUrl()); + if (url == null) url = file.getPresentableUrl(); + VirtualFile baseDir = ProjectBaseDirectory.getInstance(project).getBaseDir(); if (baseDir == null) baseDir = project.getBaseDir(); + if (baseDir != null) { - //noinspection ConstantConditions final String projectHomeUrl = FileUtil.getLocationRelativeToUserHome(baseDir.getPresentableUrl()); - if (url.startsWith(projectHomeUrl)) { + if (projectHomeUrl != null && url.startsWith(projectHomeUrl)) { url = "..." + url.substring(projectHomeUrl.length()); } } + return url; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java index 60ce09d2c921..997e85a14001 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowAction.java @@ -90,7 +90,7 @@ public class ProjectWindowAction extends ToggleAction implements DumbAware { public Frame findProjectFrame() { final Project[] projects = ProjectManager.getInstance().getOpenProjects(); for (Project project : projects) { - if (myProjectLocation.equals(project.getLocation())) { + if (myProjectLocation.equals(project.getPresentableUrl())) { final WindowManager windowManager = WindowManager.getInstance(); return windowManager.getFrame(project); } @@ -104,7 +104,7 @@ public class ProjectWindowAction extends ToggleAction implements DumbAware { if (project == null) { return false; } - return myProjectLocation.equals(project.getLocation()); + return myProjectLocation.equals(project.getPresentableUrl()); } public void setSelected(@Nullable AnActionEvent e, boolean selected) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowActionGroup.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowActionGroup.java index 4c8bc785c276..341d28d166dc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowActionGroup.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ProjectWindowActionGroup.java @@ -36,7 +36,7 @@ public class ProjectWindowActionGroup extends DefaultActionGroup { private ProjectWindowAction latest = null; public void addProject(@NotNull Project project) { - final String projectLocation = project.getLocation(); + final String projectLocation = project.getPresentableUrl(); if (projectLocation == null) { return; } @@ -56,7 +56,7 @@ public class ProjectWindowActionGroup extends DefaultActionGroup { } public void removeProject(@NotNull Project project) { - final ProjectWindowAction windowAction = findWindowAction(project.getLocation()); + final ProjectWindowAction windowAction = findWindowAction(project.getPresentableUrl()); if (windowAction == null) { return; } @@ -91,7 +91,7 @@ public class ProjectWindowActionGroup extends DefaultActionGroup { if (project == null) { return; } - final ProjectWindowAction windowAction = findWindowAction(project.getLocation()); + final ProjectWindowAction windowAction = findWindowAction(project.getPresentableUrl()); if (windowAction == null) { return; } @@ -106,7 +106,7 @@ public class ProjectWindowActionGroup extends DefaultActionGroup { if (project == null) { return; } - final ProjectWindowAction windowAction = findWindowAction(project.getLocation()); + final ProjectWindowAction windowAction = findWindowAction(project.getPresentableUrl()); if (windowAction == null) { return; } @@ -144,7 +144,7 @@ public class ProjectWindowActionGroup extends DefaultActionGroup { final ProjectWindowAction windowAction = (ProjectWindowAction) child; if (projectName.equals(windowAction.getProjectName())) { if (result == null) { - result = new ArrayList(); + result = new ArrayList(); } result.add(windowAction); } diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java index de80c1b6561b..8a19a00ae88e 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java @@ -22,6 +22,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.wm.IdeFrame; +import com.intellij.openapi.wm.impl.IdeMenuBar; import com.intellij.ui.mac.foundation.Foundation; import com.intellij.ui.mac.foundation.ID; import com.intellij.ui.mac.foundation.MacUtil; @@ -83,6 +85,14 @@ public class MacFileChooserDialogImpl implements PathChooserDialog { processResult(returnCode, openPanelDidEnd); try { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + IdeMenuBar bar = getMenuBar(); + if (bar != null) { + bar.enableUpdates(); + } + } + }); if (myResultPaths != null) { final List paths = myResultPaths; final Consumer> callback = myCallback; @@ -192,24 +202,23 @@ public class MacFileChooserDialogImpl implements PathChooserDialog { } static { - final ID delegateClass = Foundation.allocateObjcClassPair(Foundation.getObjcClass("NSObject"), "NSOpenPanelDelegate_"); - if (!Foundation.addMethod(delegateClass, Foundation.createSelector("panel:shouldShowFilename:"), SHOULD_SHOW_FILENAME_CALLBACK, "B*")) { + final ID delegate = Foundation.allocateObjcClassPair(Foundation.getObjcClass("NSObject"), "NSOpenPanelDelegate_"); + if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:shouldShowFilename:"), SHOULD_SHOW_FILENAME_CALLBACK, "B*")) { throw new RuntimeException("Unable to add method to objective-c delegate class!"); } - if (!Foundation.addMethod(delegateClass, Foundation.createSelector("panel:isValidFilename:"), IS_VALID_FILENAME_CALLBACK, "B*")) { + if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:isValidFilename:"), IS_VALID_FILENAME_CALLBACK, "B*")) { throw new RuntimeException("Unable to add method to objective-c delegate class!"); } - if (!Foundation.addMethod(delegateClass, Foundation.createSelector("showOpenPanel:"), MAIN_THREAD_RUNNABLE, "v*")) { + if (!Foundation.addMethod(delegate, Foundation.createSelector("showOpenPanel:"), MAIN_THREAD_RUNNABLE, "v*")) { throw new RuntimeException("Unable to add method to objective-c delegate class!"); } - if (!Foundation.addMethod(delegateClass, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), OPEN_PANEL_DID_END, - "v*i")) { + if (!Foundation.addMethod(delegate, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), OPEN_PANEL_DID_END, "v*i")) { throw new RuntimeException("Unable to add method to objective-c delegate class!"); } - if (!Foundation.addMethod(delegateClass, Foundation.createSelector("panel:shouldEnableURL:"), SHOULD_ENABLE_URL, "B@@")) { + if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:shouldEnableURL:"), SHOULD_ENABLE_URL, "B@@")) { throw new RuntimeException("Unable to add method to objective-c delegate class!"); } - Foundation.registerObjcClassPair(delegateClass); + Foundation.registerObjcClassPair(delegate); } public MacFileChooserDialogImpl(@NotNull FileChooserDescriptor chooserDescriptor, Project project) { @@ -232,7 +241,28 @@ public class MacFileChooserDialogImpl implements PathChooserDialog { }); } + @Nullable + private static IdeMenuBar getMenuBar() { + Window cur = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + + while (cur != null) { + if (cur instanceof JFrame) { + JMenuBar menuBar = ((JFrame)cur).getJMenuBar(); + if (menuBar instanceof IdeMenuBar) { + return (IdeMenuBar)menuBar; + } + } + cur = cur.getOwner(); + } + return null; + } + private static void showNativeChooserAsSheet(@Nullable String toSelect) { + IdeMenuBar bar = getMenuBar(); + if (bar != null) { + bar.disableUpdates(); + } + final ID autoReleasePool = createAutoReleasePool(); try { final ID delegate = invoke(Foundation.getObjcClass("NSOpenPanelDelegate_"), "new"); diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java index 723e80e7b28d..a0d5dba83e32 100644 --- a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java @@ -85,6 +85,7 @@ public class MacMessagesImpl extends MacMessages { int defaultOptionIndex = Integer.parseInt(toStringViaUTF8(invoke(params, "objectAtIndex:", 6))); int focusedOptionIndex = Integer.parseInt(toStringViaUTF8(invoke(params, "objectAtIndex:", 7))); ID buttons = invoke(params, "objectAtIndex:", 8); + ID doNotAskChecked = invoke(params, "objectAtIndex:", 9); ID alert = invoke(invoke("NSAlert", "alloc"), "init"); @@ -121,6 +122,7 @@ public class MacMessagesImpl extends MacMessages { if (!"-1".equals(doNotAsk)) { invoke(alert, "setShowsSuppressionButton:", 1); invoke(invoke(alert, "suppressionButton"), "setTitle:", doNotAskText); + invoke(invoke(alert, "suppressionButton"), "setState:", "checked".equals(toStringViaUTF8(doNotAskChecked))); } invoke(alert, "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:", focusedWindow, self, @@ -139,6 +141,7 @@ public class MacMessagesImpl extends MacMessages { ID fakeId = invoke(params, "objectAtIndex:", 6); ID alertStyle = invoke(params, "objectAtIndex:", 7); ID doNotAskText = invoke(params, "objectAtIndex:", 8); + ID doNotAskChecked = invoke(params, "objectAtIndex:", 9); boolean alternateExist = !"-1".equals(toStringViaUTF8(alternateText)); boolean otherExist = !"-1".equals(toStringViaUTF8(otherText)); @@ -165,6 +168,7 @@ public class MacMessagesImpl extends MacMessages { if (!"-1".equals(doNotAsk)) { invoke(alert, "setShowsSuppressionButton:", 1); invoke(invoke(alert, "suppressionButton"), "setTitle:", doNotAskText); + invoke(invoke(alert, "suppressionButton"), "setState:", "checked".equals(toStringViaUTF8(doNotAskChecked))); } invoke(alert, "beginSheetModalForWindow:modalDelegate:didEndSelector:contextInfo:", focusedWindow, self, @@ -277,7 +281,8 @@ public class MacMessagesImpl extends MacMessages { ? "-1" : doNotAskDialogOption.getDoNotShowMessage()), nsString(Integer.toString(defaultOptionIndex)), - nsString(Integer.toString(focusedOptionIndex)), buttonsArray, null); + nsString(Integer.toString(focusedOptionIndex)), buttonsArray, + nsString(doNotAskDialogOption != null && !doNotAskDialogOption.isToBeShown() ? "checked" : "-1"), null); IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false); @@ -438,7 +443,8 @@ public class MacMessagesImpl extends MacMessages { nsString(doNotAskDialogOption == null || !doNotAskDialogOption.canBeHidden() // TODO: state=!doNotAsk.shouldBeShown() ? "-1" - : doNotAskDialogOption.getDoNotShowMessage()), null); + : doNotAskDialogOption.getDoNotShowMessage()), + nsString(doNotAskDialogOption != null && !doNotAskDialogOption.isToBeShown() ? "checked" : "-1"), null); IdeFocusManager.getGlobalInstance().setTypeaheadEnabled(false); diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index a5150687296c..33cb7db819ff 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -1309,3 +1309,6 @@ action.Images.ShowThumbnails.description=Show thumbnails view for current direct action.Diff.UpdatedFiles.text=Show Diff action.Diff.UpdatedFiles.description=Show diff with version before update + +action.TabList.text=Show All Tabs +action.TabList.description=Show dropdown with the list of all tabs in single-row tab layout diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index 96996b50611e..dbc4f8169baa 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -191,6 +191,7 @@ intention.error.cannot.create.class.title=Failed to Create Class intention.assign.field.from.parameter.text=Assign Parameter to Field ''{0}'' intention.assign.field.from.parameter.family=Assign Parameter to Field intention.create.field.from.parameter.text=Create Field For Parameter ''{0}'' +intention.create.fields.from.parameters.text=Create Fields For Constructor Parameters intention.create.field.from.parameter.family=Create Field for Parameter intention.implement.abstract.method.searching.for.descendants.progress=Searching For Descendants... intention.implement.abstract.method.error.no.classes.message=There are no classes found where this method can be implemented diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 0181271196aa..80a38b3927fe 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -67,7 +67,7 @@ invalid.data.dialog.title=Invalid Data template.settings.configurable.display.name=Template Settings default.run.configuration.name= -process.is.running.dialog.title=Process ''{0}'' is running +process.is.running.dialog.title=Process ''{0}'' Is Running button.disconnect=Disconnect button.terminate=Terminate disconnect.process.confirmation.text=Do you want to disconnect from the process ''{0}''? diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 77fc75407f13..d645042cb8df 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -708,7 +708,7 @@ prompt.select.module.file.to.import=Select {0} module file (.iml) to import message.module.file.has.an.older.format.do.you.want.to.convert.it=Module file has an older format. Do you want to convert it? dialog.title.convert.module=Convert Module error.message.cannot.modify.file.0=Cannot modify file ''{0}'' -message.your.module.was.succesfully.converted.br.old.version.was.saved.to.0=Your module was successfully converted.
\ +message.your.module.was.successfully.converted.br.old.version.was.saved.to.0=Your module was successfully converted.
\ Old version was saved to ''{0}'' label.select.module.type=Module type: error.please.specify.path.to.module.file=Please specify path to {0} module file (.iml) @@ -863,7 +863,7 @@ updates.no.updates.message=

You are using the latest version of $FULLNA updates.configure.label={0}
To configure automatic update settings, see the Updates dialog of your IDE settings updates.timeout.error=Connection timed out updates.download.and.install.patch.button=&Download Patch and Shutdown -updates.download.and.install.patch.button.restart=&Download Patch and Restart +updates.download.and.install.patch.button.restart=Up&date and Restart updates.more.info.button=&More Info... updates.new.version.available=

A new version of $FULLNAME$ is available.

updates.available.idea.version=New version: diff --git a/platform/platform-resources-en/src/tips/CloseOthers.html b/platform/platform-resources-en/src/tips/CloseOthers.html new file mode 100644 index 000000000000..ab5beb58f6e3 --- /dev/null +++ b/platform/platform-resources-en/src/tips/CloseOthers.html @@ -0,0 +1,15 @@ + + + + + +

+ There are two ways of closing all tabs in the editor, except the current one:

+
    +
  • First, right-click the editor tab, and choose Close Others on the context menu.
  • +
  • Second, keeping the Alt key pressed, click on the editor tab.
  • +
+

+

+ + diff --git a/platform/platform-resources-en/src/tips/images/close1.png b/platform/platform-resources-en/src/tips/images/close1.png new file mode 100644 index 000000000000..f26627085a0a Binary files /dev/null and b/platform/platform-resources-en/src/tips/images/close1.png differ diff --git a/platform/platform-resources-en/src/tips/images/close_others.png b/platform/platform-resources-en/src/tips/images/close_others.png new file mode 100644 index 000000000000..33d53a239446 Binary files /dev/null and b/platform/platform-resources-en/src/tips/images/close_others.png differ diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index d0f904632b35..ea6c38ec027d 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -320,6 +320,7 @@ + diff --git a/platform/testFramework/src/com/intellij/mock/MockProjectStore.java b/platform/testFramework/src/com/intellij/mock/MockProjectStore.java index 8efc9ba48ed6..af32d43cdc3b 100644 --- a/platform/testFramework/src/com/intellij/mock/MockProjectStore.java +++ b/platform/testFramework/src/com/intellij/mock/MockProjectStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,10 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.Collection; -import java.util.List; import java.util.Set; -import java.util.TreeSet; /** * @author peter @@ -64,10 +61,14 @@ public class MockProjectStore implements IProjectStore { } @Override - @Nullable public VirtualFile getProjectBaseDir() { throw new UnsupportedOperationException("Method getProjectBaseDir is not yet implemented in " + getClass().getName()); - }//------ This methods should be got rid of + } + + @Override + public String getProjectBasePath() { + throw new UnsupportedOperationException("Method getProjectBasePath is not yet implemented in " + getClass().getName()); + } @Override public String getLocation() { @@ -117,18 +118,7 @@ public class MockProjectStore implements IProjectStore { @Override @NotNull public String getProjectFilePath() { - return null; - } - - public void setUsedMacros(@NotNull Collection macros) { - } - - public Set getMacroTrackingSet() { - return new TreeSet(); - } - - public void initStore() { - throw new UnsupportedOperationException("Method initStore is not yet implemented in " + getClass().getName()); + throw new UnsupportedOperationException("Method getProjectFilePath is not yet implemented in " + getClass().getName()); } @Override @@ -149,20 +139,12 @@ public class MockProjectStore implements IProjectStore { throw new UnsupportedOperationException("Method load is not yet implemented in " + getClass().getName()); } - public Collection getUsedMacros() { - throw new UnsupportedOperationException("Method getUsedMacros not implemented in " + getClass()); - } - @Override @NotNull public SaveSession startSave() throws IOException { throw new UnsupportedOperationException("Method startSave not implemented in " + getClass()); } - public List getAllStorageFilesToSave(final boolean includingSubStructures) { - throw new UnsupportedOperationException("Method getAllStorageFilesToSave is not yet implemented in " + getClass().getName()); - } - @Override @Nullable public String getPresentableUrl() { diff --git a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java index 6c08399b0199..67bfa9c18dde 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import com.intellij.diagnostic.LogMessageEx; import com.intellij.diagnostic.errordialog.Attachment; import com.intellij.execution.ExecutionBundle; import com.intellij.execution.configurations.RuntimeConfiguration; -import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.TestFrameworkRunningModel; import com.intellij.ide.BrowserUtil; import com.intellij.openapi.actionSystem.ActionManager; @@ -28,7 +27,6 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.progress.PerformInBackgroundOption; @@ -142,12 +140,11 @@ public class ExportTestResultsAction extends DumbAwareAction { outputFolder = new File(config.getOutputFolder()); } else { - outputFolder = new File(new File(project.getLocation()), config.getOutputFolder()); + outputFolder = new File(new File(project.getBasePath()), config.getOutputFolder()); } } else { - outputFolder = new File(project.getLocation()); - + outputFolder = new File(project.getBasePath()); } final File outputFile = new File(outputFolder, filename_); final String outputText; diff --git a/platform/util/src/com/intellij/openapi/util/RecursionManager.java b/platform/util/src/com/intellij/openapi/util/RecursionManager.java index 080c6e143ae4..2551b46306c1 100644 --- a/platform/util/src/com/intellij/openapi/util/RecursionManager.java +++ b/platform/util/src/com/intellij/openapi/util/RecursionManager.java @@ -112,7 +112,14 @@ public class RecursionManager { return result; } finally { - stack.afterComputation(realKey, sizeBefore, sizeAfter); + try { + stack.afterComputation(realKey, sizeBefore, sizeAfter); + } + catch (Throwable e) { + throw new RuntimeException("Throwable in afterComputation", e); + } + + stack.checkDepth("4"); if (oldHash != realKey.hashCode()) { throw new AssertionError("Object has changed its hashCode: " + key); @@ -252,20 +259,21 @@ public class RecursionManager { if (depth == 0) { intermediateCache.clear(); - assert key2ReentrancyDuringItsCalculation.isEmpty() : "non-empty key2ReentrancyDuringItsCalculation"; - assert toMemoize.isEmpty() : "non-empty toMemoize"; + LOG.assertTrue(key2ReentrancyDuringItsCalculation.isEmpty(), "non-empty key2ReentrancyDuringItsCalculation"); + LOG.assertTrue(toMemoize.isEmpty(), "non-empty toMemoize"); } if (sizeBefore != progressMap.size()) { LOG.error("Map size doesn't decrease: " + progressMap.size() + " " + sizeBefore + " " + realKey.second); } - assert value != null : realKey.second + " has changed its equals/hashCode"; + if (value == null) { + LOG.error(realKey.second + " has changed its equals/hashCode"); + } reentrancyCount = value; checkZero(); - checkDepth("4"); } private void enableMemoization(MyKey realKey, Set loop) { @@ -283,7 +291,9 @@ public class RecursionManager { private Set prohibitResultCaching(MyKey realKey) { reentrancyCount++; - checkZero(); + if (!checkZero()) { + throw new AssertionError("zero1"); + } Set loop = new THashSet(); boolean inLoop = false; @@ -297,7 +307,9 @@ public class RecursionManager { } } - checkZero(); + if (!checkZero()) { + throw new AssertionError("zero2"); + } return loop; } @@ -309,10 +321,12 @@ public class RecursionManager { } } - private void checkZero() { + private boolean checkZero() { if (!progressMap.isEmpty() && !new Integer(0).equals(progressMap.get(progressMap.keySet().iterator().next()))) { - throw new AssertionError("Prisoner Zero has escaped: " + progressMap + "; value=" + progressMap.get(progressMap.keySet().iterator().next())); + LOG.error("Prisoner Zero has escaped: " + progressMap + "; value=" + progressMap.get(progressMap.keySet().iterator().next())); + return false; } + return true; } } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 2140094c72dc..e02187132e29 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -1287,20 +1287,18 @@ public class FileUtil { } @Nullable - public static String getLocationRelativeToUserHome(final String path) { + public static String getLocationRelativeToUserHome(@Nullable final String path) { if (path == null) return null; - String _path = path; - - if (SystemInfo.isLinux || SystemInfo.isMac) { + if (SystemInfo.isUnix) { final File projectDir = new File(path); final File userHomeDir = new File(SystemProperties.getUserHome()); if (isAncestor(userHomeDir, projectDir, true)) { - _path = "~/" + getRelativePath(userHomeDir, projectDir); + return "~/" + getRelativePath(userHomeDir, projectDir); } } - return _path; + return path; } public static boolean isHashBangLine(CharSequence firstCharsIfText, String marker) { diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 10f96efc3f06..c5694078cd8c 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -54,6 +54,18 @@ public class StringUtil { } }; + public static List getWordsInStringLongestFirst(String find) { + List words = getWordsIn(find); + // hope long words are rare + Collections.sort(words, new Comparator() { + @Override + public int compare(final String o1, final String o2) { + return o2.length() - o1.length(); + } + }); + return words; + } + @NotNull public static String escapePattern(final @NotNull String text) { return replace(replace(text, "'", "''"), "{", "'{'"); diff --git a/platform/util/src/com/intellij/util/BloomFilterBase.java b/platform/util/src/com/intellij/util/BloomFilterBase.java new file mode 100644 index 000000000000..6779ae273d2b --- /dev/null +++ b/platform/util/src/com/intellij/util/BloomFilterBase.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.util; + +public class BloomFilterBase { + private final int myHashFunctionCount; + private final int myBitsCount; + private final long[] myElementsSet; + private static final int BITS_PER_ELEMENT = 6; + + protected BloomFilterBase(int _maxElementCount, double probability) { + int bitsPerElementFactor = (int)Math.ceil(-Math.log(probability) / (Math.log(2) * Math.log(2))); + myHashFunctionCount = (int)Math.ceil(bitsPerElementFactor * Math.log(2)); + + int bitsCount = _maxElementCount * bitsPerElementFactor; + + if ((bitsCount & 1) == 0) ++bitsCount; + while(!isPrime(bitsCount)) bitsCount += 2; + myBitsCount = bitsCount; + myElementsSet = new long[(bitsCount >> BITS_PER_ELEMENT) + 1]; + } + + private static boolean isPrime(int bits) { + if ((bits & 1) == 0 || bits % 3 == 0) return false; + int sqrt = (int)Math.sqrt(bits); + for(int i = 6; i <= sqrt; i += 6) { + if (bits % (i - 1) == 0 || bits % (i + 1) == 0) return false; + } + return true; + } + + protected final void addIt(int prime, int prime2) { + for(int i = 0; i < myHashFunctionCount; ++i) { + int abs = Math.abs(i * prime + prime2 * (myHashFunctionCount - i)) % myBitsCount; + myElementsSet[abs >> BITS_PER_ELEMENT] |= (1L << abs); + } + } + + protected final boolean maybeContains(int prime, int prime2) { + for(int i = 0; i < myHashFunctionCount; ++i) { + int abs = Math.abs(i * prime + prime2 * (myHashFunctionCount - i)) % myBitsCount; + if ((myElementsSet[abs >> BITS_PER_ELEMENT] & (1L << abs)) == 0) return false; + } + + return true; + } +} diff --git a/platform/util/src/com/intellij/util/lang/ClasspathCache.java b/platform/util/src/com/intellij/util/lang/ClasspathCache.java index 658cda05f986..9acbbe87c104 100644 --- a/platform/util/src/com/intellij/util/lang/ClasspathCache.java +++ b/platform/util/src/com/intellij/util/lang/ClasspathCache.java @@ -21,6 +21,7 @@ package com.intellij.util.lang; import com.intellij.openapi.util.text.StringHash; import com.intellij.util.ArrayUtil; +import com.intellij.util.BloomFilterBase; import com.intellij.util.SmartList; import com.intellij.util.containers.HashMap; import gnu.trove.THashMap; @@ -30,7 +31,6 @@ import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.Nullable; import sun.misc.Resource; -import java.util.BitSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -44,7 +44,7 @@ public class ClasspathCache { private THashMap> myResources2LoadersTempMap = new THashMap>(); private static final double PROBABILITY = 0.005d; - private BloomFilter myNameFilter; + private Name2LoaderFilter myNameFilter; private boolean myTempMapMode = true; public ClasspathCache() { @@ -232,7 +232,7 @@ public class ClasspathCache { nBits += (int)(nBits * 0.03d); // allow some growth for Idea main loader } - myNameFilter = new BloomFilter(nBits, PROBABILITY); + myNameFilter = new Name2LoaderFilter(nBits, PROBABILITY); for(Map.Entry> e:myResources2LoadersTempMap.entrySet()) { final String name = e.getKey(); @@ -246,50 +246,25 @@ public class ClasspathCache { } } - static class BloomFilter { - private final int myHashFunctionCount; - private final int NBITS; - private final BitSet myResourceMap; + private static class Name2LoaderFilter extends BloomFilterBase { private static final int SEED = 31; - BloomFilter(int nBits, double probability) { - int bitsPerNameFactor = (int)Math.ceil(-Math.log(probability) / (Math.log(2) * Math.log(2))); - myHashFunctionCount = (int)Math.ceil(bitsPerNameFactor * Math.log(2)); - - nBits = nBits * bitsPerNameFactor; - - if ((nBits & 1) == 0) ++nBits; - while(!isPrime(nBits)) nBits += 2; - NBITS = nBits; - myResourceMap = new BitSet(NBITS); - } - - private static boolean isPrime(int bits) { - if ((bits & 1) == 0) return false; - int sqrt = (int)Math.sqrt(bits); - for(int i = 3; i <= sqrt; i+=2) { - if (bits % i == 0) return false; - } - return true; + Name2LoaderFilter(int nBits, double probability) { + super(nBits, probability); } private boolean maybeContains(String name, Loader loader) { int hash = hashFromNameAndLoader(name, loader, StringHash.murmur(name, SEED)); int hash2 = hashFromNameAndLoader(name, loader, hash); - for (int i = 0; i < myHashFunctionCount; ++i) { - if (!myResourceMap.get(Math.abs((hash + i * hash2) % NBITS))) return false; - } - return true; + return maybeContains(hash, hash2); } - public void add(String name, Loader loader) { - int hash1 = hashFromNameAndLoader(name, loader, StringHash.murmur(name, SEED)); - int hash2 = hashFromNameAndLoader(name, loader, hash1); + void add(String name, Loader loader) { + int hash = hashFromNameAndLoader(name, loader, StringHash.murmur(name, SEED)); + int hash2 = hashFromNameAndLoader(name, loader, hash); - for (int i = 0; i < myHashFunctionCount; ++i) { - myResourceMap.set(Math.abs((hash1 + i * hash2) % NBITS)); - } + addIt(hash, hash2); } private int hashFromNameAndLoader(String name, Loader loader, int n) { diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/SynchronizeDiff.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/SynchronizeDiff.java index cf61b6bed681..34fa766faaee 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/SynchronizeDiff.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/actions/SynchronizeDiff.java @@ -26,6 +26,8 @@ import com.intellij.openapi.util.SystemInfo; import java.util.List; +import static com.intellij.openapi.diff.impl.dir.DirDiffOperation.*; + /** * @author Konstantin Bulenkov */ @@ -48,7 +50,8 @@ public class SynchronizeDiff extends DirDiffAction { List elements = mySelectedOnly ? getModel().getSelectedElements() : getModel().getElements(); for (DirDiffElement dirDiffElement : elements) { if ((dirDiffElement.getSource() == null || dirDiffElement.getSource().isOperationsEnabled()) && - (dirDiffElement.getTarget() == null || dirDiffElement.getTarget().isOperationsEnabled())) { + (dirDiffElement.getTarget() == null || dirDiffElement.getTarget().isOperationsEnabled()) && + (dirDiffElement.getOperation() == COPY_FROM || dirDiffElement.getOperation() == COPY_TO || dirDiffElement.getOperation() == DELETE)) { e.getPresentation().setEnabled(true); return; } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java index 8cb62c17f356..369183eaf68b 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeForDiffConvertor.java @@ -18,6 +18,7 @@ package com.intellij.openapi.vcs.changes.actions; import com.intellij.openapi.diff.DiffRequest; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.FileStatus; @@ -68,6 +69,22 @@ public class ChangeForDiffConvertor implements Convertor 0 && + e.getPresentation().setEnabled(Boolean.TRUE.equals(haveSelectedChanges) && ((changeLists == null || changeLists.length == 1)) || (presetMessage != null)); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java index 2b3edd9df215..6aa22ca8b07d 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesTreeBrowser.java @@ -369,6 +369,9 @@ public class CommittedChangesTreeBrowser extends JPanel implements TypeSafeDataP if (key.equals(VcsDataKeys.CHANGES)) { final Collection changes = collectChanges(getSelectedChangeLists(), false); sink.put(VcsDataKeys.CHANGES, changes.toArray(new Change[changes.size()])); + } else if (key.equals(VcsDataKeys.HAVE_SELECTED_CHANGES)) { + final int count = myChangesTree.getSelectionCount(); + sink.put(VcsDataKeys.HAVE_SELECTED_CHANGES, count > 0 ? Boolean.TRUE : Boolean.FALSE); } else if (key.equals(VcsDataKeys.CHANGES_WITH_MOVED_CHILDREN)) { final Collection changes = collectChanges(getSelectedChangeLists(), true); diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java index b255a8a7f856..cb6c61738945 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesBrowser.java @@ -292,7 +292,7 @@ public class ChangesBrowser extends JPanel implements TypeSafeDataProvider { } public void actionPerformed(AnActionEvent e) { - showDiff(); + showDiff(); // todo here } }; myDiffAction.registerCustomShortcutSet(CommonShortcuts.getDiff(), myViewer); diff --git a/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetAction.java b/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetAction.java index 9f6e9e7c7ab2..e7c1e3528bf9 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetAction.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/actions/TargetAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,7 +41,9 @@ public final class TargetAction extends AnAction { templatePresentation.setDescription(description); myBuildName = buildFile.getPresentableName(); myTargets = targets; - myDebugString = "Target action: " + displayName+ "; Build: " + buildFile.getPresentableName() + "; Project: " + buildFile.getProject().getLocation(); + myDebugString = "Target action: " + displayName + + "; Build: " + buildFile.getPresentableName() + + "; Project: " + buildFile.getProject().getPresentableUrl(); } public String toString() { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/ExecutionHandler.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/ExecutionHandler.java index 77e9bd77b1ad..25d4c498804f 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/execution/ExecutionHandler.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/ExecutionHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,6 +46,7 @@ import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.openapi.wm.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.concurrent.TimeUnit; @@ -63,7 +64,7 @@ public final class ExecutionHandler { */ public static void runBuild(final AntBuildFileBase buildFile, String[] targets, - final AntBuildMessageView buildMessageViewToReuse, + @Nullable final AntBuildMessageView buildMessageViewToReuse, final DataContext dataContext, List additionalProperties, @NotNull final AntBuildListener antBuildListener) { FileDocumentManager.getInstance().saveAllDocuments(); @@ -223,7 +224,7 @@ public final class ExecutionHandler { } } - private static AntBuildMessageView prepareMessageView(AntBuildMessageView buildMessageViewToReuse, + private static AntBuildMessageView prepareMessageView(@Nullable AntBuildMessageView buildMessageViewToReuse, AntBuildFileBase buildFile, String[] targets) throws RunCanceledException { AntBuildMessageView messageView; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java index 55a8f20a93e5..cb283209ff19 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyNoVariantsDelegator.java @@ -23,6 +23,7 @@ import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiType; +import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; @@ -135,6 +136,11 @@ public class GroovyNoVariantsDelegator extends NoVariantsDelegator { } } + for (PsiClass aClass : PsiShortNamesCache.getInstance(qualifier.getProject()).getClassesByName(referenceName, qualifier.getResolveScope())) { + variants.add(GroovyCompletionUtil.createClassLookupItem(aClass)); + } + + if (variants.isEmpty()) { GroovyCompletionContributor.addAllClasses(parameters, new Consumer() { @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/GroovyUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/GroovyUtils.java index a5a6b8d38c20..9fb54c52b881 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/GroovyUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/GroovyUtils.java @@ -16,12 +16,12 @@ package org.jetbrains.plugins.groovy.util; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PluginPathManager; import com.intellij.openapi.module.JavaModuleType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; +import com.intellij.util.PathUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.config.GroovyConfigUtils; @@ -86,7 +86,7 @@ public abstract class GroovyUtils { } public static File getBundledGroovyJar() { - String root = ApplicationManager.getApplication().isUnitTestMode() ? + String root = new File(PathUtil.getJarPathForClass(GroovyUtils.class)).isDirectory() ? PluginPathManager.getPluginHomePath("groovy") + "/../../lib/" : PathManager.getHomePath() + "/lib/"; final File[] groovyJars = getFilesInDirectoryByPattern(root, GroovyConfigUtils.GROOVY_ALL_JAR_PATTERN); assert groovyJars.length == 1; diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/english.dic b/plugins/spellchecker/src/com/intellij/spellchecker/english.dic index e5e1f75b4c06..8e1321bb6ff0 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/english.dic +++ b/plugins/spellchecker/src/com/intellij/spellchecker/english.dic @@ -134293,6 +134293,8 @@ versifying versing version version's +versional +versioned versions verso verso's diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java index 8c91cb2a524e..be92910bdbc0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/actions/AbstractShowPropertiesDiffAction.java @@ -280,7 +280,7 @@ public abstract class AbstractShowPropertiesDiffAction extends AnAction implemen final ISVNPropertyHandler propertyHandler = createHandler(revision, lines); - client.doGetProperty(url, null, revision, revision, SVNDepth.EMPTY, propertyHandler); + client.doGetProperty(url, null, SVNRevision.UNDEFINED, revision, SVNDepth.EMPTY, propertyHandler); Collections.sort(lines, new Comparator() { public int compare(final SVNPropertyData o1, final SVNPropertyData o2) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java index eba00c54ea7a..3a4040912748 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnChangeList.java @@ -474,12 +474,12 @@ public class SvnChangeList implements CommittedChangeList { } final FilePath filePath = ChangesUtil.getFilePath(change); - final SimpleContentRevision before = createRevisionForProperty(wasUrl, change.getBeforeRevision(), filePath); - final SimpleContentRevision after = createRevisionForProperty(becameUrl, change.getAfterRevision(), filePath); - final String beforeText = before == null ? null : before.getContent(); - final String afterText = after == null ? null : after.getContent(); - if (Comparing.equal(beforeText, afterText) || StringUtil.isEmptyOrSpaces(beforeText) && StringUtil.isEmptyOrSpaces(afterText)) return; - final Change additional = new Change(before, after); + final Change additional = new Change(change.getBeforeRevision() == null ? null : + new SvnLazyPropertyContentRevision(filePath, change.getBeforeRevision().getRevisionNumber(), + myVcs.getProject(), wasUrl), + change.getAfterRevision() == null ? null : + new SvnLazyPropertyContentRevision(filePath, change.getAfterRevision().getRevisionNumber(), + myVcs.getProject(), becameUrl)); change.addAdditionalLayerElement(SvnChangeProvider.PROPERTY_LAYER, additional); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnLazyPropertyContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnLazyPropertyContentRevision.java new file mode 100644 index 000000000000..b522963616aa --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn17/history/SvnLazyPropertyContentRevision.java @@ -0,0 +1,89 @@ +/* + * Copyright 2000-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn17.history; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.ContentRevision; +import com.intellij.openapi.vcs.changes.SimpleContentRevision; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn17.SvnRevisionNumber; +import org.jetbrains.idea.svn17.SvnVcs17; +import org.jetbrains.idea.svn17.actions.AbstractShowPropertiesDiffAction; +import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNWCClient; + +/** + * Created with IntelliJ IDEA. + * User: Irina.Chernushina + * Date: 2/22/12 + * Time: 10:28 AM + */ +public class SvnLazyPropertyContentRevision implements ContentRevision { + private final FilePath myPath; + private final VcsRevisionNumber myNumber; + private final Project myProject; + private final SVNURL myUrl; + private String myContent; + + public SvnLazyPropertyContentRevision(FilePath path, VcsRevisionNumber number, Project project, SVNURL url) { + myPath = path; + myNumber = number; + myProject = project; + myUrl = url; + } + + @Override + public String getContent() throws VcsException { + if (myContent == null) { + myContent = loadContent(); + } + return myContent; + } + + private String loadContent() { + final SvnVcs17 vcs = SvnVcs17.getInstance(myProject); + final SVNWCClient client = vcs.createWCClient(); + String list; + try { + list = AbstractShowPropertiesDiffAction.getPropertyList(myUrl, ((SvnRevisionNumber) myNumber).getRevision(), client); + } + catch (SVNException e) { + // unknown node kind (node deleted) + /*if (e.getErrorMessage().getErrorCode().getCode() == 145000) { + return ""; + }*/ + list = "Can not get properties: " + e.getMessage(); + } + return list; + } + + @NotNull + @Override + public FilePath getFile() { + return myPath; + } + + @NotNull + @Override + public VcsRevisionNumber getRevisionNumber() { + return myNumber; + } +} diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml index 3116a2bb7fd5..c48d091cf6a6 100644 --- a/resources-en/src/tips/tips.xml +++ b/resources-en/src/tips/tips.xml @@ -137,6 +137,7 @@ +