Merge remote branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2011-12-12 14:03:43 +01:00
16 changed files with 259 additions and 112 deletions
@@ -257,10 +257,13 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
throw new RuntimeConfigurationWarning(ExecutionBundle.message("html.file.not.specified.error.message"));
}
try {
new URL(HTML_FILE_NAME);
new URL(getHtmlURL().getUrl());
}
catch (CantRunException ex) {
checkUrlIsValid(ex);
}
catch (MalformedURLException ex) {
throw new RuntimeConfigurationWarning("URL " + HTML_FILE_NAME + " is not valid: " + ex.getLocalizedMessage());
checkUrlIsValid(ex);
}
}
else {
@@ -268,6 +271,10 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
}
}
private void checkUrlIsValid(Exception ex) throws RuntimeConfigurationWarning {
throw new RuntimeConfigurationWarning("URL " + HTML_FILE_NAME + " is not valid: " + ex.getLocalizedMessage());
}
public AppletParameter[] getAppletParameters() {
return myAppletParameters;
}
@@ -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]);
}
}
@@ -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<PsiMethod> generateDelegatePrototype(PsiMethodMember methodCandidate, PsiElement target) throws IncorrectOperationException {
private PsiGenerationInfo<PsiMethod> 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<PsiMethod>(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<MethodSignature> signatures = new HashSet<MethodSignature>();
final Set<MethodSignature> existingSignatures = new HashSet<MethodSignature>(aClass.getVisibleSignatures());
final Set<PsiMethodMember> selection = new HashSet<PsiMethodMember>();
Map<PsiClass, PsiSubstitutor> superSubstitutors = new HashMap<PsiClass, PsiSubstitutor>();
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<PsiElementClassMember> chooser = new MemberChooser<PsiElementClassMember>(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<PsiElementClassMember> 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;
@@ -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<PsiExpression, PsiType> myCalculatedTypes = new ConcurrentWeakHashMap<PsiExpression, PsiType>();
private final ConcurrentMap<PsiElement, PsiType> myCachedReferencesInPsiTypes = new ConcurrentWeakHashMap<PsiElement, PsiType>();
// e.g. given FileOutputStream os, os2;
// PsiJavaCodeReferenceElement("FileOutputStream") -> [ PsiReferenceExpression("os"), PsiReferenceExpression("os2") ]
private final Map<PsiElement, WeakList<PsiElement>> myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere = new WeakHashMap<PsiElement, WeakList<PsiElement>>();
private final Map<PsiVariable,Object> myVarToConstValueMapPhysical;
private final Map<PsiVariable,Object> 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<PsiElement>() {
@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 <T extends PsiExpression> 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<PsiElement> refsTo = myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.get(reference);
if (refsTo==null) {
refsTo = new WeakList<PsiElement>();
myCachedReferenceIn_PsiClassReferenceType_To_ListOfReferencesOfThisType_CachedHere.put(reference, refsTo);
}
refsTo.add(expr);
}
DebugUtil.trackInvalidation(expr, "Expression invalidated", new Processor<PsiElement>() {
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<PsiElement>() {
@Override
public boolean process(PsiElement element) {
DebugUtil.onInvalidated((TreeElement)dummyHolder.getNode());
return true;
}
});
}
}
DebugUtil.trackInvalidation(reference, "Reference inside PsiClassReferenceType was invalidated", new Processor<PsiElement>() {
@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<PsiElement> 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<PsiElement>() {
@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
@@ -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(); }
@@ -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};
}
@@ -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<Pair<Object, Processor<PsiElement>>> callbacks = element.getUserData(TRACK_INVALIDATION_KEY);
@@ -501,6 +501,7 @@ public class DebugUtil {
if (psi != null) callback.process(psi);
}
}
super.visitNode(element);
}
});
}
@@ -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;
}
@@ -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";
@@ -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
@@ -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
* <ul>
* <li>0 if new project should be opened in new window
* <li>1 if new project should be opened in same window
* <li>-1 if a confirmation dialog should be shown
* <li>{@link GeneralSettings#OPEN_PROJECT_NEW_WINDOW} if new project should be opened in new window
* <li>{@link GeneralSettings#OPEN_PROJECT_SAME_WINDOW} if new project should be opened in same window
* <li>{@link GeneralSettings#OPEN_PROJECT_ASK} if a confirmation dialog should be shown
* </ul>
*/
public int getConfirmOpenNewProject() {
@@ -67,7 +67,7 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable<Searchabl
settings.setInactiveTimeout(newInactiveTimeout);
}
}
catch (NumberFormatException e) {
catch (NumberFormatException ignored) {
}
@@ -85,13 +85,14 @@ public class GeneralSettingsConfigurable extends CompositeConfigurable<Searchabl
int openProjectOption = settings.getConfirmOpenNewProject();
isModified |= (myComponent.myConfirmFrameToOpenCheckBox.isSelected() && openProjectOption >= 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<Searchabl
myComponent.myTfInactiveTimeout.setText(Integer.toString(settings.getInactiveTimeout()));
myComponent.myTfInactiveTimeout.setEditable(settings.isAutoSaveIfInactive());
myComponent.myConfirmExit.setSelected(settings.isConfirmExit());
myComponent.myConfirmFrameToOpenCheckBox.setSelected(settings.getConfirmOpenNewProject() < 0);
myComponent.myConfirmFrameToOpenCheckBox.setSelected(settings.getConfirmOpenNewProject() == GeneralSettings.OPEN_PROJECT_ASK);
}
public void disposeUIResources() {
@@ -25,7 +25,9 @@ public class ProjectNewWindowDoNotAskOption implements DialogWrapper.DoNotAskOpt
}
public void setToBeShown(boolean value, int exitCode) {
GeneralSettings.getInstance().setConfirmOpenNewProject(value || exitCode == 2 ? -1 : exitCode);
int confirmOpenNewProject = value || exitCode == 2 ? GeneralSettings.OPEN_PROJECT_ASK :
exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW ;
GeneralSettings.getInstance().setConfirmOpenNewProject(confirmOpenNewProject);
}
public boolean canBeHidden() {
@@ -161,10 +161,10 @@ public class ProjectUtil {
if (!forceOpenInNewFrame && openProjects.length > 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) {
@@ -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;
}
}
@@ -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<TextRange> 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);
}
@@ -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<PicoContainer> children = new HashSet<PicoContainer>();
private final Map<Object, ComponentAdapter> componentKeyToAdapterCache = new ConcurrentHashMap<Object, ComponentAdapter>();
private final AtomicReference<LinkedHashSet<ComponentAdapter>> componentAdapters = new AtomicReference<LinkedHashSet<ComponentAdapter>>(new LinkedHashSet<ComponentAdapter>());
private final LinkedHashSetWrapper<ComponentAdapter> componentAdapters = new LinkedHashSetWrapper<ComponentAdapter>();
// Keeps track of instantiation order.
private final AtomicReference<LinkedHashSet<ComponentAdapter>> orderedComponentAdapters = new AtomicReference<LinkedHashSet<ComponentAdapter>>(new LinkedHashSet<ComponentAdapter>());
private final LinkedHashSetWrapper<ComponentAdapter> orderedComponentAdapters = new LinkedHashSetWrapper<ComponentAdapter>();
private final Map<String, ComponentAdapter> classNameToAdapter = new ConcurrentHashMap<String, ComponentAdapter>();
private final CopyOnWriteArrayList<ComponentAdapter> nonAssignableComponentAdapters = new CopyOnWriteArrayList<ComponentAdapter>();
private final AtomicReference<FList<ComponentAdapter>> nonAssignableComponentAdapters = new AtomicReference<FList<ComponentAdapter>>(FList.<ComponentAdapter>emptyList());
public DefaultPicoContainer(@NotNull ComponentAdapterFactory componentAdapterFactory, PicoContainer parent) {
this.componentAdapterFactory = componentAdapterFactory;
@@ -50,7 +50,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable
}
public Collection<ComponentAdapter> getComponentAdapters() {
return Collections.unmodifiableCollection(componentAdapters.get());
return componentAdapters.getImmutableSet();
}
public Map<String, ComponentAdapter> getAssignablesCache() {
@@ -59,7 +59,7 @@ public class DefaultPicoContainer implements MutablePicoContainer, Serializable
public Collection<ComponentAdapter> 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<ComponentAdapter> oldList = nonAssignableComponentAdapters.get();
FList<ComponentAdapter> 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 <T> void addElement(AtomicReference<LinkedHashSet<T>> collectionHolder, T element) {
do {
LinkedHashSet<T> oldCollection = collectionHolder.get();
if (oldCollection.contains(element)) {
return;
}
LinkedHashSet<T> newCollection = new LinkedHashSet<T>(oldCollection);
newCollection.add(element);
if (collectionHolder.compareAndSet(oldCollection, newCollection)) break;
} while (true);
}
private static <T> void removeElement(AtomicReference<LinkedHashSet<T>> collectionHolder, T element) {
do {
LinkedHashSet<T> oldCollection = collectionHolder.get();
LinkedHashSet<T> newCollection = new LinkedHashSet<T>(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<ComponentAdapter, Object> adapterToInstanceMap = new HashMap<ComponentAdapter, Object>();
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<Object> result = new ArrayList<Object>();
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<T> {
private volatile Set<T> immutableSet;
private final LinkedHashSet<T> synchronizedSet = new LinkedHashSet<T>();
private final ConcurrentHashMap<T, T> concurrentSet = new ConcurrentHashMap<T, T>();
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<T> getImmutableSet() {
Set<T> res = immutableSet;
if (res == null) {
synchronized (synchronizedSet) {
res = immutableSet;
if (res == null) {
res = Collections.unmodifiableSet((Set<T>)synchronizedSet.clone());
immutableSet = res;
}
}
}
return res;
}
}
}
@@ -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<ReferenceType> 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.
}