From 5afdafd5e30c65e6cb2cf43752c4580f6214f6d9 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 12 Dec 2011 11:56:37 +0100 Subject: [PATCH 01/10] delegate: copy javadoc; preselect yet non-delegated methods (IDEA-59629) --- .../generation/GenerateDelegateHandler.java | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java index a1e91dc00a12..c5a800c9de6a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java @@ -47,6 +47,7 @@ import java.util.Set; */ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.generation.GenerateDelegateHandler"); + private boolean myToCopyJavaDoc = false; @Override public boolean isValidFor(Editor editor, PsiFile file) { @@ -101,7 +102,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler return false; } - private static PsiGenerationInfo generateDelegatePrototype(PsiMethodMember methodCandidate, PsiElement target) throws IncorrectOperationException { + private PsiGenerationInfo generateDelegatePrototype(PsiMethodMember methodCandidate, PsiElement target) throws IncorrectOperationException { PsiMethod method = GenerateMembersUtil.substituteGenericMethod(methodCandidate.getElement(), methodCandidate.getSubstitutor()); clearMethod(method); @@ -184,7 +185,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler return new PsiGenerationInfo(method); } - private static void clearMethod(PsiMethod method) throws IncorrectOperationException { + private void clearMethod(PsiMethod method) throws IncorrectOperationException { LOG.assertTrue(!method.isPhysical()); PsiCodeBlock codeBlock = JavaPsiFacade.getInstance(method.getProject()).getElementFactory().createCodeBlock(); if (method.getBody() != null) { @@ -194,9 +195,11 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler method.add(codeBlock); } - final PsiDocComment docComment = method.getDocComment(); - if (docComment != null) { - docComment.delete(); + if (!myToCopyJavaDoc) { + final PsiDocComment docComment = method.getDocComment(); + if (docComment != null) { + docComment.delete(); + } } } @@ -208,7 +211,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler } @Nullable - private static PsiMethodMember[] chooseMethods(PsiElement target, PsiFile file, Editor editor, Project project) { + private PsiMethodMember[] chooseMethods(PsiElement target, PsiFile file, Editor editor, Project project) { PsiClassType.ClassResolveResult resolveResult = null; if (target instanceof PsiField) { @@ -232,6 +235,8 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler final PsiMethod[] allMethods = targetClass.getAllMethods(); final Set signatures = new HashSet(); + final Set existingSignatures = new HashSet(aClass.getVisibleSignatures()); + final Set selection = new HashSet(); Map superSubstitutors = new HashMap(); JavaPsiFacade facade = JavaPsiFacade.getInstance(target.getProject()); for (PsiMethod method : allMethods) { @@ -248,7 +253,11 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler if (!signatures.contains(signature)) { signatures.add(signature); if (facade.getResolveHelper().isAccessible(method, target, aClass)) { - methodInstances.add(new PsiMethodMember(method, methodSubstitutor)); + final PsiMethodMember methodMember = new PsiMethodMember(method, methodSubstitutor); + methodInstances.add(methodMember); + if (!existingSignatures.contains(signature)) { + selection.add(methodMember); + } } } } @@ -257,21 +266,29 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler if (!ApplicationManager.getApplication().isUnitTestMode()) { MemberChooser chooser = new MemberChooser(methodInstances.toArray(new PsiMethodMember[methodInstances.size()]), false, true, project); chooser.setTitle(CodeInsightBundle.message("generate.delegate.method.chooser.title")); - chooser.setCopyJavadocVisible(false); + chooser.setCopyJavadocVisible(true); + if (!selection.isEmpty()) { + chooser.selectElements(selection.toArray(new ClassMember[selection.size()])); + } chooser.show(); if (chooser.getExitCode() != MemberChooser.OK_EXIT_CODE) return null; + myToCopyJavaDoc = chooser.isCopyJavadoc(); final List list = chooser.getSelectedElements(); result = list.toArray(new PsiMethodMember[list.size()]); } else { - result = new PsiMethodMember[] {methodInstances.get(0)}; + result = methodInstances.isEmpty() ? new PsiMethodMember[0] : new PsiMethodMember[] {methodInstances.get(0)}; } return result; } + public void setToCopyJavaDoc(boolean toCopyJavaDoc) { + myToCopyJavaDoc = toCopyJavaDoc; + } + public static boolean isApplicable(PsiFile file, Editor editor) { ClassMember[] targetElements = getTargetElements(file, editor); return targetElements != null && targetElements.length > 0; From 40d8cda3fef5c371b5a400f71f3ac3ea0808d245 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 12 Dec 2011 12:23:02 +0100 Subject: [PATCH 02/10] applet: check preprocessed url during configuration validation (IDEA-70227) --- .../execution/applet/AppletConfiguration.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java b/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java index 6773ac3029ff..17a90c945d89 100644 --- a/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java +++ b/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java @@ -257,10 +257,13 @@ public class AppletConfiguration extends ModuleBasedConfiguration Date: Fri, 9 Dec 2011 13:14:55 +0400 Subject: [PATCH 03/10] IDEA-78444 --- .../src/com/intellij/usages/ChunkExtractor.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java index a7de001cb4e9..0e0bbdb3c1df 100644 --- a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java +++ b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java @@ -16,6 +16,7 @@ package com.intellij.usages; import com.intellij.injected.editor.DocumentWindow; +import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.lexer.Lexer; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -29,6 +30,7 @@ import com.intellij.openapi.fileTypes.PlainSyntaxHighlighter; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Segment; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -96,7 +98,7 @@ public class ChunkExtractor { }; public static TextChunk[] extractChunks(@NotNull PsiFile file, UsageInfo2UsageAdapter usageAdapter) { - return ourExtractors.get().getValue().get(file).extractChunks(usageAdapter); + return ourExtractors.get().getValue().get(file).extractChunks(usageAdapter, file); } @@ -124,7 +126,7 @@ public class ChunkExtractor { return minStart == Integer.MAX_VALUE ? -1 : minStart; } - private TextChunk[] extractChunks(UsageInfo2UsageAdapter usageInfo2UsageAdapter) { + private TextChunk[] extractChunks(@NotNull UsageInfo2UsageAdapter usageInfo2UsageAdapter, @NotNull PsiFile file) { int absoluteStartOffset = usageInfo2UsageAdapter.getNavigationOffset(); if (absoluteStartOffset == -1) return TextChunk.EMPTY_ARRAY; @@ -150,6 +152,14 @@ public class ChunkExtractor { lineStartOffset = Math.max(lineStartOffset, absoluteStartOffset - OFFSET_BEFORE_TO_SHOW_WHEN_LONG_LINE); lineEndOffset = Math.min(lineEndOffset, absoluteStartOffset + OFFSET_AFTER_TO_SHOW_WHEN_LONG_LINE); } + if (myDocument instanceof DocumentWindow) { + List editable = InjectedLanguageManager.getInstance(file.getProject()) + .intersectWithAllEditableFragments(file, new TextRange(lineStartOffset, lineEndOffset)); + for (TextRange range : editable) { + createTextChunks(usageInfo2UsageAdapter, chars, range.getStartOffset(), range.getEndOffset(), result); + } + return result.toArray(new TextChunk[result.size()]); + } return createTextChunks(usageInfo2UsageAdapter, chars, lineStartOffset, lineEndOffset, result); } From bab167569bf4aee33d185a9907abcc2c18481f08 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 9 Dec 2011 13:19:58 +0400 Subject: [PATCH 04/10] diagnostics --- .../impl/source/resolve/JavaResolveCache.java | 105 ++++++++++++++---- .../src/com/intellij/psi/impl/DebugUtil.java | 3 +- 2 files changed, 83 insertions(+), 25 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java index 11cdf6305f98..38eb67cdd892 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java @@ -27,13 +27,17 @@ import com.intellij.openapi.util.NotNullLazyKey; import com.intellij.psi.*; import com.intellij.psi.impl.AnyPsiChangeListener; import com.intellij.psi.impl.DebugUtil; +import com.intellij.psi.impl.PsiManagerEx; import com.intellij.psi.impl.PsiManagerImpl; import com.intellij.psi.impl.source.PsiClassReferenceType; +import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ConcurrentWeakHashMap; +import com.intellij.util.containers.WeakHashMap; +import com.intellij.util.containers.WeakList; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,6 +57,9 @@ public class JavaResolveCache { private final ConcurrentMap myCalculatedTypes = new ConcurrentWeakHashMap(); private final ConcurrentMap myCachedReferencesInPsiTypes = new ConcurrentWeakHashMap(); + // e.g. given FileOutputStream os, os2; + // PsiJavaCodeReferenceElement("FileOutputStream") -> [ PsiReferenceExpression("os"), PsiReferenceExpression("os2") ] + private final Map> myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere = new WeakHashMap>(); private final Map myVarToConstValueMapPhysical; private final Map myVarToConstValueMapNonPhysical; @@ -78,6 +85,7 @@ public class JavaResolveCache { private void clearCaches(boolean isPhysical) { myCalculatedTypes.clear(); myCachedReferencesInPsiTypes.clear(); + myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.clear(); if (isPhysical) { myVarToConstValueMapPhysical.clear(); } @@ -96,8 +104,15 @@ public class JavaResolveCache { if (type == null) { type = TypeConversionUtil.NULL_TYPE; } - type = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, type); + PsiType stored = ConcurrencyUtil.cacheOrGet(myCalculatedTypes, expr, type); + + if (stored == type && DebugUtil.DO_EXPENSIVE_CHECKS) { + registerDiagnosticsHooks(expr, type); + } + + type = stored; } + if (!type.isValid()) { if (expr.isValid()) { PsiJavaCodeReferenceElement refInside = type instanceof PsiClassReferenceType ? ((PsiClassReferenceType)type).getReference() : null; @@ -109,44 +124,86 @@ public class JavaResolveCache { } } - if (DebugUtil.DO_EXPENSIVE_CHECKS) { - if (type instanceof PsiClassReferenceType) { - PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference(); - ConcurrencyUtil.cacheOrGet(myCachedReferencesInPsiTypes, reference, type); - DebugUtil.trackInvalidation(reference, "Reference inside PsiClassReferenceType was invalidated", new Processor() { - @Override - public boolean process(PsiElement element) { - PsiType cached = myCalculatedTypes.get(element); - if (cached != null) { - LOG.error(element + " (inside ref) is invalid and yet it is still cached: " + cached); - } - PsiType cachedRef = myCachedReferencesInPsiTypes.get(element); - if (cachedRef != null) { - LOG.error(element + " (inside ref) is invalid and yet it is still cached in ref cache: " + cachedRef); - } - return true; - } - }); + return type == TypeConversionUtil.NULL_TYPE ? null : type; + } + private void registerDiagnosticsHooks(T expr, PsiType type) { + if (type instanceof PsiClassReferenceType) { + PsiJavaCodeReferenceElement reference = ((PsiClassReferenceType)type).getReference(); + ConcurrencyUtil.cacheOrGet(myCachedReferencesInPsiTypes, reference, type); + synchronized (myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere) { + WeakList refsTo = myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.get(reference); + if (refsTo==null) { + refsTo = new WeakList(); + myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.put(reference, refsTo); + } + refsTo.add(expr); } - DebugUtil.trackInvalidation(expr, "Expression invalidated", new Processor() { + final PsiFile dummyHolder = reference.getContainingFile(); + if (dummyHolder != null && !dummyHolder.isPhysical()) { + PsiElement physicalContext = dummyHolder.getContext(); + PsiFile physicalFile; + if (physicalContext != null && + (physicalFile = physicalContext.getContainingFile()) != null && + physicalFile.getVirtualFile() != null && + !((PsiManagerEx)PsiManager.getInstance(dummyHolder.getProject())).isAssertOnFileLoading(physicalFile.getVirtualFile())) { + DebugUtil.trackInvalidation(physicalContext, "dummy holder was invalidated", new Processor() { + @Override + public boolean process(PsiElement element) { + DebugUtil.onInvalidated((TreeElement)dummyHolder.getNode()); + return true; + } + }); + } + } + + DebugUtil.trackInvalidation(reference, "Reference inside PsiClassReferenceType was invalidated", new Processor() { @Override public boolean process(PsiElement element) { PsiType cached = myCalculatedTypes.get(element); if (cached != null) { - LOG.error(element + " is invalid and yet it is still cached: " + cached); + LOG.error(element + " (inside ref) is invalid and yet it is still cached: " + cached); } - PsiType cachedRef = myCachedReferencesInPsiTypes.get(element); if (cachedRef != null) { - LOG.error(element + " is invalid and yet it is still cached (inside PsiType): " + cachedRef); + LOG.error(element + " (inside ref) is invalid and yet it is still cached in ref cache: " + cachedRef); } + + + synchronized (myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere) { + WeakList refsTo = myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.get(element); + if (refsTo != null) { + for (PsiElement ref : refsTo) { + PsiType cachedT = myCalculatedTypes.get(ref); + if (cachedT != null && !cachedT.isValid()) { + LOG.error("During invalidation of " + element + " ("+element.getClass()+")"+ + " cached type " + cachedT + " of the ref "+ref+" ("+ref.getClass()+")"+ + " became invalid and yet it is still cached" + ); + } + } + } + } + return true; } }); } + DebugUtil.trackInvalidation(expr, "Expression invalidated", new Processor() { + @Override + public boolean process(PsiElement element) { + PsiType cached = myCalculatedTypes.get(element); + if (cached != null) { + LOG.error(element + " is invalid and yet it is still cached: " + cached); + } - return type == TypeConversionUtil.NULL_TYPE ? null : type; + PsiType cachedRef = myCachedReferencesInPsiTypes.get(element); + if (cachedRef != null) { + LOG.error(element + " is invalid and yet it is still cached (inside PsiType): " + cachedRef); + } + return true; + } + }); } @Nullable diff --git a/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java b/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java index 90aa13fdb388..c8cb5460e197 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java +++ b/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java @@ -490,7 +490,7 @@ public class DebugUtil { } public static void onInvalidated(@NotNull TreeElement treeElement) { - treeElement.acceptTree(new RecursiveTreeElementWalkingVisitor() { + treeElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) { @Override protected void visitNode(TreeElement element) { List>> callbacks = element.getUserData(TRACK_INVALIDATION_KEY); @@ -501,6 +501,7 @@ public class DebugUtil { if (psi != null) callback.process(psi); } } + super.visitNode(element); } }); } From 82212e6a149758d1af32e600a302a7a7b2bf0eef Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Dec 2011 10:20:44 +0400 Subject: [PATCH 05/10] reset option "open project in window" to "ask user" --- platform/platform-api/src/com/intellij/ide/GeneralSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java index 142faa3a4637..42f47d5be63a 100644 --- a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java +++ b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java @@ -74,7 +74,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli @NonNls private static final String OPTION_USE_CYCLIC_BUFFER = "useCyclicBuffer"; @NonNls private static final String OPTION_SEARCH_IN_BACKGROUND = "searchInBackground"; @NonNls private static final String OPTION_CONFIRM_EXIT = "confirmExit"; - @NonNls private static final String OPTION_CONFIRM_OPEN_NEW_PROJECT = "confirmOpenNewProject"; + @NonNls private static final String OPTION_CONFIRM_OPEN_NEW_PROJECT = "confirmOpenNewProject2"; @NonNls private static final String OPTION_CYCLIC_BUFFER_SIZE = "cyclicBufferSize"; @NonNls private static final String OPTION_LAST_PROJECT_LOCATION = "lastProjectLocation"; @Deprecated From 5c7f40b17b920829c245ed92c762e7142f129594 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Dec 2011 10:27:06 +0400 Subject: [PATCH 06/10] constants instead of magic numbers --- .../com/intellij/ide/impl/NewProjectUtil.java | 3 +- .../src/com/intellij/ide/GeneralSettings.java | 10 ++--- .../ide/GeneralSettingsConfigurable.java | 9 +++-- .../impl/ProjectNewWindowDoNotAskOption.java | 4 +- .../com/intellij/ide/impl/ProjectUtil.java | 37 ++++++++++--------- .../PlatformProjectOpenProcessor.java | 6 ++- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java index 41ce665cc145..91d04d04dc3a 100644 --- a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java +++ b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.java @@ -19,6 +19,7 @@ */ package com.intellij.ide.impl; +import com.intellij.ide.GeneralSettings; import com.intellij.ide.util.newProjectWizard.AddModuleWizard; import com.intellij.ide.util.projectWizard.ProjectBuilder; import com.intellij.openapi.application.ApplicationManager; @@ -209,7 +210,7 @@ public class NewProjectUtil { Project[] openProjects = ProjectManager.getInstance().getOpenProjects(); if (openProjects.length > 0) { int exitCode = ProjectUtil.confirmOpenNewProject(true); - if (exitCode == 0) { // this window option + if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) { ProjectUtil.closeAndDispose(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1]); } } diff --git a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java index 42f47d5be63a..52415124e3e7 100644 --- a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java +++ b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java @@ -52,7 +52,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli private String myLastProjectLocation; private boolean mySearchInBackground; private boolean myConfirmExit = true; - private int myConfirmOpenNewProject = -1; + private int myConfirmOpenNewProject = OPEN_PROJECT_ASK; @NonNls private static final String ELEMENT_OPTION = "option"; @NonNls private static final String ATTRIBUTE_NAME = "name"; @NonNls private static final String ATTRIBUTE_VALUE = "value"; @@ -331,7 +331,7 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli myConfirmOpenNewProject = Integer.valueOf(value).intValue(); } catch (Exception ex) { - myConfirmOpenNewProject = -1; + myConfirmOpenNewProject = OPEN_PROJECT_ASK; } } @@ -477,9 +477,9 @@ public class GeneralSettings implements NamedJDOMExternalizable, ExportableAppli /** * @return *
    - *
  • 0 if new project should be opened in new window - *
  • 1 if new project should be opened in same window - *
  • -1 if a confirmation dialog should be shown + *
  • {@link GeneralSettings#OPEN_PROJECT_NEW_WINDOW} if new project should be opened in new window + *
  • {@link GeneralSettings#OPEN_PROJECT_SAME_WINDOW} if new project should be opened in same window + *
  • {@link GeneralSettings#OPEN_PROJECT_ASK} if a confirmation dialog should be shown *
*/ public int getConfirmOpenNewProject() { diff --git a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java index 3fc1d36b617c..c748cdeb847b 100644 --- a/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/ide/GeneralSettingsConfigurable.java @@ -67,7 +67,7 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable= 0) || (!myComponent.myConfirmFrameToOpenCheckBox.isSelected() == openProjectOption < 0); + boolean savedOptionIsAsk = openProjectOption == GeneralSettings.OPEN_PROJECT_ASK; + isModified |= myComponent.myConfirmFrameToOpenCheckBox.isSelected() != savedOptionIsAsk; int inactiveTimeout = -1; try { inactiveTimeout = Integer.parseInt(myComponent.myTfInactiveTimeout.getText()); } - catch (NumberFormatException e) { + catch (NumberFormatException ignored) { } isModified |= inactiveTimeout > 0 && settings.getInactiveTimeout() != inactiveTimeout; @@ -141,7 +142,7 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable 0) { int exitCode = confirmOpenNewProject(false); - if (exitCode == 0) { // this window option + if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) { if (!closeAndDispose(projectToClose != null ? projectToClose : openProjects[openProjects.length - 1])) return null; } - else if (exitCode != 1) { // not in a new window + else if (exitCode != GeneralSettings.OPEN_PROJECT_NEW_WINDOW) { return null; } } @@ -192,30 +192,33 @@ public class ProjectUtil { } /** - * @return 0 - this window - * 1 - new window - * 2 - cancel + * @return {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_SAME_WINDOW} + * {@link com.intellij.ide.GeneralSettings#OPEN_PROJECT_NEW_WINDOW} + * {@link com.intellij.openapi.ui.Messages#CANCEL} - if user canceled the dialog * @param isNewProject */ public static int confirmOpenNewProject(boolean isNewProject) { final GeneralSettings settings = GeneralSettings.getInstance(); - if (settings.getConfirmOpenNewProject() == GeneralSettings.OPEN_PROJECT_ASK) { + int confirmOpenNewProject = settings.getConfirmOpenNewProject(); + if (confirmOpenNewProject == GeneralSettings.OPEN_PROJECT_ASK) { if (isNewProject) { - return 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()); + 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()); + return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW; } else { - return 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()); + 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; } } - return settings.getConfirmOpenNewProject(); + return confirmOpenNewProject; } private static boolean isSameProject(String path, Project p) { diff --git a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java index f9246c0edab1..0d60ed6689a2 100644 --- a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java +++ b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java @@ -16,6 +16,8 @@ package com.intellij.platform; import com.intellij.conversion.ConversionResult; + +import com.intellij.ide.GeneralSettings; import com.intellij.ide.impl.ProjectUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; @@ -125,10 +127,10 @@ public class PlatformProjectOpenProcessor extends ProjectOpenProcessor { } else { int exitCode = ProjectUtil.confirmOpenNewProject(false); - if (exitCode == 0) { // this window option + if (exitCode == GeneralSettings.OPEN_PROJECT_SAME_WINDOW) { if (!ProjectUtil.closeAndDispose(projectToClose)) return null; } - else if (exitCode != 1) { // not in a new window + else if (exitCode != GeneralSettings.OPEN_PROJECT_NEW_WINDOW) { // not in a new window return null; } } From 67b693cc5804132519110094efd1aa0ed3410427 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 12 Dec 2011 10:29:27 +0400 Subject: [PATCH 07/10] run external annotators on the whole file --- .../codeInsight/daemon/impl/ExternalToolPassFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java index dfe94b45c3e1..4dec3b2a23b6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/ExternalToolPassFactory.java @@ -54,7 +54,7 @@ public class ExternalToolPassFactory extends AbstractProjectComponent implements @Override @Nullable public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) { - TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.EXTERNAL_TOOLS); + TextRange textRange = file.getTextRange(); if (textRange == null || !externalAnnotatorsDefined(file)) { return null; } From 227de9f5cabc39900f9bf1687c834752bda4315d Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 12 Dec 2011 12:50:28 +0100 Subject: [PATCH 08/10] fix tests --- .../codeInsight/daemon/JavadocHighlightingTest.java | 7 ++++++- .../daemon/quickFix/JavadocInspectionQuickFixTest.java | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java index 5dc0bd3c99dd..d70e62c881c0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java @@ -65,7 +65,12 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase { public void testException1() throws Exception { doTest(); } public void testException2() throws Exception { doTest(); } public void testException3() throws Exception { doTest(); } - public void testException4() throws Exception { doTest(); } + public void testException4() throws Exception { + final JavaDocLocalInspection javaDocLocalInspection = new JavaDocLocalInspection(); + javaDocLocalInspection.METHOD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = "package"; + enableInspectionTool(javaDocLocalInspection); + doTest(); + } public void testMultipleThrows() throws Exception { doTest(); } public void testInheritJavaDoc() throws Exception {doTestWithLangLevel(LanguageLevel.JDK_1_3);} public void testLink0() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java index f05103fa51ed..6c40bf65b1db 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java @@ -19,6 +19,8 @@ public class JavadocInspectionQuickFixTest extends LightQuickFix15TestCase { protected LocalInspectionTool[] configureLocalInspectionTools() { final JavaDocLocalInspection javaDocLocalInspection = new JavaDocLocalInspection(); javaDocLocalInspection.TOP_LEVEL_CLASS_OPTIONS.REQUIRED_TAGS = "param"; + javaDocLocalInspection.TOP_LEVEL_CLASS_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = "package"; + javaDocLocalInspection.METHOD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = "package"; return new LocalInspectionTool[]{javaDocLocalInspection}; } From 810c16844ffb3f432fa729766d8af36c8a7d84a9 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 12 Dec 2011 16:29:30 +0300 Subject: [PATCH 09/10] Bug fix: Process doesn't stop on breakpoint. --- .../springloaded/SpringLoadedPositionManager.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java index dffc834d3c2a..34f0e7d303df 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/springloaded/SpringLoadedPositionManager.java @@ -33,7 +33,7 @@ import java.util.regex.Pattern; */ public class SpringLoadedPositionManager implements PositionManager { - private static final Pattern GENERATED_CLASS_NAME = Pattern.compile(".*\\$\\$[A-Za-z0-9]{8}"); + private static final Pattern GENERATED_CLASS_NAME = Pattern.compile("\\$\\$[A-Za-z0-9]{8}"); private final DebugProcess myDebugProcess; @@ -158,6 +158,16 @@ public class SpringLoadedPositionManager implements PositionManager { return myDebugProcess.getRequestsManager().createClassPrepareRequest(requestor, className + "*"); } + private static boolean isSpringLoadedGeneratedClass(ReferenceType ownerClass, ReferenceType aClass) { + String name = aClass.name(); + String ownerClassName = ownerClass.name(); + + // return name == ownerClassName + "$$" + /[A-Za-z0-9]{8}/ + return name.length() == ownerClassName.length() + 2 + 8 + && name.startsWith(ownerClassName) + && GENERATED_CLASS_NAME.matcher(name.substring(ownerClassName.length())).matches(); + } + @Nullable private static List findNested(ReferenceType fromClass, SourcePosition classPosition) { if (!fromClass.isPrepared()) return null; @@ -169,7 +179,7 @@ public class SpringLoadedPositionManager implements PositionManager { for (ReferenceType nested : nestedTypes) { if (!nested.isPrepared()) continue; - if (GENERATED_CLASS_NAME.matcher(nested.name()).matches()) { + if (isSpringLoadedGeneratedClass(fromClass, nested)) { if (springLoadedGeneratedClasses.size() > 0 && !springLoadedGeneratedClasses.get(0).name().equals(nested.name())) { springLoadedGeneratedClasses.clear(); // Only latest generated classes should be used. } From 69ccf77b024bb2482e6007cb6ee88e27dac909d1 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 12 Dec 2011 16:48:26 +0300 Subject: [PATCH 10/10] Optimize DefaultPicoContainer for test. --- .../util/pico/DefaultPicoContainer.java | 107 +++++++++++------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java index 842cd469f4a4..c7dc592bb474 100644 --- a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java +++ b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java @@ -17,6 +17,7 @@ package com.intellij.util.pico; import com.intellij.util.ReflectionCache; import com.intellij.util.containers.ConcurrentHashMap; +import com.intellij.util.containers.FList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.*; @@ -24,7 +25,6 @@ import org.picocontainer.defaults.*; import java.io.Serializable; import java.util.*; -import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; public class DefaultPicoContainer implements MutablePicoContainer, Serializable { @@ -34,11 +34,11 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable private final Set children = new HashSet(); private final Map componentKeyToAdapterCache = new ConcurrentHashMap(); - private final AtomicReference> componentAdapters = new AtomicReference>(new LinkedHashSet()); + private final LinkedHashSetWrapper componentAdapters = new LinkedHashSetWrapper(); // Keeps track of instantiation order. - private final AtomicReference> orderedComponentAdapters = new AtomicReference>(new LinkedHashSet()); + private final LinkedHashSetWrapper orderedComponentAdapters = new LinkedHashSetWrapper(); private final Map classNameToAdapter = new ConcurrentHashMap(); - private final CopyOnWriteArrayList nonAssignableComponentAdapters = new CopyOnWriteArrayList(); + private final AtomicReference> nonAssignableComponentAdapters = new AtomicReference>(FList.emptyList()); public DefaultPicoContainer(@NotNull ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) { this.componentAdapterFactory = componentAdapterFactory; @@ -50,7 +50,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } public Collection getComponentAdapters() { - return Collections.unmodifiableCollection(componentAdapters.get()); + return componentAdapters.getImmutableSet(); } public Map getAssignablesCache() { @@ -59,7 +59,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable public Collection getNonAssignableAdapters() { - return nonAssignableComponentAdapters; + return nonAssignableComponentAdapters.get().getReversedList(); } @Nullable @@ -141,51 +141,34 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable classNameToAdapter.put(classKey, componentAdapter); } else { - nonAssignableComponentAdapters.add(componentAdapter); + do { + FList oldList = nonAssignableComponentAdapters.get(); + FList newList = oldList.prepend(componentAdapter); + if (nonAssignableComponentAdapters.compareAndSet(oldList, newList)) { + break; + } + } while (true); } - addElement(componentAdapters, componentAdapter); + componentAdapters.add(componentAdapter); componentKeyToAdapterCache.put(componentKey, componentAdapter); return componentAdapter; } - private static void addElement(AtomicReference> collectionHolder, T element) { - do { - LinkedHashSet oldCollection = collectionHolder.get(); - if (oldCollection.contains(element)) { - return; - } - - LinkedHashSet newCollection = new LinkedHashSet(oldCollection); - newCollection.add(element); - - if (collectionHolder.compareAndSet(oldCollection, newCollection)) break; - } while (true); - } - - private static void removeElement(AtomicReference> collectionHolder, T element) { - do { - LinkedHashSet oldCollection = collectionHolder.get(); - - LinkedHashSet newCollection = new LinkedHashSet(oldCollection); - newCollection.remove(element); - - if (collectionHolder.compareAndSet(oldCollection, newCollection)) break; - } while (true); - } - public ComponentAdapter unregisterComponent(Object componentKey) { ComponentAdapter adapter = componentKeyToAdapterCache.remove(componentKey); - removeElement(componentAdapters, adapter); - removeElement(orderedComponentAdapters, adapter); + componentAdapters.remove(adapter); + orderedComponentAdapters.remove(adapter); return adapter; } private void addOrderedComponentAdapter(ComponentAdapter componentAdapter) { - addElement(orderedComponentAdapters, componentAdapter); + if (!orderedComponentAdapters.contains(componentAdapter)) { + orderedComponentAdapters.add(componentAdapter); + } } public List getComponentInstances() throws PicoException { @@ -198,7 +181,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } Map adapterToInstanceMap = new HashMap(); - for (final ComponentAdapter componentAdapter : componentAdapters.get()) { + for (final ComponentAdapter componentAdapter : componentAdapters.getImmutableSet()) { if (ReflectionCache.isAssignable(componentType, componentAdapter.getComponentImplementation())) { Object componentInstance = getInstance(componentAdapter); adapterToInstanceMap.put(componentAdapter, componentInstance); @@ -210,7 +193,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable } List result = new ArrayList(); - for (ComponentAdapter componentAdapter : orderedComponentAdapters.get()) { + for (ComponentAdapter componentAdapter : orderedComponentAdapters.getImmutableSet()) { final Object componentInstance = adapterToInstanceMap.get(componentAdapter); if (componentInstance != null) { // may be null in the case of the "implicit" adapter @@ -240,7 +223,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable @Nullable private Object getInstance(ComponentAdapter componentAdapter) { - final boolean isLocal = componentAdapters.get().contains(componentAdapter); + final boolean isLocal = componentAdapters.contains(componentAdapter); if (isLocal) { return getLocalInstance(componentAdapter); @@ -359,4 +342,50 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable public PicoContainer getParent() { return parent; } + + private static class LinkedHashSetWrapper { + + private volatile Set immutableSet; + + private final LinkedHashSet synchronizedSet = new LinkedHashSet(); + + private final ConcurrentHashMap concurrentSet = new ConcurrentHashMap(); + + public boolean contains(@Nullable T element) { + return element != null && concurrentSet.containsKey(element); + } + + public void add(@NotNull T element) { + synchronized (synchronizedSet) { + immutableSet = null; + synchronizedSet.add(element); + concurrentSet.put(element, element); + } + } + + public void remove(@Nullable T element) { + if (element == null) return; + synchronized (synchronizedSet) { + immutableSet = null; + synchronizedSet.remove(element); + concurrentSet.remove(element); + } + } + + @NotNull + public Set getImmutableSet() { + Set res = immutableSet; + if (res == null) { + synchronized (synchronizedSet) { + res = immutableSet; + if (res == null) { + res = Collections.unmodifiableSet((Set)synchronizedSet.clone()); + immutableSet = res; + } + } + } + + return res; + } + } } \ No newline at end of file