diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java b/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java index 78bf10fe7e40..2cfa649b10dc 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/InstructionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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,21 +22,16 @@ import org.jetbrains.annotations.Nullable; */ public class InstructionParser { private final byte[] myCode; - private final long myCurrentInstructionIndex; + private final long myStopOffset; - public InstructionParser(byte[] code, long instructionIndex) { + public InstructionParser(byte[] code, long stopOffset) { myCode = code; - myCurrentInstructionIndex = instructionIndex; + myStopOffset = stopOffset; } public void parse() { - final int codeEnd = myCode.length; int v = 0; - int instructionIndex = 0; - while (v < codeEnd) { - if (instructionIndex++ >= myCurrentInstructionIndex) { - break; - } + while (v < myStopOffset) { int opcode = myCode[v] & 0xFF; final byte opcodeType = opcode == Bytecodes.IMPDEP1 || opcode == Bytecodes.IMPDEP2? Bytecodes.NOARG_INSN : Bytecodes.TYPE[opcode]; switch (opcodeType) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java index c4c6201f0ee6..5bf55df20844 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/FrameVariablesTree.java @@ -242,9 +242,8 @@ public class FrameVariablesTree extends DebuggerTree { final byte[] bytecodes = method.bytecodes(); if (bytecodes != null && bytecodes.length > 0) { final int firstLocalVariableSlot = ArgumentValueDescriptorImpl.getFirstLocalsSlot(method); - final long instructionIndex = location.codeIndex(); final TIntObjectHashMap usedVars = new TIntObjectHashMap(); - new InstructionParser(bytecodes, instructionIndex) { + new InstructionParser(bytecodes, location.codeIndex()) { @Override protected void localVariableInstructionFound(int opcode, int slot, String typeSignature) { if (slot >= firstLocalVariableSlot) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java index 2e3653afaf02..545517903000 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ArgumentValueDescriptorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -161,9 +161,15 @@ public class ArgumentValueDescriptorImpl extends ValueDescriptorImpl{ } public void visitSynchronizedStatement(PsiSynchronizedStatement statement) { - appendName(""); - myCurrentSlotIndex++; - super.visitSynchronizedStatement(statement); + myIndexStack.push(myCurrentSlotIndex); + try { + appendName(""); + myCurrentSlotIndex++; + super.visitSynchronizedStatement(statement); + } + finally { + myCurrentSlotIndex = myIndexStack.pop(); + } } private void appendName(String varName) { diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java index a5b22a82ec83..a8effbfcb884 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -542,65 +542,60 @@ public class ExternalAnnotationsManagerImpl extends ReadableExternalAnnotationsM notifyAfterAnnotationChanging(listOwner, annotationFQName, false); return; } - CommandProcessor.getInstance().executeCommand(myPsiManager.getProject(), new Runnable() { - @Override - public void run() { - try { - final XmlDocument document = xmlFile.getDocument(); - if (document != null) { - final XmlTag rootTag = document.getRootTag(); - final String externalName = getExternalName(listOwner, false); - if (externalName == null) { - LOG.info("member without external name: " + listOwner); - } - if (rootTag != null && externalName != null) { - XmlTag anchor = null; - for (XmlTag item : rootTag.getSubTags()) { - int compare = Comparing.compare(externalName, StringUtil.unescapeXml(item.getAttributeValue("name"))); + try { + final XmlDocument document = xmlFile.getDocument(); + if (document != null) { + final XmlTag rootTag = document.getRootTag(); + final String externalName = getExternalName(listOwner, false); + if (externalName == null) { + LOG.info("member without external name: " + listOwner); + } + if (rootTag != null && externalName != null) { + XmlTag anchor = null; + for (XmlTag item : rootTag.getSubTags()) { + int compare = Comparing.compare(externalName, StringUtil.unescapeXml(item.getAttributeValue("name"))); + if (compare == 0) { + anchor = null; + for (XmlTag annotation : item.getSubTags()) { + compare = Comparing.compare(annotationFQName, annotation.getAttributeValue("name")); if (compare == 0) { - anchor = null; - for (XmlTag annotation : item.getSubTags()) { - compare = Comparing.compare(annotationFQName, annotation.getAttributeValue("name")); - if (compare == 0) { - annotation.delete(); - break; - } - anchor = annotation; - } - XmlTag newTag = XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText( - createAnnotationTag(annotationFQName, values)); - item.addAfter(newTag, anchor); - commitChanges(xmlFile); - notifyAfterAnnotationChanging(listOwner, annotationFQName, true); - return; + annotation.delete(); + break; } - if (compare < 0) break; - anchor = item; + anchor = annotation; } - @NonNls String text = - "\n"; - text += createAnnotationTag(annotationFQName, values); - text += ""; - rootTag.addAfter(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text), anchor); + XmlTag newTag = XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText( + createAnnotationTag(annotationFQName, values)); + item.addAfter(newTag, anchor); commitChanges(xmlFile); notifyAfterAnnotationChanging(listOwner, annotationFQName, true); return; } + if (compare < 0) break; + anchor = item; } - notifyAfterAnnotationChanging(listOwner, annotationFQName, false); - } - catch (IncorrectOperationException e) { - LOG.error(e); - notifyAfterAnnotationChanging(listOwner, annotationFQName, false); - } - finally { - dropCache(); - if (codeUsageFile.getVirtualFile().isInLocalFileSystem()) { - UndoUtil.markPsiFileForUndo(codeUsageFile); - } + @NonNls String text = + "\n"; + text += createAnnotationTag(annotationFQName, values); + text += ""; + rootTag.addAfter(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text), anchor); + commitChanges(xmlFile); + notifyAfterAnnotationChanging(listOwner, annotationFQName, true); + return; } } - }, ExternalAnnotationsManagerImpl.class.getName(), null); + notifyAfterAnnotationChanging(listOwner, annotationFQName, false); + } + catch (IncorrectOperationException e) { + LOG.error(e); + notifyAfterAnnotationChanging(listOwner, annotationFQName, false); + } + finally { + dropCache(); + if (codeUsageFile.getVirtualFile().isInLocalFileSystem()) { + UndoUtil.markPsiFileForUndo(codeUsageFile); + } + } } private static void sortItems(@NotNull XmlFile xmlFile) { diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java index 9de12bd4dfec..f2c24d3b8ebf 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -100,6 +100,17 @@ public abstract class PsiElementFinder { return PsiClass.EMPTY_ARRAY; } + /** + * Returns the filter to exclude classes, for example derived classes. + * + * @param scope the scope in which classes are searched. + * @return the filter to use, or null if no additional filtering is necessary + */ + @Nullable + public Condition getClassesFilter(@NotNull GlobalSearchScope scope) { + return null; + } + /** * Returns a list of files belonging to the specified package which are not located in any of the package directories. * diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java index 9b57ab5d4aa4..78a58fc8b70b 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java @@ -115,34 +115,23 @@ public class MethodCandidateInfo extends CandidateInfo{ if (myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) { return getApplicabilityLevel(); } - @ApplicabilityLevelConstant int level; final PsiSubstitutor substitutor = getSubstitutor(false); - Map map = CURRENT_CANDIDATE.get(); - if (map == null) { - map = ContainerUtil.createConcurrentWeakMap(); - CURRENT_CANDIDATE.set(map); - } final PsiMethod method = getElement(); - final CurrentCandidateProperties properties = new CurrentCandidateProperties(method, substitutor, isVarargs(), true); - final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), properties); - try { - PsiType[] argumentTypes = getArgumentTypes(); - if (argumentTypes == null) { - return ApplicabilityLevel.NOT_APPLICABLE; - } + @ApplicabilityLevelConstant int level = computeForOverloadedCandidate(new Computable() { + @Override + public Integer compute() { + PsiType[] argumentTypes = getArgumentTypes(); + if (argumentTypes == null) { + return ApplicabilityLevel.NOT_APPLICABLE; + } - level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel); - if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) { - return ApplicabilityLevel.NOT_APPLICABLE; + int level = PsiUtil.getApplicabilityLevel(method, substitutor, argumentTypes, myLanguageLevel); + if (!isVarargs() && level < ApplicabilityLevel.FIXED_ARITY) { + return ApplicabilityLevel.NOT_APPLICABLE; + } + return level; } - } - finally { - if (alreadyThere == null) { - map.remove(getMarkerList()); - } else { - map.put(getMarkerList(), alreadyThere); - } - } + }, substitutor); if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(new Computable() { @Override public PsiSubstitutor compute() { @@ -154,6 +143,34 @@ public class MethodCandidateInfo extends CandidateInfo{ return level; } + public PsiType[] getPertinentArgumentTypes() { + return computeForOverloadedCandidate(new Computable() { + public PsiType[] compute() { + return getArgumentTypes(); + } + }, getSubstitutor(false)); + } + + private T computeForOverloadedCandidate(final Computable computable, final PsiSubstitutor substitutor) { + Map map = CURRENT_CANDIDATE.get(); + if (map == null) { + map = ContainerUtil.createConcurrentWeakMap(); + CURRENT_CANDIDATE.set(map); + } + final CurrentCandidateProperties alreadyThere = map.put(getMarkerList(), + new CurrentCandidateProperties(getElement(), substitutor, isVarargs(), true)); + try { + return computable.compute(); + } + finally { + if (alreadyThere == null) { + map.remove(getMarkerList()); + } else { + map.put(getMarkerList(), alreadyThere); + } + } + } + @NotNull public PsiSubstitutor getSiteSubstitutor() { PsiSubstitutor incompleteSubstitutor = super.getSubstitutor(); diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java index 64169e127a6c..228e97f116aa 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java @@ -735,7 +735,12 @@ public class ControlFlowUtil { if (lastInstruction instanceof GoToInstruction && ((GoToInstruction)lastInstruction).role == BranchingInstruction.Role.END && !((GoToInstruction)lastInstruction).isReturn) { - lastOffset--; + if (((GoToInstruction)lastInstruction).offset == startOffset) { + lastOffset = -1; + } + else { + lastOffset--; + } } if (lastOffset >= 0) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java index aa389214205a..6f31641ed805 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java @@ -35,11 +35,11 @@ import com.intellij.psi.util.PsiModificationTracker; import com.intellij.reference.SoftReference; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Processor; -import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import java.util.*; @@ -95,9 +95,14 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return null; } - for (PsiElementFinder finder : finders()) { + PsiElementFinder[] finders = finders(); + Condition classesFilter = getFilterFromFinders(scope, finders); + + for (PsiElementFinder finder : finders) { PsiClass aClass = finder.findClass(qualifiedName, scope); - if (aClass != null) return aClass; + if (aClass != null && (classesFilter == null || classesFilter.value(aClass))) { + return aClass; + } } return null; @@ -131,13 +136,30 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { return findClassesInDumbMode(qualifiedName, scope); } - List classes = new SmartList(); - for (PsiElementFinder finder : finders()) { + PsiElementFinder[] finders = finders(); + Condition classesFilter = getFilterFromFinders(scope, finders); + + List result = null; + for (PsiElementFinder finder : finders) { PsiClass[] finderClasses = finder.findClasses(qualifiedName, scope); - ContainerUtil.addAll(classes, finderClasses); + if (finderClasses.length != 0) { + if (result == null) result = new ArrayList(finderClasses.length); + filterClassesAndAppend(classesFilter, finderClasses, result); + } } - return classes.toArray(new PsiClass[classes.size()]); + return result == null || result.isEmpty() ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); + } + + private static Condition getFilterFromFinders(@NotNull GlobalSearchScope scope, @NotNull PsiElementFinder[] finders) { + Condition filter = null; + for (PsiElementFinder finder : finders) { + Condition finderFilter = finder.getClassesFilter(scope); + if (finderFilter != null) { + filter = filter == null ? finderFilter : Conditions.and(filter, finderFilter); + } + } + return filter; } private boolean shouldUseSlowResolve() { @@ -231,17 +253,35 @@ public class JavaPsiFacadeImpl extends JavaPsiFacadeEx { @NotNull public PsiClass[] getClasses(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { + PsiElementFinder[] finders = filteredFinders(); + Condition classesFilter = getFilterFromFinders(scope, finders); + List result = null; - for (PsiElementFinder finder : filteredFinders()) { + for (PsiElementFinder finder : finders) { PsiClass[] classes = finder.getClasses(psiPackage, scope); if (classes.length == 0) continue; - if (result == null) result = new ArrayList(); - ContainerUtil.addAll(result, classes); + if (result == null) result = new ArrayList(classes.length); + filterClassesAndAppend(classesFilter, classes, result); } return result == null ? PsiClass.EMPTY_ARRAY : result.toArray(new PsiClass[result.size()]); } + private static void filterClassesAndAppend(@Nullable Condition classesFilter, + @NotNull PsiClass[] classes, + @NotNull List result) { + if (classesFilter == null) { + ContainerUtil.addAll(result, classes); + } + else { + for (PsiClass psiClass : classes) { + if (classesFilter.value(psiClass)) { + result.add(psiClass); + } + } + } + } + @NotNull public PsiFile[] getPackageFiles(@NotNull PsiPackage psiPackage, @NotNull GlobalSearchScope scope) { Condition filter = null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java index a825e7cd7281..d0a665a9e2e4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java @@ -50,6 +50,7 @@ import com.intellij.util.containers.MostlySingularMultiMap; import com.intellij.util.indexing.IndexingDataKeys; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; @@ -314,7 +315,12 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava final PsiElement resolved = statement.resolve(); if (resolved instanceof PsiClass) { processor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, statement); - if (!processor.execute(resolved, state)) return false; + final PsiClass containingClass = ((PsiClass)resolved).getContainingClass(); + if (containingClass != null && containingClass.hasTypeParameters()) { + if (!processor.execute(resolved, state.put(PsiSubstitutor.KEY, + createRawSubstitutor(containingClass)))) return false; + } + else if (!processor.execute(resolved, state)) return false; } } } @@ -385,6 +391,11 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava return true; } + @NotNull + private static PsiSubstitutor createRawSubstitutor(PsiClass containingClass) { + return JavaPsiFacade.getElementFactory(containingClass.getProject()).createRawSubstitutor(containingClass); + } + private static boolean processOnDemandTarget(PsiElement target, PsiScopeProcessor processor, ResolveState substitutor, PsiElement place) { if (target instanceof PsiPackage) { if (!target.processDeclarations(processor, substitutor, null, place)) { @@ -393,6 +404,10 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava } else if (target instanceof PsiClass) { PsiClass[] inners = ((PsiClass)target).getInnerClasses(); + if (((PsiClass)target).hasTypeParameters()) { + substitutor = substitutor.put(PsiSubstitutor.KEY, createRawSubstitutor((PsiClass)target)); + } + for (PsiClass inner : inners) { if (!processor.execute(inner, substitutor)) return false; } @@ -494,8 +509,18 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava @Override public boolean process(SymbolCollectingProcessor.ResultWithContext result) { - myProcessor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, result.getFileContext()); - return myProcessor.execute(result.getElement(), myState); + final PsiElement context = result.getFileContext(); + myProcessor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, context); + final PsiNamedElement element = result.getElement(); + + if (element instanceof PsiClass && context instanceof PsiImportStatement) { + final PsiClass containingClass = ((PsiClass)element).getContainingClass(); + if (containingClass != null && containingClass.hasTypeParameters()) { + return myProcessor.execute(element, myState.put(PsiSubstitutor.KEY, createRawSubstitutor(containingClass))); + } + } + + return myProcessor.execute(element, myState); } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java index 4ffc804573ae..5755a53c69ef 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java @@ -422,16 +422,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ (method.getCurrentFileResolveScope() instanceof PsiImportStaticStatement ? 0 : 1); } - @NotNull - private PsiType[] getActualParameterTypes() { - PsiType[] types = myActualParameterTypes; - if (types == null) { - LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); - myActualParameterTypes = types = getArgumentTypes(); - } - return types; - } - private int getActualParametersLength() { if (myActualParameterTypes == null) { LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList); @@ -440,11 +430,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ return myActualParameterTypes.length; } - @NotNull - protected PsiType[] getArgumentTypes() { - return ((PsiExpressionList)myArgumentsList).getExpressionTypes(); - } - private enum Specifics { FIRST, SECOND, @@ -509,20 +494,23 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{ boolean sameBoxing = true; int[] boxingHappened = new int[2]; + final PsiType[] argTypes1 = myActualParameterTypes != null ? myActualParameterTypes : info1.getPertinentArgumentTypes(); + final PsiType[] argTypes2 = myActualParameterTypes != null ? myActualParameterTypes : info2.getPertinentArgumentTypes(); for (int i = 0; i < types1.length; i++) { ProgressManager.checkCanceled(); PsiType type1 = classSubstitutor1.substitute(types1[i]); PsiType type2 = classSubstitutor2.substitute(types2[i]); - PsiType argType = i < getActualParameterTypes().length ? getActualParameterTypes()[i] : null; + final PsiType argType1 = i < getActualParametersLength() ? argTypes1[i] : null; + final PsiType argType2 = i < getActualParametersLength() ? argTypes2[i] : null; boolean boxingInFirst = false; - if (isBoxingHappened(argType, type1, languageLevel)) { + if (isBoxingHappened(argType1, type1, languageLevel)) { boxingHappened[0] += 1; boxingInFirst = true; } boolean boxingInSecond = false; - if (isBoxingHappened(argType, type2, languageLevel)) { + if (isBoxingHappened(argType2, type2, languageLevel)) { boxingHappened[1] += 1; boxingInSecond = true; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java new file mode 100644 index 000000000000..71f2a5e58a71 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class1.java @@ -0,0 +1,9 @@ +package p; + +import p2.GenericClass; + +public class Class1 extends GenericClass { + public void map(InnerClass context) { + Class2.test(context); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java new file mode 100644 index 000000000000..10506b456976 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p/Class2.java @@ -0,0 +1,10 @@ +package p; + +import p2.GenericClass.InnerClass; + +public class Class2 { + + public static boolean test(InnerClass context) { + return true; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java new file mode 100644 index 000000000000..21c284bbd1b0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/raw/p2/GenericClass.java @@ -0,0 +1,6 @@ +package p2; + +public class GenericClass { + public class InnerClass { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java new file mode 100644 index 000000000000..71f2a5e58a71 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class1.java @@ -0,0 +1,9 @@ +package p; + +import p2.GenericClass; + +public class Class1 extends GenericClass { + public void map(InnerClass context) { + Class2.test(context); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java new file mode 100644 index 000000000000..55941a9b084f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p/Class2.java @@ -0,0 +1,10 @@ +package p; + +import p2.GenericClass.*; + +public class Class2 { + + public static boolean test(InnerClass context) { + return true; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java new file mode 100644 index 000000000000..21c284bbd1b0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/rawOnDemand/p2/GenericClass.java @@ -0,0 +1,6 @@ +package p2; + +public class GenericClass { + public class InnerClass { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java new file mode 100644 index 000000000000..d81a7a47e68f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/InfiniteLoopAndValueCompatibility.java @@ -0,0 +1,14 @@ +import java.io.Reader; +import java.io.StringReader; +import java.util.concurrent.Callable; + +class Test { + public static final void main(String[] args) throws Exception { + Reader r = new StringReader("Elvis lives!"); + Callable c1 = () -> { + while (true) { + r.read(); + } + }; + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java new file mode 100644 index 000000000000..14316e0154a9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/MultipleOverloadsWithNestedGeneric.java @@ -0,0 +1,9 @@ +import java.lang.String; + +abstract class Test { + abstract T get(); + + void foo() { + String.valueOf(get()); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log new file mode 100644 index 000000000000..98d7347e73f2 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Client.class +out/production/ChangeLambdaSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeLambdaSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log new file mode 100644 index 000000000000..74c5f74e7cc3 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeLambdaTargetReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..83badb8b4311 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(()-> repo.getStorages()); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeLambdaTargetReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log new file mode 100644 index 000000000000..19e7ce03cf1f --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Repository.class +End of files +Compiling files: +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeMethodRefReturnType/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new new file mode 100644 index 000000000000..f70ad61f7ea8 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeMethodRefReturnType/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.Collection; + +public class Repository { + public Collection getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log new file mode 100644 index 000000000000..4b61261611d1 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Client.class +out/production/ChangeSAMMethodSignature/ppp/DataProvider.class +out/production/ChangeSAMMethodSignature/ppp/Repository.class +End of files +Compiling files: +src/ppp/Client.java +src/ppp/DataProvider.java +src/ppp/Repository.java +End of files +Cleaning output files: +out/production/ChangeSAMMethodSignature/ppp/Main.class +End of files +Compiling files: +src/ppp/Main.java +End of files \ No newline at end of file diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java new file mode 100644 index 000000000000..463efb86e87a --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData()) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new new file mode 100644 index 000000000000..bcef65b859f9 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Client.java.new @@ -0,0 +1,8 @@ +package ppp; +public class Client { + public void execute(DataProvider data) { + for (String s : data.getData(10)) { + System.out.println(s); + } + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java new file mode 100644 index 000000000000..867c0ec1b227 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new new file mode 100644 index 000000000000..48cad7204add --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/DataProvider.java.new @@ -0,0 +1,7 @@ +package ppp; + +import java.util.Collection; + +public interface DataProvider { + Collection getData(int param); +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java new file mode 100644 index 000000000000..3f1e0382a832 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Main.java @@ -0,0 +1,9 @@ +package ppp; + +public class Main { + public static void main(String[] args) { + Repository repo = new Repository(); + Client client = new Client(); + client.execute(repo::getStorages); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java new file mode 100644 index 000000000000..ff7c586d6b38 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages() { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new new file mode 100644 index 000000000000..29625a07d866 --- /dev/null +++ b/java/java-tests/testData/compileServer/incremental/methodProperties/changeSAMMethodSignature/src/ppp/Repository.java.new @@ -0,0 +1,10 @@ +package ppp; + +import java.util.Arrays; +import java.util.List; + +public class Repository { + public List getStorages(int param) { + return Arrays.asList("a", "b", "c"); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java index dcac1068a631..19e3b245fa89 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingJdk7Test.java @@ -63,6 +63,14 @@ public class AdvHighlightingJdk7Test extends DaemonAnalyzerTestCase { doTest(BASE_PATH + "staticImportConflict/UsageMixed.java", BASE_PATH + "/staticImportConflict", false, false); } + public void testRawInnerClassImport() throws Exception { + doTest(BASE_PATH + "raw/p/Class1.java", BASE_PATH + "/raw", false, false); + } + + public void testRawInnerClassImportOnDemand() throws Exception { + doTest(BASE_PATH + "rawOnDemand/p/Class1.java", BASE_PATH + "/rawOnDemand", false, false); + } + //ambiguous method calls private void doTestAmbiguous() throws Exception { doTestAmbiguous(JavaSdkVersion.JDK_1_7); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java index 696da0e64078..6a76895714b4 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java @@ -185,6 +185,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testInfiniteLoopAndValueCompatibility() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java index 5ec359058511..d2ff3ce3ae6f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java @@ -98,6 +98,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase { }).assertTiming(); } + public void testMultipleOverloadsWithNestedGeneric() throws Exception { + doTest(false); + } + private void doTest() { doTest(true); } diff --git a/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java b/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java index 676e570e7aa5..fce6d92714f8 100644 --- a/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/search/SearchInLibsTest.java @@ -1,6 +1,23 @@ +/* + * Copyright 2000-2015 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; +import com.intellij.find.FindModel; +import com.intellij.find.impl.FindInProjectUtil; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; @@ -9,31 +26,15 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.testFramework.PsiTestCase; import com.intellij.testFramework.PsiTestUtil; +import com.intellij.usageView.UsageInfo; +import com.intellij.util.CommonProcessors; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; +import java.util.*; public class SearchInLibsTest extends PsiTestCase { - public void testSearchInProject() throws Exception { - doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); - doTest("LibraryClass1", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); - doTest("LibraryClass2", new String[]{}, GlobalSearchScope.projectScope(myProject)); - } - - public void testSearchInLibs() throws Exception { - doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); - doTest("LibraryClass1", new String[]{"LibraryClass2.java", "ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); - doTest("LibraryClass2", new String[]{"LibraryClass1.java"}, GlobalSearchScope.allScope(myProject)); - } - - public void testInnerSourceRoot() throws Exception { - doTest("ProjectClass2", new String[]{"ProjectClass2.java"}, GlobalSearchScope.projectScope(myProject)); - } - - private void doTest(String classNameToSearch, String[] expectedFileNames, SearchScope scope) throws Exception { - + @Override + protected void setUp() throws Exception { + super.setUp(); String root = JavaTestUtil.getJavaTestDataPath() + "/psi/search/searchInLibs"; VirtualFile rootFile = PsiTestUtil.createTestProjectStructure(myProject, myModule, root, myFilesToDelete, false); @@ -52,15 +53,59 @@ public class SearchInLibsTest extends PsiTestCase { PsiTestUtil.addSourceRoot(myModule, projectRoot); PsiTestUtil.addSourceRoot(myModule, innerSourceRoot); ModuleRootModificationUtil.addModuleLibrary(myModule, "lib", Collections.singletonList(libClassesRoot.getUrl()), Collections.singletonList(libSrcRoot.getUrl())); + } + public void testFindUsagesInProject() throws Exception { + doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); + } + public void testFindUsagesInProject1() throws Exception { + doTest("LibraryClass1", new String[]{"ProjectClass.java"}, GlobalSearchScope.projectScope(myProject)); + } + public void testFindUsagesInProject2() throws Exception { + doTest("LibraryClass2", new String[]{}, GlobalSearchScope.projectScope(myProject)); + } + + public void testFindUsagesInLibs() throws Exception { + doTest("ProjectClass", new String[]{"ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); + } + public void testFindUsagesInLibs1() throws Exception { + doTest("LibraryClass1", new String[]{"LibraryClass2.java", "ProjectClass.java"}, GlobalSearchScope.allScope(myProject)); + } + public void testFindUsagesInLibs2() throws Exception { + doTest("LibraryClass2", new String[]{"LibraryClass1.java"}, GlobalSearchScope.allScope(myProject)); + } + + public void testFindInPathInLibraryDirActuallySearchesInTheirSourcesToo() throws Exception { + FindModel model = new FindModel(); + final PsiClass aClass = myJavaFacade.findClass("LibraryClass1"); + assertNotNull(aClass); + model.setDirectoryName(aClass.getContainingFile().getContainingDirectory().getVirtualFile().getPath()); + model.setCaseSensitive(true); + model.setCustomScope(false); + model.setStringToFind("LibraryClass1"); + model.setProjectScope(false); + + List usages = new ArrayList(); + FindInProjectUtil.findUsages(model, aClass.getContainingFile().getContainingDirectory(), getProject(), + new CommonProcessors.CollectProcessor( + usages), FindInProjectUtil + .setupProcessPresentation(getProject(), false, FindInProjectUtil.setupViewPresentation(false, model))); + + assertEquals(2, usages.size()); + } + + public void testInnerSourceRoot() throws Exception { + doTest("ProjectClass2", new String[]{"ProjectClass2.java"}, GlobalSearchScope.projectScope(myProject)); + } + + private void doTest(String classNameToSearch, String[] expectedFileNames, SearchScope scope) throws Exception { final PsiClass aClass = myJavaFacade.findClass(classNameToSearch); assertNotNull(aClass); PsiReference[] refs = ReferencesSearch.search(aClass, scope, false).toArray(new PsiReference[0]); ArrayList files = new ArrayList(); - for (int i = 0; i < refs.length; i++) { - PsiReference ref = refs[i]; + for (PsiReference ref : refs) { PsiFile file = ref.getElement().getContainingFile(); if (!files.contains(file)) { files.add(file); @@ -69,19 +114,17 @@ public class SearchInLibsTest extends PsiTestCase { assertEquals("files count", expectedFileNames.length, files.size()); - Collections.sort(files, new Comparator() { + Collections.sort(files, new Comparator() { @Override - public int compare(Object o1, Object o2) { - PsiFile file1 = (PsiFile) o1; - PsiFile file2 = (PsiFile) o2; - return file1.getName().compareTo(file2.getName()); + public int compare(PsiFile o1, PsiFile o2) { + return o1.getName().compareTo(o2.getName()); } }); Arrays.sort(expectedFileNames); for (int i = 0; i < expectedFileNames.length; i++) { String name = expectedFileNames[i]; - PsiFile file = (PsiFile) files.get(i); + PsiFile file = files.get(i); assertEquals(name, file.getName()); } } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java index 137f4527b5a8..a67fa2563769 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassfileAnalyzer.java @@ -19,6 +19,7 @@ import com.intellij.openapi.util.Pair; import gnu.trove.THashMap; import gnu.trove.THashSet; import gnu.trove.TIntHashSet; +import org.jetbrains.annotations.Nullable; import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.signature.SignatureReader; import org.jetbrains.org.objectweb.asm.signature.SignatureVisitor; @@ -34,6 +35,7 @@ import java.util.Set; */ class ClassfileAnalyzer { + public static final String LAMBDA_FACTORY_CLASS = "java/lang/invoke/LambdaMetafactory"; private final DependencyContext myContext; ClassfileAnalyzer(DependencyContext context) { @@ -390,11 +392,11 @@ class ClassfileAnalyzer { } @Override - public FieldVisitor visitField(int access, String n, String desc, String signature, Object value) { + public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { processSignature(signature); if ((access & Opcodes.ACC_SYNTHETIC) == 0) { - myFields.add(new FieldRepr(myContext, access, myContext.get(n), myContext.get(desc), myContext.get(signature), value)); + myFields.add(new FieldRepr(myContext, access, myContext.get(name), myContext.get(desc), myContext.get(signature), value)); } return new FieldVisitor(Opcodes.ASM5) { @@ -504,34 +506,118 @@ class ClassfileAnalyzer { @Override public void visitFieldInsn(int opcode, String owner, String name, String desc) { - final int fieldName = myContext.get(name); - final int fieldOwner = myContext.get(owner); - final int descr = myContext.get(desc); - - if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { - myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); - } - - if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { - addClassUsage(TypeRepr.getType(myContext, descr)); - } - - myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + registerFieldUsage(opcode, owner, name, desc); super.visitFieldInsn(opcode, owner, name, desc); } @Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - final int methodName = myContext.get(name); - final int methodOwner = myContext.get(owner); - - myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); - myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); - addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); - + registerMethodUsage(owner, name, desc); super.visitMethodInsn(opcode, owner, name, desc, itf); } + @Override + public void visitInvokeDynamicInsn(String methodName, String desc, Handle bsm, Object... bsmArgs) { + final Type returnType = Type.getReturnType(desc); + addClassUsage(TypeRepr.getType(myContext, returnType)); + + // common args processing + for (Object arg : bsmArgs) { + if (arg instanceof Type) { + final Type type = (Type)arg; + if (type.getSort() == Type.METHOD) { + for (Type argType : type.getArgumentTypes()) { + addClassUsage(TypeRepr.getType(myContext, argType)); + } + addClassUsage(TypeRepr.getType(myContext, type.getReturnType())); + } + else { + addClassUsage(TypeRepr.getType(myContext, type)); + } + } + else if (arg instanceof Handle) { + processMethodHandle((Handle)arg); + } + } + + if (LAMBDA_FACTORY_CLASS.equals(bsm.getOwner())) { + // This invokeDynamic implements a lambda or method reference usage. + // Need to register method usage for the corresponding SAM-type. + // First three arguments to the bootstrap methods are provided automatically by VM. + // Arguments in args array are expected to be as following: + // [0]: Type: Signature and return type of method to be implemented by the function object. + // [1]: Handle: implementation method handle + // [2]: Type: The signature and return type that should be enforced dynamically at invocation time. May be the same as samMethodType, or may be a specialization of it + // [...]: optional additional arguments + + if (returnType.getSort() == Type.OBJECT && bsmArgs.length >= 3) { + if (bsmArgs[0] instanceof Type) { + final Type samMethodType = (Type)bsmArgs[0]; + if (samMethodType.getSort() == Type.METHOD) { + registerMethodUsage(returnType.getInternalName(), methodName, samMethodType.getDescriptor()); + } + } + } + } + + super.visitInvokeDynamicInsn(methodName, desc, bsm, bsmArgs); + } + + private void processMethodHandle(Handle handle) { + final String memberOwner = handle.getOwner(); + if (myContext.get(memberOwner) != myName) { + // do not register access to own class members + final String memberName = handle.getName(); + final String memberDescriptor = handle.getDesc(); + if (isFieldAccessHandle(handle)) { + final int tag = handle.getTag(); + int opCode; + if (tag == Opcodes.H_GETFIELD) { + opCode = Opcodes.GETFIELD; + } + else if (tag == Opcodes.H_GETSTATIC) { + opCode = Opcodes.GETSTATIC; + } + else if (tag == Opcodes.H_PUTFIELD) { + opCode = Opcodes.PUTFIELD; + } + else if (tag == Opcodes.H_PUTSTATIC) { + opCode = Opcodes.PUTSTATIC; + } + else { + opCode = Opcodes.H_GETFIELD; + } + registerFieldUsage(opCode, memberOwner, memberName, memberDescriptor); + } + else { + registerMethodUsage(memberOwner, memberName, memberDescriptor); + } + } + } + + private void registerFieldUsage(int opcode, String owner, String fName, String desc) { + final int fieldName = myContext.get(fName); + final int fieldOwner = myContext.get(owner); + final int descr = myContext.get(desc); + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + myUsages.add(UsageRepr.createFieldAssignUsage(myContext, fieldName, fieldOwner, descr)); + } + if (opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC) { + addClassUsage(TypeRepr.getType(myContext, descr)); + } + myUsages.add(UsageRepr.createFieldUsage(myContext, fieldName, fieldOwner, descr)); + } + + private void registerMethodUsage(String owner, String name, @Nullable String desc) { + final int methodOwner = myContext.get(owner); + final int methodName = myContext.get(name); + myUsages.add(UsageRepr.createMetaMethodUsage(myContext, methodName, methodOwner)); + if (desc != null) { + myUsages.add(UsageRepr.createMethodUsage(myContext, methodName, methodOwner, desc)); + addClassUsage(TypeRepr.getType(myContext, Type.getReturnType(desc))); + } + } + private void addClassUsage(final TypeRepr.AbstractType type) { TypeRepr.ClassType classType = null; if (type instanceof TypeRepr.ClassType) { @@ -551,6 +637,11 @@ class ClassfileAnalyzer { }; } + private boolean isFieldAccessHandle(Handle handle) { + final int tag = handle.getTag(); + return tag == Opcodes.H_GETFIELD || tag == Opcodes.H_GETSTATIC || tag == Opcodes.H_PUTFIELD || tag == Opcodes.H_PUTSTATIC; + } + @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { if (outerName != null) { diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java index 4525aa74bd4d..f8b4e51ccd52 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java @@ -37,7 +37,9 @@ import org.jetbrains.jps.model.module.JpsModule; import org.jetbrains.jps.model.serialization.PathMacroUtil; import org.jetbrains.jps.util.JpsPathUtil; -import java.io.*; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; /** * @author db @@ -212,6 +214,20 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase { module.addSourceRoot(getUrl(testRootRelativePath), JavaSourceRootType.TEST_SOURCE); } + protected static boolean isRunningOnAtLeastJava(int javaVersion) { + final String versionString = System.getProperty("java.version"); + final String prefix = "1."; + final int startIndex = versionString.startsWith(prefix) ? prefix.length() : 0; + final int dotIndex = versionString.indexOf('.', startIndex); + try { + int version = Integer.parseInt(versionString.substring(startIndex, dotIndex > startIndex? dotIndex : versionString.length())); + return version >= javaVersion; + } + catch (NumberFormatException ignored) { + } + return false; + } + private static class StringProjectBuilderLogger extends ProjectBuilderLoggerBase { private final String myRoot; private StringBuilder myLog; diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java index 28093d91f8b8..839effbe7ac8 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java +++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MethodPropertyTest.java @@ -32,6 +32,42 @@ public class MethodPropertyTest extends IncrementalTestCase { doTest(); } + public void testChangeMethodRefReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaTargetReturnType() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + + public void testChangeLambdaSAMMethodSignature() throws Exception { + if (isRunningOnAtLeastJava(8)) { + doTest(); + } + else { + System.err.println("Skipping test " + getTestName(true) + ": java version 8 or higher required to run it"); + } + } + public void testChangeReturnType1() throws Exception { doTest(); } diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java index 73257051db51..b70622ae2d0d 100644 --- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java +++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java @@ -19,9 +19,7 @@ package com.intellij.analysis; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.ProblemHighlightFilter; import com.intellij.lang.injection.InjectedLanguageManager; -import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -177,6 +175,9 @@ public class AnalysisScope { protected PsiElementVisitor createFileSearcher() { final FileIndex fileIndex = getFileIndex(); final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.setText(AnalysisScopeBundle.message("scanning.scope.progress.title")); + } return new PsiElementVisitor() { @Override @@ -191,12 +192,6 @@ public class AnalysisScope { } if (!shouldHighlightFile(file)) return; myFilesSet.add(virtualFile); - if (indicator != null) { - indicator.setText(AnalysisScopeBundle.message("scanning.scope.progress.title")); - Project project = file.getProject(); - String text = displayProjectRelativePath(virtualFile, project); - indicator.setText2(text); - } } } }; @@ -247,7 +242,7 @@ public class AnalysisScope { } else if (myType == DIRECTORY || myType == PROJECT || myType == MODULES || myType == MODULE || myType == CUSTOM) { myFilesSet = new HashSet(); - accept(createFileSearcher()); + accept(createFileSearcher(), false); } else if (myType == VIRTUAL_FILES) { myFilesSet = new HashSet(); @@ -275,16 +270,23 @@ public class AnalysisScope { public void accept(@NotNull final PsiElementVisitor visitor) { - accept(visitor, !ApplicationManager.getApplication().isReadAccessAllowed()); + accept(visitor, true); } - protected void accept(@NotNull final PsiElementVisitor visitor, final boolean needReadAction) { + private void accept(@NotNull final PsiElementVisitor visitor, final boolean clearResolveCache) { + final boolean needReadAction = !ApplicationManager.getApplication().isReadAccessAllowed(); final PsiManager psiManager = PsiManager.getInstance(myProject); final FileIndex fileIndex = getFileIndex(); accept(new Processor() { @Override public boolean process(VirtualFile file) { - return processFile(file, visitor, fileIndex, psiManager, needReadAction); + if (file.isDirectory()) return true; + if (ProjectCoreUtil.isProjectOrWorkspaceFile(file)) return true; + if (fileIndex.isInContent(file) && (myIncludeTestSource || !fileIndex.isInTestSourceContent(file)) + && !isInGeneratedSources(file, myProject)) { + return processFile(file, visitor, psiManager, needReadAction, clearResolveCache); + } + return true; } }); } @@ -375,20 +377,6 @@ public class AnalysisScope { }); } - private boolean processFile(@NotNull final VirtualFile fileOrDir, - @NotNull final PsiElementVisitor visitor, - @NotNull final FileIndex fileIndex, - @NotNull final PsiManager psiManager, - final boolean needReadAction) { - if (fileOrDir.isDirectory()) return true; - if (ProjectCoreUtil.isProjectOrWorkspaceFile(fileOrDir)) return true; - if (fileIndex.isInContent(fileOrDir) && (myIncludeTestSource || !fileIndex.isInTestSourceContent(fileOrDir)) - && !isInGeneratedSources(fileOrDir, psiManager.getProject())) { - return processFile(fileOrDir, visitor, psiManager, needReadAction); - } - return true; - } - private static boolean isInGeneratedSources(@NotNull VirtualFile file, @NotNull Project project) { for (GeneratedSourcesFilter filter : GeneratedSourcesFilter.EP_NAME.getExtensions()) { if (filter.isGeneratedSource(file, project)) { @@ -398,32 +386,15 @@ public class AnalysisScope { return false; } - private static boolean processFile(@NotNull final VirtualFile fileOrDir, + private static boolean processFile(@NotNull final VirtualFile vFile, @NotNull final PsiElementVisitor visitor, @NotNull final PsiManager psiManager, - final boolean needReadAction) { - final PsiFile file; - - AccessToken accessToken = ReadAction.start(); - try { - if (!fileOrDir.isValid()) return false; - - file = psiManager.findFile(fileOrDir); - if (file == null) { - //skip .class files under src directory - return true; - } - - if (!shouldHighlightFile(file)) return true; - } - finally { - accessToken.finish(); - } - + final boolean needReadAction, + final boolean clearResolveCache) { final Runnable runnable = new Runnable() { @Override public void run() { - doProcessFile(visitor, psiManager, file); + doProcessFile(visitor, psiManager, vFile, clearResolveCache); } }; if (needReadAction && !ApplicationManager.getApplication().isDispatchThread()) { @@ -471,10 +442,18 @@ public class AnalysisScope { } } - private static void doProcessFile(@NotNull PsiElementVisitor visitor, @NotNull PsiManager psiManager, @NotNull PsiFile file) { - file.accept(visitor); - psiManager.dropResolveCaches(); - InjectedLanguageManager.getInstance(file.getProject()).dropFileCaches(file); + private static void doProcessFile(@NotNull PsiElementVisitor visitor, @NotNull PsiManager psiManager, @NotNull VirtualFile vFile, + boolean clearResolveCache) { + if (!vFile.isValid()) return; + + PsiFile psiFile = psiManager.findFile(vFile); + if (psiFile == null || !shouldHighlightFile(psiFile)) return; + + psiFile.accept(visitor); + if (clearResolveCache) { + psiManager.dropResolveCaches(); + InjectedLanguageManager.getInstance(psiManager.getProject()).dropFileCaches(psiFile); + } } protected boolean accept(@NotNull final PsiDirectory dir, @NotNull final Processor processor) { diff --git a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java index a45bc13625a7..37c0b604409c 100644 --- a/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java +++ b/platform/analysis-api/src/com/intellij/psi/search/GlobalSearchScopesCore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -57,6 +57,18 @@ public class GlobalSearchScopesCore { return new DirectoryScope(project, directory, withSubdirectories); } + @NotNull + public static GlobalSearchScope directoriesScope(@NotNull Project project, boolean withSubdirectories, @NotNull VirtualFile... directories) { + if (directories.length ==1) { + return directoryScope(project, directories[0], withSubdirectories); + } + BitSet withSubdirectoriesBS = new BitSet(directories.length); + if (withSubdirectories) { + withSubdirectoriesBS.set(0, directories.length-1); + } + return new DirectoriesScope(project, directories, withSubdirectoriesBS); + } + public static GlobalSearchScope filterScope(@NotNull Project project, @NotNull NamedScope set) { return new FilterScopeAdapter(project, set); } diff --git a/platform/core-api/src/com/intellij/codeInsight/folding/CodeFoldingSettings.java b/platform/core-api/src/com/intellij/codeInsight/folding/CodeFoldingSettings.java index 747d1de5bebb..9fa501f5aa06 100644 --- a/platform/core-api/src/com/intellij/codeInsight/folding/CodeFoldingSettings.java +++ b/platform/core-api/src/com/intellij/codeInsight/folding/CodeFoldingSettings.java @@ -1,13 +1,28 @@ +/* + * Copyright 2000-2015 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.codeInsight.folding; import com.intellij.openapi.components.ServiceManager; public class CodeFoldingSettings { - @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_IMPORTS = true; - @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_METHODS = false; - @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_FILE_HEADER = true; - @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_DOC_COMMENTS = false; - @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_CUSTOM_FOLDING_REGIONS = false; + public boolean COLLAPSE_IMPORTS = true; + public boolean COLLAPSE_METHODS = false; + public boolean COLLAPSE_FILE_HEADER = true; + public boolean COLLAPSE_DOC_COMMENTS = false; + public boolean COLLAPSE_CUSTOM_FOLDING_REGIONS = false; public static CodeFoldingSettings getInstance() { return ServiceManager.getService(CodeFoldingSettings.class); diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java b/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java index bd69a0d863c3..f826b230f3e9 100644 --- a/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java +++ b/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,7 +29,7 @@ import java.util.Map; * @author peter */ public class CharsetUtil { - @SuppressWarnings("MismatchedQueryAndUpdenateOfCollection") + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private static final Map ourSupportsCharsetDetection = new ConcurrentFactoryMap() { @Nullable @Override diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 8de2d02f1c07..0bbc064b3cab 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -21,6 +21,8 @@ import com.intellij.diff.DiffRequestFactory; import com.intellij.diff.requests.DiffRequest; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.diff.DiffBundle; +import com.intellij.openapi.project.DefaultProjectFactory; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,6 +61,7 @@ public class DiffApplication extends ApplicationStarterBase { file2.refresh(false, true); DiffRequest request = DiffRequestFactory.getInstance().createFromFiles(null, file1, file2); - DiffManagerEx.getInstance().showDiffBuiltin(null, request, DiffDialogHints.MODAL); + Project project = DefaultProjectFactory.getInstance().getDefaultProject(); + DiffManagerEx.getInstance().showDiffBuiltin(project, request, DiffDialogHints.MODAL); } } diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java index 7f3cfef27b3a..fa1b888a3917 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java @@ -334,5 +334,25 @@ public class DiffIterableUtil { this.val1 = val1; this.val2 = val2; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + IntPair pair = (IntPair)o; + + if (val1 != pair.val1) return false; + if (val2 != pair.val2) return false; + + return true; + } + + @Override + public int hashCode() { + int result = val1; + result = 31 * result + val2; + return result; + } } } diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java index 1a39c5b5e658..eace4af9f1ee 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffRequestProcessor.java @@ -34,6 +34,7 @@ import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.diff.util.DiffUserDataKeysEx; import com.intellij.diff.util.DiffUserDataKeysEx.ScrollToPolicy; import com.intellij.diff.util.DiffUtil; +import com.intellij.ide.DataManager; import com.intellij.ide.impl.DataManagerImpl; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; @@ -242,7 +243,7 @@ public abstract class DiffRequestProcessor implements Disposable { IdRunnable task = new IdRunnable(this) { @Override public void run() { - if (myApplyData == null) return; + if (myApplyData == null || myDisposed) return; doApplyRequest(myApplyData.request, myApplyData.force, myApplyData.scrollToChangePolicy); myApplyData = null; } @@ -429,7 +430,9 @@ public abstract class DiffRequestProcessor implements Disposable { protected void buildToolbar(@Nullable List viewerActions) { ActionGroup group = collectToolbarActions(viewerActions); ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.DIFF_TOOLBAR, group, true); - toolbar.setTargetComponent(myMainPanel); + + DataManager.registerDataProvider(toolbar.getComponent(), myMainPanel); + toolbar.setTargetComponent(toolbar.getComponent()); myToolbarPanel.setContent(toolbar.getComponent()); for (AnAction action : group.getChildren(null)) { diff --git a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java index f7b4dd7d1a56..8d9cff475107 100644 --- a/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java +++ b/platform/diff-impl/src/com/intellij/diff/impl/DiffWindowBase.java @@ -19,8 +19,7 @@ import com.intellij.diff.DiffDialogHints; import com.intellij.diff.util.DiffUserDataKeys; import com.intellij.diff.util.DiffUtil; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.CustomShortcutSet; -import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.WindowWrapper; @@ -73,8 +72,7 @@ public abstract class DiffWindowBase { public void actionPerformed(final AnActionEvent e) { myWrapper.close(); } - }.registerCustomShortcutSet(new CustomShortcutSet(KeymapManager.getInstance().getActiveKeymap().getShortcuts("CloseContent")), - myProcessor.getComponent()); + }.registerCustomShortcutSet(CommonShortcuts.getCloseActiveWindow(), myProcessor.getComponent()); } public void show() { diff --git a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java index 75f496f570c9..a4dd1e76416f 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/dir/DirDiffViewer.java @@ -38,6 +38,8 @@ import com.intellij.openapi.diff.impl.dir.DirDiffFrame; import com.intellij.openapi.diff.impl.dir.DirDiffPanel; import com.intellij.openapi.diff.impl.dir.DirDiffTableModel; import com.intellij.openapi.diff.impl.dir.DirDiffWindow; +import com.intellij.openapi.project.DefaultProjectFactory; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -63,7 +65,11 @@ class DirDiffViewer implements FrameDiffTool.DiffViewer { List contents = request.getContents(); DiffElement element1 = createDiffElement(contents.get(0)); DiffElement element2 = createDiffElement(contents.get(1)); - DirDiffTableModel model = new DirDiffTableModel(context.getProject(), element1, element2, new DirDiffSettings()); + + Project project = context.getProject(); + if (project == null) project = DefaultProjectFactory.getInstance().getDefaultProject(); + + DirDiffTableModel model = new DirDiffTableModel(project, element1, element2, new DirDiffSettings()); myDirDiffPanel = new DirDiffPanel(model, new DirDiffWindow((DirDiffFrame)null) { @Override diff --git a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideFragmentBuilder.java b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideFragmentBuilder.java index ed7b1942d4e4..a6ed08b79e81 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideFragmentBuilder.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/fragmented/OnesideFragmentBuilder.java @@ -69,7 +69,7 @@ public class OnesideFragmentBuilder { processEquals(fragment.getStartLine1() - 1, fragment.getStartLine2() - 1); processChanged(fragment); } - processEquals(getLineCount(myDocument1) - 1, getLineCount(myDocument1) - 2); + processEquals(getLineCount(myDocument1) - 1, getLineCount(myDocument2) - 1); } private void processEquals(int endLine1, int endLine2) { diff --git a/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java b/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java index 8b799509a1fd..573dbd7a4345 100644 --- a/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java +++ b/platform/diff-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffTableModel.java @@ -82,7 +82,7 @@ public class DirDiffTableModel extends AbstractTableModel implements DirDiffMode public static final String EMPTY_STRING = " "; private DirDiffPanel myPanel; - public DirDiffTableModel(Project project, DiffElement src, DiffElement trg, DirDiffSettings settings) { + public DirDiffTableModel(@NotNull Project project, DiffElement src, DiffElement trg, DirDiffSettings settings) { myProject = project; mySettings = settings; mySrc = src; diff --git a/platform/diff-impl/tests/com/intellij/diff/comparison/AutoTestCase.java b/platform/diff-impl/tests/com/intellij/diff/comparison/AutoTestCase.java index 2f3b25f7c386..ac78afb98444 100644 --- a/platform/diff-impl/tests/com/intellij/diff/comparison/AutoTestCase.java +++ b/platform/diff-impl/tests/com/intellij/diff/comparison/AutoTestCase.java @@ -15,8 +15,12 @@ */ package com.intellij.diff.comparison; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.testFramework.UsefulTestCase; +import com.intellij.util.text.CharSequenceSubSequence; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.lang.reflect.Field; import java.util.Map; @@ -68,4 +72,37 @@ public abstract class AutoTestCase extends UsefulTestCase { return -1; } } + + @NotNull + public static String textToReadableFormat(@Nullable Document text) { + if (text == null) return "null"; + return "'" + text.getCharsSequence().toString().replace('\n', '*').replace('\t', '+') + "'"; + } + + public static void assertEqualsCharSequences(@NotNull CharSequence chunk1, @NotNull CharSequence chunk2, + boolean ignoreSpaces, boolean skipLastNewline) { + if (ignoreSpaces) { + assertTrue(StringUtil.equalsIgnoreWhitespaces(chunk1, chunk2)); + } + else { + if (skipLastNewline) { + CharSequence chunk12 = StringUtil.endsWithChar(chunk1, '\n') ? trimLastChar(chunk1) : null; + CharSequence chunk22 = StringUtil.endsWithChar(chunk2, '\n') ? trimLastChar(chunk2) : null; + + if (StringUtil.equals(chunk1, chunk2)) return; + if (StringUtil.equals(chunk12, chunk2)) return; + if (StringUtil.equals(chunk1, chunk22)) return; + + assertTrue(false); + } + else { + assertTrue(StringUtil.equals(chunk1, chunk2)); + } + } + } + + @NotNull + private static CharSequence trimLastChar(@NotNull CharSequence text) { + return new CharSequenceSubSequence(text, 0, text.length() - 1); + } } diff --git a/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.java b/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.java index fbbf3af54861..9abb32c62a84 100644 --- a/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.java +++ b/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.java @@ -22,11 +22,8 @@ import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.progress.DumbProgressIndicator; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.HashMap; -import com.intellij.util.text.CharSequenceSubSequence; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -37,8 +34,8 @@ public class ComparisonUtilAutoTest extends AutoTestCase { private static DumbProgressIndicator INDICATOR = DumbProgressIndicator.INSTANCE; private static ComparisonManager myComparisonManager = new ComparisonManagerImpl(); - private static int CHAR_COUNT = 12; - private static Map CHAR_TABLE = initCharMap(); + private static final int CHAR_COUNT = 12; + private static final Map CHAR_TABLE = initCharMap(); private boolean myOldRegistryValue; @@ -173,8 +170,8 @@ public class ComparisonUtilAutoTest extends AutoTestCase { System.out.println("Policy: " + policy); System.out.println("I: " + i); System.out.println("Current seed: " + getLastSeed()); - System.out.println("Text1: " + normalize(text1)); - System.out.println("Text2: " + normalize(text2)); + System.out.println("Text1: " + textToReadableFormat(text1)); + System.out.println("Text2: " + textToReadableFormat(text2)); System.out.println("Debug Data: " + debugData.get()); if (e instanceof Error) throw (Error)e; if (e instanceof Exception) throw (Exception)e; @@ -320,41 +317,14 @@ public class ComparisonUtilAutoTest extends AutoTestCase { CharSequence chunk1 = text1.subSequence(last1, fragment.getStartOffset1()); CharSequence chunk2 = text2.subSequence(last2, fragment.getStartOffset2()); - check(chunk1, chunk2, ignoreSpaces, skipNewline); + assertEqualsCharSequences(chunk1, chunk2, ignoreSpaces, skipNewline); last1 = fragment.getEndOffset1(); last2 = fragment.getEndOffset2(); } CharSequence chunk1 = text1.subSequence(last1, text1.length()); CharSequence chunk2 = text2.subSequence(last2, text2.length()); - check(chunk1, chunk2, ignoreSpaces, skipNewline); - } - - private static void check(@NotNull CharSequence chunk1, @NotNull CharSequence chunk2, - boolean ignoreSpaces, boolean skipNewline) { - if (ignoreSpaces) { - assertTrue(StringUtil.equalsIgnoreWhitespaces(chunk1, chunk2)); - } - else { - if (skipNewline) { - CharSequence chunk12 = StringUtil.endsWithChar(chunk1, '\n') ? trimLastChar(chunk1) : null; - CharSequence chunk22 = StringUtil.endsWithChar(chunk2, '\n') ? trimLastChar(chunk2) : null; - - if (StringUtil.equals(chunk1, chunk2)) return; - if (StringUtil.equals(chunk12, chunk2)) return; - if (StringUtil.equals(chunk1, chunk22)) return; - - assertTrue(false); - } - else { - assertTrue(StringUtil.equals(chunk1, chunk2)); - } - } - } - - @NotNull - private static CharSequence trimLastChar(@NotNull CharSequence text) { - return new CharSequenceSubSequence(text, 0, text.length() - 1); + assertEqualsCharSequences(chunk1, chunk2, ignoreSpaces, skipNewline); } @NotNull @@ -383,12 +353,6 @@ public class ComparisonUtilAutoTest extends AutoTestCase { return map; } - @NotNull - private static String normalize(@Nullable Document text) { - if (text == null) return "null"; - return "'" + text.getCharsSequence().toString().replace('\n', '*').replace('\t', '+') + "'"; - } - @NotNull private static CharSequence subsequence(@NotNull Document document, int start, int end) { return document.getCharsSequence().subSequence(start, end); diff --git a/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderAutoTest.java b/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderAutoTest.java new file mode 100644 index 000000000000..20fb310c3daa --- /dev/null +++ b/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderAutoTest.java @@ -0,0 +1,216 @@ +/* + * Copyright 2000-2015 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.diff.tools.fragmented; + +import com.intellij.diff.comparison.AutoTestCase; +import com.intellij.diff.comparison.ComparisonManager; +import com.intellij.diff.comparison.ComparisonManagerImpl; +import com.intellij.diff.comparison.ComparisonPolicy; +import com.intellij.diff.comparison.iterables.DiffIterableUtil; +import com.intellij.diff.fragments.LineFragment; +import com.intellij.diff.util.Side; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.progress.DumbProgressIndicator; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.HashMap; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class OnesideFragmentBuilderAutoTest extends AutoTestCase { + private static ComparisonManager myComparisonManager = new ComparisonManagerImpl(); + + private static final int CHAR_COUNT = 12; + private static final Map CHAR_TABLE = initCharMap(); + + public void test() throws Exception { + doTest(System.currentTimeMillis(), 30, 30); + } + + public void doTest(long seed, int runs, int maxLength) throws Exception { + myRng.setSeed(seed); + + ComparisonPolicy policy = null; + Side masterSide = null; + + for (int i = 0; i < runs; i++) { + if (i % 1000 == 0) System.out.println(i); + Document text1 = null; + Document text2 = null; + try { + rememberSeed(); + + text1 = generateText(maxLength); + text2 = generateText(maxLength); + + for (Side side : Side.values()) { + for (ComparisonPolicy comparisonPolicy : ComparisonPolicy.values()) { + policy = comparisonPolicy; + masterSide = side; + doTest(text1, text2, policy, masterSide); + } + } + } + catch (Throwable e) { + System.out.println("Seed: " + seed); + System.out.println("Runs: " + runs); + System.out.println("MaxLength: " + maxLength); + System.out.println("Policy: " + policy); + System.out.println("Current side: " + masterSide); + System.out.println("I: " + i); + System.out.println("Current seed: " + getLastSeed()); + System.out.println("Text1: " + textToReadableFormat(text1)); + System.out.println("Text2: " + textToReadableFormat(text2)); + if (e instanceof Error) throw (Error)e; + if (e instanceof Exception) throw (Exception)e; + throw new Exception(e); + } + } + } + + public void doTest(@NotNull Document document1, @NotNull Document document2, @NotNull ComparisonPolicy policy, @NotNull Side masterSide) { + CharSequence sequence1 = document1.getCharsSequence(); + CharSequence sequence2 = document2.getCharsSequence(); + + List fragments = myComparisonManager.compareLinesInner(sequence1, sequence2, + policy, DumbProgressIndicator.INSTANCE); + + OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, true, masterSide); + builder.exec(); + + boolean ignoreWhitespaces = policy != ComparisonPolicy.DEFAULT; + CharSequence text = builder.getText(); + List blocks = builder.getBlocks(); + LineNumberConvertor convertor = builder.getConvertor(); + List changedLines = builder.getChangedLines(); + List ranges = builder.getRanges(); + + // both documents - before and after - should be subsequence of result text. + assertTrue(isSubsequence(text, sequence1, ignoreWhitespaces)); + assertTrue(isSubsequence(text, sequence2, ignoreWhitespaces)); + + // all changes should be inside ChangedLines + for (LineFragment fragment : fragments) { + int startLine1 = fragment.getStartLine1(); + int endLine1 = fragment.getEndLine1(); + int startLine2 = fragment.getStartLine2(); + int endLine2 = fragment.getEndLine2(); + + for (int i = startLine1; i < endLine1; i++) { + int targetLine = convertor.convertInv1(i); + assertTrue(targetLine != -1); + assertTrue(isLineChanged(targetLine, changedLines)); + } + for (int i = startLine2; i < endLine2; i++) { + int targetLine = convertor.convertInv2(i); + assertTrue(targetLine != -1); + assertTrue(isLineChanged(targetLine, changedLines)); + } + } + + // changed fragments and changed blocks should have same content + assertEquals(blocks.size(), fragments.size()); + for (int i = 0; i < fragments.size(); i++) { + LineFragment fragment = fragments.get(i); + ChangedBlock block = blocks.get(i); + + CharSequence fragment1 = sequence1.subSequence(fragment.getStartOffset1(), fragment.getEndOffset1()); + CharSequence fragment2 = sequence2.subSequence(fragment.getStartOffset2(), fragment.getEndOffset2()); + + CharSequence block1 = text.subSequence(block.getStartOffset1(), block.getEndOffset1()); + CharSequence block2 = text.subSequence(block.getStartOffset2(), block.getEndOffset2()); + + assertEqualsCharSequences(fragment1, block1, ignoreWhitespaces, true); + assertEqualsCharSequences(fragment2, block2, ignoreWhitespaces, true); + } + + // ranges should have exact same content + for (HighlightRange range : ranges) { + CharSequence sideSequence = range.getSide().select(sequence1, sequence2); + CharSequence baseRange = text.subSequence(range.getBase().getStartOffset(), range.getBase().getEndOffset()); + CharSequence sideRange = sideSequence.subSequence(range.getChanged().getStartOffset(), range.getChanged().getEndOffset()); + assertTrue(StringUtil.equals(baseRange, sideRange)); + } + } + + private static boolean isSubsequence(@NotNull CharSequence text, @NotNull CharSequence sequence, boolean ignoreWhitespaces) { + int index1 = 0; + int index2 = 0; + + while (index2 < sequence.length()) { + char c2 = sequence.charAt(index2); + if (c2 == '\n' || + StringUtil.isWhiteSpace(c2) && ignoreWhitespaces) { + index2++; + continue; + } + + assertTrue(index1 < text.length()); + char c1 = text.charAt(index1); + if (c1 == '\n' || + StringUtil.isWhiteSpace(c1) && ignoreWhitespaces) { + index1++; + continue; + } + + if (c1 == c2) { + index1++; + index2++; + } + else { + index1++; + } + } + + return true; + } + + private static boolean isLineChanged(int line, @NotNull List changedLines) { + for (DiffIterableUtil.IntPair changedLine : changedLines) { + if (changedLine.val1 <= line && changedLine.val2 > line) return true; + } + return false; + } + + @NotNull + private Document generateText(int maxLength) { + return new DocumentImpl(generateText(maxLength, CHAR_COUNT, CHAR_TABLE)); + } + + @NotNull + private static Map initCharMap() { + Map map = new HashMap(); + + List characters = new ArrayList(); + characters.add('\n'); + characters.add('\n'); + characters.add('\t'); + characters.add(' '); + characters.add(' '); + characters.add('.'); + characters.add('<'); + characters.add('!'); + + for (int i = 0; i < characters.size(); i++) { + map.put(i, characters.get(i)); + } + + return map; + } +} diff --git a/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderTest.java b/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderTest.java new file mode 100644 index 000000000000..b0c2efebfb4d --- /dev/null +++ b/platform/diff-impl/tests/com/intellij/diff/tools/fragmented/OnesideFragmentBuilderTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2015 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.diff.tools.fragmented; + +import com.intellij.diff.comparison.ComparisonManager; +import com.intellij.diff.comparison.ComparisonManagerImpl; +import com.intellij.diff.comparison.ComparisonPolicy; +import com.intellij.diff.comparison.iterables.DiffIterableUtil; +import com.intellij.diff.fragments.LineFragment; +import com.intellij.diff.util.Side; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.impl.DocumentImpl; +import com.intellij.openapi.progress.DumbProgressIndicator; +import com.intellij.testFramework.UsefulTestCase; + +import java.util.Collections; +import java.util.List; + +public class OnesideFragmentBuilderTest extends UsefulTestCase { + private static ComparisonManager myComparisonManager = new ComparisonManagerImpl(); + + public void testEquals() { + Document document1 = new DocumentImpl("A\nB\nC"); + Document document2 = new DocumentImpl("A\nB\nC"); + + List fragments = myComparisonManager.compareLinesInner(document1.getCharsSequence(), document2.getCharsSequence(), + ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE); + + OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, true, Side.LEFT); + builder.exec(); + + assertTrue(builder.isEqual()); + assertEquals(builder.getText().toString(), "A\nB\nC\n"); + assertEmpty(builder.getChangedLines()); + assertEmpty(builder.getBlocks()); + } + + public void testWrongEndLineTypoBug() { + Document document1 = new DocumentImpl("A\nB\nC\nD"); + Document document2 = new DocumentImpl("A\nD"); + + List fragments = myComparisonManager.compareLinesInner(document1.getCharsSequence(), document2.getCharsSequence(), + ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE); + + OnesideFragmentBuilder builder = new OnesideFragmentBuilder(fragments, document1, document2, true, Side.RIGHT); + builder.exec(); + + assertFalse(builder.isEqual()); + assertEquals(builder.getText().toString(), "A\nB\nC\nD\n"); + assertEquals(builder.getChangedLines(), Collections.singletonList(new DiffIterableUtil.IntPair(1, 3))); + + assertEquals(builder.getBlocks().size(), 1); + ChangedBlock block = builder.getBlocks().get(0); + assertEquals(block.getLine1(), 1); + assertEquals(block.getLine2(), 3); + assertEquals(block.getStartOffset1(), 2); + assertEquals(block.getEndOffset1(), 6); + assertEquals(block.getStartOffset2(), 6); + assertEquals(block.getEndOffset2(), 6); + } +} diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java index d8b492b5630f..d5877d6ac55d 100644 --- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java +++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java @@ -261,11 +261,7 @@ public class PushLog extends JPanel implements DataProvider { @Override public void linkSelected(LinkLabel aSource, String aLinkData) { if (linkLabel.isEnabled()) { - mySyncStrategy = true; - DefaultMutableTreeNode nodeToEdit = getFirstNodeToEdit(); - if (nodeToEdit != null) { - myTree.startEditingAtPath(TreeUtil.getPathFromRoot(nodeToEdit)); - } + startSyncEditing(); } } }, null); @@ -282,6 +278,13 @@ public class PushLog extends JPanel implements DataProvider { return labelPanel; } + private void startSyncEditing() { + mySyncStrategy = true; + DefaultMutableTreeNode nodeToEdit = getFirstNodeToEdit(); + if (nodeToEdit != null) { + myTree.startEditingAtPath(TreeUtil.getPathFromRoot(nodeToEdit)); + } + } @NotNull private static List collectAllChanges(@NotNull List commitNodes) { @@ -418,11 +421,7 @@ public class PushLog extends JPanel implements DataProvider { return true; } if (myAllowSyncStrategy && e.getKeyCode() == KeyEvent.VK_F2 && e.getModifiers() == InputEvent.ALT_MASK && pressed) { - mySyncStrategy = true; - DefaultMutableTreeNode node = getFirstNodeToEdit(); - if (node != null) { - myTree.startEditingAtPath(TreeUtil.getPathFromRoot(node)); - } + startSyncEditing(); return true; } return super.processKeyBinding(ks, e, condition, pressed); diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java index 43a1eefbc3eb..d4339655c596 100644 --- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java +++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java @@ -162,7 +162,8 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { @NotNull final String text, final short searchContext, final boolean caseSensitively) { - boolean result = processElementsWithWord(processor, searchScope, text, searchContext, caseSensitively, shouldProcessInjectedPsi(searchScope)); + boolean result = processElementsWithWord(processor, searchScope, text, searchContext, caseSensitively, + shouldProcessInjectedPsi(searchScope)); return AsyncUtil.wrapBoolean(result); } @@ -576,7 +577,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { refProcessor = second; } - boolean uniteWith(@NotNull final RequestWithProcessor another) { + private boolean uniteWith(@NotNull final RequestWithProcessor another) { if (request.equals(another.request)) { final Processor myProcessor = refProcessor; if (myProcessor != another.refProcessor) { @@ -891,11 +892,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { registerRequest(locals, primitive, processor); } else { - final List words = getWordsToSearch(primitive.word); - final Set key = new HashSet(words.size() * 2); - for (String word : words) { - key.add(new IdIndexEntry(word, primitive.caseSensitive)); - } + Set key = new HashSet(getWordEntries(primitive.word, primitive.caseSensitive)); registerRequest(singles.getModifiable(key), primitive, processor); } } @@ -923,18 +920,6 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } } - private static List getWordsToSearch(String word) { - List words = StringUtil.getWordsInStringLongestFirst(word); - if (!words.isEmpty()) { - return words; - } - String trimmed = word.trim(); - if (StringUtil.isNotEmpty(trimmed)) { - return Collections.singletonList(trimmed); - } - return Collections.emptyList(); - } - private static void registerRequest(@NotNull Collection collection, @NotNull PsiSearchRequest primitive, @NotNull Processor processor) { @@ -1006,14 +991,21 @@ public class PsiSearchHelperImpl implements PsiSearchHelper { } @NotNull - private static List getWordEntries(@NotNull String name, boolean caseSensitively) { - List words = getWordsToSearch(name); - if (words.isEmpty()) return Collections.emptyList(); - List keys = new ArrayList(words.size()); - for (String word : words) { - keys.add(new IdIndexEntry(word, caseSensitively)); + private static List getWordEntries(@NotNull String name, final boolean caseSensitively) { + List words = StringUtil.getWordsInStringLongestFirst(name); + if (words.isEmpty()) { + String trimmed = name.trim(); + if (StringUtil.isNotEmpty(trimmed)) { + words = Collections.singletonList(trimmed); + } } - return keys; + if (words.isEmpty()) return Collections.emptyList(); + return ContainerUtil.map2List(words, new Function() { + @Override + public IdIndexEntry fun(String word) { + return new IdIndexEntry(word, caseSensitively); + } + }); } public static boolean processTextOccurrences(@NotNull final PsiElement element, diff --git a/platform/lang-api/src/com/intellij/codeInsight/template/TemplateContextType.java b/platform/lang-api/src/com/intellij/codeInsight/template/TemplateContextType.java index 6acd8ccf26ce..fb600f753973 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/template/TemplateContextType.java +++ b/platform/lang-api/src/com/intellij/codeInsight/template/TemplateContextType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -32,7 +32,9 @@ import org.jetbrains.annotations.Nullable; public abstract class TemplateContextType { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.liveTemplateContext"); + @NotNull private final String myContextId; + @NotNull private final String myPresentableName; private final Class myBaseContextType; @@ -48,10 +50,12 @@ public abstract class TemplateContextType { myBaseContextType = baseContextType; } + @NotNull public String getPresentableName() { return myPresentableName; } + @NotNull public String getContextId() { return myContextId; } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java index f4491e8633cd..bc7ff19bfa04 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettings.java @@ -27,6 +27,7 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.autodetect.IndentOptionsInDocumentKeeper; import com.intellij.util.Processor; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ClassMap; @@ -622,8 +623,15 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea if (file != null && file.isValid() && file.isWritable()) { boolean isFullReformat = isFileFullyCoveredByRange(file, formatRange); if (!ignoreDocOptions && !isFullReformat) { - IndentOptions docOptions = IndentOptions.retrieveFromAssociatedDocument(file); - if (docOptions != null) return docOptions; + Pair pair = IndentOptionsInDocumentKeeper.retrieveFromUnderlyingDocument(file); + IndentOptions indentOptions = pair != null ? pair.first : null; + if (indentOptions != null) { + FileIndentOptionsProvider indentProvider = pair.second; + if (indentProvider != null && providerProcessor != null) { + providerProcessor.process(indentProvider); + } + return indentOptions; + } } FileIndentOptionsProvider[] providers = Extensions.getExtensions(FileIndentOptionsProvider.EP_NAME); for (FileIndentOptionsProvider provider : providers) { diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsManager.java index 4baf86c555f6..bc95bdfc7024 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsManager.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsManager.java @@ -20,12 +20,11 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.DefaultJDOMExternalizer; -import com.intellij.openapi.util.DifferenceFilter; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.WriteExternalException; +import com.intellij.openapi.util.*; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.autodetect.IndentOptionsInDocumentKeeper; +import com.intellij.util.Processor; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -142,8 +141,16 @@ public class CodeStyleSettingsManager implements PersistentStateComponent providerRef = new Ref(); + CommonCodeStyleSettings.IndentOptions indentOptions = + getSettings(project).getIndentOptionsByFile(file, null, true, new Processor() { + @Override + public boolean process(FileIndentOptionsProvider provider) { + providerRef.set(provider); + return true; + } + }); + IndentOptionsInDocumentKeeper.storeIntoDocument(document, indentOptions, providerRef.get()); } } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java index b6c149ee7e8c..fc0d8b347783 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java @@ -16,12 +16,8 @@ package com.intellij.psi.codeStyle; import com.intellij.lang.Language; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.util.*; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.arrangement.ArrangementSettings; import com.intellij.psi.codeStyle.arrangement.ArrangementUtil; import com.intellij.util.ReflectionUtil; @@ -903,8 +899,6 @@ public class CommonCodeStyleSettings { public boolean USE_RELATIVE_INDENTS = false; public boolean KEEP_INDENTS_ON_EMPTY_LINES = false; - private final static Key INDENT_OPTIONS_KEY = Key.create("INDENT_OPTIONS"); - @Override public void readExternal(Element element) throws InvalidDataException { DefaultJDOMExternalizer.readExternal(this, element); @@ -984,19 +978,5 @@ public class CommonCodeStyleSettings { public void copyFrom(IndentOptions other) { copyPublicFields(other, this); } - - @Nullable - static IndentOptions retrieveFromAssociatedDocument(@NotNull PsiFile file) { - PsiDocumentManager documentManager = PsiDocumentManager.getInstance(file.getProject()); - if (documentManager != null) { - Document document = documentManager.getDocument(file); - if (document != null) return document.getUserData(INDENT_OPTIONS_KEY); - } - return null; - } - - void associateWithDocument(@NotNull Document document) { - document.putUserData(INDENT_OPTIONS_KEY, this); - } } } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsInDocumentKeeper.java b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsInDocumentKeeper.java new file mode 100644 index 000000000000..7c4cf0ec3019 --- /dev/null +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsInDocumentKeeper.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2015 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.codeStyle.autodetect; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.codeStyle.FileIndentOptionsProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class IndentOptionsInDocumentKeeper { + + public static final Key> INDENT_OPTIONS_KEY = Key.create("INDENT_OPTIONS_KEY"); + + public static void storeIntoDocument(@NotNull Document document, + @NotNull CommonCodeStyleSettings.IndentOptions options, + @Nullable FileIndentOptionsProvider provider) { + document.putUserData(INDENT_OPTIONS_KEY, Pair.create(options, provider)); + } + + @Nullable + public static Pair retrieveFromUnderlyingDocument(@NotNull PsiFile file) { + Project project = file.getProject(); + Document document = PsiDocumentManager.getInstance(project).getDocument(file); + return document != null ? retrieveFromDocument(document) : null; + } + + public static Pair retrieveFromDocument(@NotNull Document document) { + return document.getUserData(INDENT_OPTIONS_KEY); + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index a0a0af7b9849..3cac97504db1 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -21,13 +21,13 @@ import com.intellij.codeInsight.hint.ElementLocationUtil; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.icons.AllIcons; +import com.intellij.ide.BrowserUtil; import com.intellij.ide.DataManager; import com.intellij.ide.actions.BaseNavigateToSourceAction; import com.intellij.ide.actions.ExternalJavaDocAction; import com.intellij.lang.documentation.CompositeDocumentationProvider; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lang.documentation.ExternalDocumentationHandler; -import com.intellij.lang.documentation.ExternalDocumentationProvider; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionButton; @@ -39,6 +39,7 @@ import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -54,6 +55,7 @@ import com.intellij.ui.SideBorder; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; @@ -696,6 +698,12 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr } } + private static final Condition BROWSABLE_URL = new Condition() { + @Override + public boolean value(String s) { + return BrowserUtil.canBeBrowsed(s); + } + }; private class ExternalDocAction extends AnAction implements HintManagerImpl.ActionToIgnore { public ExternalDocAction() { @@ -722,10 +730,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr if (!processed) { final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext()); final List urls; - if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl)) { + if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl) && BROWSABLE_URL.value(myEffectiveExternalUrl)) { urls = Collections.singletonList(myEffectiveExternalUrl); } else { - urls = provider.getUrlFor(element, originalElement); + urls = getBrowsableUrls(provider.getUrlFor(element, originalElement)); assert urls != null : provider; assert !urls.isEmpty() : provider; } @@ -742,15 +750,15 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); final PsiElement originalElement = DocumentationManager.getOriginalElement(element); - if (provider instanceof ExternalDocumentationProvider) { - presentation.setEnabled(element != null && ((ExternalDocumentationProvider)provider).hasDocumentationFor(element, originalElement)); - } - else { - final List urls = provider.getUrlFor(element, originalElement); - presentation.setEnabled(element != null && urls != null && !urls.isEmpty()); - } + List urls = getBrowsableUrls(provider.getUrlFor(element, originalElement)); + presentation.setEnabled(element != null && urls != null && !urls.isEmpty()); } } + + @Nullable + private List getBrowsableUrls(@Nullable List urls) { + return urls == null ? null : ContainerUtil.filter(urls, BROWSABLE_URL); + } } private void registerActions() { 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 4b12e9aba710..0a5977842dd2 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java +++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java @@ -513,7 +513,7 @@ public class ConsoleHistoryController { OutputStream os = null; try { os = new SafeFileOutputStream(file); - XmlSerializer serializer = XmlPullParserFactory.newInstance().newSerializer(); + XmlSerializer serializer = XmlPullParserFactory.newInstance("org.xmlpull.mxp1.MXParserFactory", null).newSerializer(); try { serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " "); } 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 23366fb404f1..0a87853657dc 100644 --- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java @@ -466,7 +466,11 @@ public class LanguageConsoleImpl extends ConsoleViewImpl implements LanguageCons @Nullable @Override public Object getData(@NonNls String dataId) { - if (OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) { + Object data = super.getData(dataId); + if (data != null) { + return data; + } + else if (OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) { return myConsoleEditor; } else if (getProject().isInitialized()) { diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java index 6e2e638f0fc1..b8b8a27ed6e0 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java @@ -52,6 +52,7 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.util.Collections; @@ -59,6 +60,7 @@ import java.util.List; public class ExecutionManagerImpl extends ExecutionManager implements Disposable { public static final Key EXECUTION_SESSION_ID_KEY = Key.create("EXECUTION_SESSION_ID_KEY"); + public static final Key EXECUTION_SKIP_RUN = Key.create("EXECUTION_SKIP_RUN"); private static final Logger LOG = Logger.getInstance(ExecutionManagerImpl.class); private static final ProcessHandler[] EMPTY_PROCESS_HANDLERS = new ProcessHandler[0]; @@ -69,8 +71,9 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable private final Alarm awaitingTerminationAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); private final List> myRunningConfigurations = ContainerUtil.createLockFreeCopyOnWriteList(); + private volatile boolean myForceCompilationInTests; - ExecutionManagerImpl(@NotNull Project project) { + protected ExecutionManagerImpl(@NotNull Project project) { myProject = project; } @@ -159,16 +162,29 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable return; } } - // important! Do not use DumbService.smartInvokeLater here because it depends on modality state - // and execution of startRunnable could be skipped if modality state check fails - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!myProject.isDisposed()) { - DumbService.getInstance(myProject).runWhenSmart(startRunnable); - } - } - }); + + doRun(environment, startRunnable); + } + }); + } + } + + protected void doRun(@NotNull final ExecutionEnvironment environment, @NotNull final Runnable startRunnable) { + Boolean allowSkipRun = environment.getUserData(EXECUTION_SKIP_RUN); + if (allowSkipRun != null && allowSkipRun) { + environment.getProject().getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(environment.getExecutor().getId(), + environment); + } + else { + // important! Do not use DumbService.smartInvokeLater here because it depends on modality state + // and execution of startRunnable could be skipped if modality state check fails + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (!myProject.isDisposed()) { + DumbService.getInstance(myProject).runWhenSmart(startRunnable); + } } }); } @@ -236,7 +252,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable } }; - if (ApplicationManager.getApplication().isUnitTestMode()) { + if (ApplicationManager.getApplication().isUnitTestMode() && !myForceCompilationInTests) { startRunnable.run(); } else { @@ -370,6 +386,11 @@ public class ExecutionManagerImpl extends ExecutionManager implements Disposable }, 50); } + @TestOnly + public void setForceCompilationInTests(boolean forceCompilationInTests) { + myForceCompilationInTests = forceCompilationInTests; + } + private static void start(@NotNull ExecutionEnvironment environment) { RunnerAndConfigurationSettings settings = environment.getRunnerAndConfigurationSettings(); ProgramRunnerUtil.executeConfiguration(environment, settings != null && settings.isEditBeforeRun(), true); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java index 6c9b9510c632..469e1948e17d 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurationBeforeRunProvider.java @@ -31,6 +31,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.util.Disposer; @@ -183,9 +184,9 @@ extends BeforeRunTaskProvider result = new Ref(false); final Disposable disposable = Disposer.newDisposable(); @@ -208,6 +211,10 @@ extends BeforeRunTaskProvider { + private static void beforeRun(@NotNull ExecutionEnvironment environment) { + for (RunConfigurationBeforeRunProviderDelegate delegate : Extensions.getExtensions(RunConfigurationBeforeRunProviderDelegate.EP_NAME)) { + delegate.beforeRun(environment); + } + } + + public class RunConfigurableBeforeRunTask extends BeforeRunTask { private String myConfigurationName; private String myConfigurationType; private boolean myInitialized = false; @@ -305,7 +318,7 @@ extends BeforeRunTaskProvider EP_NAME = ExtensionPointName.create("com.intellij.runConfigurationBeforeRunProviderDelegate"); - private final String myDescription; - - public GrCreateClassKind(final String description) { - myDescription = description; - } - - public String getDescription() { - return myDescription; - } + void beforeRun(@NotNull ExecutionEnvironment environment); } diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index 973be2bc7416..50a7862ea454 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -390,6 +390,7 @@ class FindInProjectTask { PsiFile file = element.getContainingFile(); if (file != null) { ContainerUtil.addIfNotNull(files, file.getVirtualFile()); + ContainerUtil.addIfNotNull(files, file.getNavigationElement().getContainingFile().getVirtualFile()); } } return files; @@ -432,7 +433,7 @@ class FindInProjectTask { return Collections.emptySet(); } - GlobalSearchScope scope = toGlobal(FindInProjectUtil.getScopeFromModel(myProject, myFindModel)); + final GlobalSearchScope scope = toGlobal(FindInProjectUtil.getScopeFromModel(myProject, myFindModel)); final Set resultFiles = new LinkedHashSet(); @@ -448,12 +449,10 @@ class FindInProjectTask { if (!keys.isEmpty()) { final List hits = new ArrayList(); - final GlobalSearchScope finalScope = scope; ApplicationManager.getApplication().runReadAction(new Runnable() { @Override public void run() { - FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor(hits), - finalScope); + FileBasedIndex.getInstance().getFilesWithKey(TrigramIndex.INDEX_ID, keys, new CommonProcessors.CollectProcessor(hits), scope); } }); 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 d22071e66b8e..c33eccf6187c 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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,14 +39,14 @@ import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.DumbServiceImpl; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Factory; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.LocalFileProvider; -import com.intellij.openapi.vfs.LocalFileSystem; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.ex.VirtualFileManagerEx; import com.intellij.psi.*; import com.intellij.psi.search.*; @@ -65,7 +65,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.io.File; +import java.util.Collection; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.regex.Pattern; public class FindInProjectUtil { @@ -439,6 +442,24 @@ public class FindInProjectUtil { } } + private static void addSourceDirectoriesFromLibraries(@NotNull Project project, + @NotNull VirtualFile file, + @NotNull Collection outSourceRoots) { + ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project); + VirtualFile classRoot = index.getClassRootForFile(file); + if (classRoot == null) return; + String relativePath = VfsUtil.getRelativePath(file, classRoot); + if (relativePath == null) return; + for (OrderEntry orderEntry : index.getOrderEntriesForFile(file)) { + for (VirtualFile sourceRoot : orderEntry.getFiles(OrderRootType.SOURCES)) { + VirtualFile sourceFile = sourceRoot.findFileByRelativePath(relativePath); + if (sourceFile != null) { + outSourceRoots.add(sourceFile); + } + } + } + } + @NotNull static SearchScope getScopeFromModel(@NotNull Project project, @NotNull FindModel findModel) { SearchScope customScope = findModel.getCustomScope(); @@ -448,9 +469,20 @@ public class FindInProjectUtil { return findModel.isCustomScope() && customScope != null ? customScope : // we don't have to check for myProjectFileIndex.isExcluded(file) here like FindInProjectTask.collectFilesInScope() does // because all found usages are guaranteed to be not in excluded dir - directory != null ? GlobalSearchScopesCore.directoryScope(project, directory, findModel.isWithSubdirectories()) : + directory != null ? forDirectory(project, findModel.isWithSubdirectories(), directory) : module != null ? module.getModuleContentScope() : findModel.isProjectScope() ? ProjectScope.getContentScope(project) : GlobalSearchScope.allScope(project); } + + @NotNull + private static GlobalSearchScope forDirectory(@NotNull Project project, + boolean withSubdirectories, + @NotNull VirtualFile directory) { + Set result = new LinkedHashSet(); + result.add(directory); + addSourceDirectoriesFromLibraries(project, directory, result); + VirtualFile[] array = result.toArray(new VirtualFile[result.size()]); + return GlobalSearchScopesCore.directoriesScope(project, withSubdirectories, array); + } } diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index cebe481c3d1e..e4dfaf2f37e2 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -881,6 +881,7 @@ public abstract class ChooseByNameBase { (10, (paneHeight - (y + preferredTextFieldPanelSize.height)) / (preferredTextFieldPanelSize.height / 2) - 1); ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(myTextFieldPanel, myTextField); + builder.setLocateWithinScreenBounds(false); builder.setCancelCallback(new Computable() { @Override public Boolean compute() { diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java index 499423115c30..8acd07c31177 100644 --- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java +++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -340,6 +340,11 @@ public class EditorWindowImpl extends UserDataHolderBase implements EditorWindow myDelegate.addPropertyChangeListener(listener); } + @Override + public void addPropertyChangeListener(@NotNull PropertyChangeListener listener, @NotNull Disposable parentDisposable) { + myDelegate.addPropertyChangeListener(listener, parentDisposable); + } + @Override public void removePropertyChangeListener(@NotNull final PropertyChangeListener listener) { myDelegate.removePropertyChangeListener(listener); diff --git a/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/AbstractGithubTagDownloadedProjectGenerator.java b/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/AbstractGithubTagDownloadedProjectGenerator.java index 247aae9377a7..1bc90e94f789 100644 --- a/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/AbstractGithubTagDownloadedProjectGenerator.java +++ b/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/AbstractGithubTagDownloadedProjectGenerator.java @@ -12,6 +12,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.templates.github.GeneratorException; import com.intellij.platform.templates.github.GithubTagInfo; import com.intellij.platform.templates.github.ZipUtil; +import com.intellij.util.NullableFunction; import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -39,10 +40,10 @@ public abstract class AbstractGithubTagDownloadedProjectGenerator extends WebPro protected abstract String getDisplayName(); @NotNull - protected abstract String getGithubUserName(); + public abstract String getGithubUserName(); @NotNull - protected abstract String getGithubRepositoryName(); + public abstract String getGithubRepositoryName(); @Override @Nullable @@ -128,7 +129,12 @@ public abstract class AbstractGithubTagDownloadedProjectGenerator extends WebPro ); LOG.info("Content of " + url + " has been successfully downloaded to " + zipArchiveFile.getAbsolutePath() + ", size " + zipArchiveFile.length() + " bytes"); - ZipUtil.unzipWithProgressSynchronously(project, getTitle(), zipArchiveFile, extractToDir, true); + ZipUtil.unzipWithProgressSynchronously(project, getTitle(), zipArchiveFile, extractToDir, getPathConvertor(), true); + } + + @Nullable + protected NullableFunction getPathConvertor() { + return null; } @Nullable diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java index b84513d4b774..4ba54e5ee461 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueNameEditorTabTitleProvider.java @@ -30,7 +30,10 @@ public class UniqueNameEditorTabTitleProvider implements EditorTabTitleProvider if (!UISettings.getInstance().SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES || DumbService.isDumb(project)) { return null; } - final String uniqueName = UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePathWithinOpenedFileEditors(project, file); + // Even though this is a 'tab title provider' it is used also when tabs are not shown, namely for building IDE frame title. + final String uniqueName = UISettings.getInstance().EDITOR_TAB_PLACEMENT == UISettings.TABS_NONE ? + UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePath(project, file) : + UniqueVFilePathBuilder.getInstance().getUniqueVirtualFilePathWithinOpenedFileEditors(project, file); return uniqueName.equals(file.getName()) ? null : uniqueName; } } diff --git a/platform/lang-impl/src/com/intellij/platform/templates/github/ZipUtil.java b/platform/lang-impl/src/com/intellij/platform/templates/github/ZipUtil.java index 355e8a4676f4..7fb48b80c32e 100644 --- a/platform/lang-impl/src/com/intellij/platform/templates/github/ZipUtil.java +++ b/platform/lang-impl/src/com/intellij/platform/templates/github/ZipUtil.java @@ -40,6 +40,17 @@ public class ZipUtil { @NotNull final File zipArchive, @NotNull final File extractToDir, final boolean unwrapSingleTopLevelFolder) throws GeneratorException + { + unzipWithProgressSynchronously(project, progressTitle, zipArchive, extractToDir, null, unwrapSingleTopLevelFolder); + } + + public static void unzipWithProgressSynchronously( + @Nullable Project project, + @NotNull String progressTitle, + @NotNull final File zipArchive, + @NotNull final File extractToDir, + @Nullable final NullableFunction pathConvertor, + final boolean unwrapSingleTopLevelFolder) throws GeneratorException { final Outcome outcome = DownloadUtil.provideDataWithProgressSynchronously( project, progressTitle, "Unpacking ...", @@ -47,7 +58,7 @@ public class ZipUtil { @Override public Boolean call() throws IOException { ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); - unzip(progress, extractToDir, zipArchive, null, null, unwrapSingleTopLevelFolder); + unzip(progress, extractToDir, zipArchive, pathConvertor, null, unwrapSingleTopLevelFolder); return true; } }, diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java index 24d745373d4b..df42fac043b7 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/DetectedIndentOptionsNotificationProvider.java @@ -34,7 +34,7 @@ import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.intellij.psi.codeStyle.EditorNotificationInfo.*; +import static com.intellij.psi.codeStyle.EditorNotificationInfo.ActionLabelData; /** * @author Rustam Vishnyakov @@ -42,6 +42,7 @@ import static com.intellij.psi.codeStyle.EditorNotificationInfo.*; public class DetectedIndentOptionsNotificationProvider extends EditorNotifications.Provider { private static final Key KEY = Key.create("indent.options.notification.provider"); private static final Key NOTIFIED_FLAG = Key.create("indent.options.notification.provider.status"); + protected static final Key DETECT_INDENT_NOTIFICATION_SHOWN_KEY = Key.create("indent.options.notification.provider.status.test.notification.shown"); @NotNull @Override @@ -93,6 +94,9 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio }; panel.createActionLabel(actionLabelData.label, onClickAction); } + if (ApplicationManager.getApplication().isUnitTestMode()) { + file.putUserData(DETECT_INDENT_NOTIFICATION_SHOWN_KEY, Boolean.TRUE); + } return panel; } } @@ -102,7 +106,7 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio } public static void updateIndentNotification(@NotNull PsiFile file, boolean enforce) { - if (!(ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode())) { + if (!ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode()) { FileEditor fileEditor = FileEditorManager.getInstance(file.getProject()).getSelectedEditor(file.getVirtualFile()); if (fileEditor != null) { Boolean notifiedFlag = fileEditor.getUserData(NOTIFIED_FLAG); diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java new file mode 100644 index 000000000000..5eb9ac2ea00a --- /dev/null +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2000-2015 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.codeStyle.autodetect; + +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; + +public class DetectedIndentNotificationTest extends LightPlatformCodeInsightFixtureTestCase { + + static { + PlatformTestCase.initPlatformLangPrefix(); + } + + private CodeStyleSettings mySettings; + + @Override + public void setUp() throws Exception { + super.setUp(); + mySettings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings(); + mySettings.AUTODETECT_INDENTS = true; + DetectableIndentOptionsProvider optionsProvider = DetectableIndentOptionsProvider.getInstance(); + if (optionsProvider != null) { + optionsProvider.setEnabledInTest(true); + } + } + + @Override + public void tearDown() throws Exception { + mySettings.AUTODETECT_INDENTS = false; + DetectableIndentOptionsProvider optionsProvider = DetectableIndentOptionsProvider.getInstance(); + if (optionsProvider != null) { + optionsProvider.setEnabledInTest(false); + } + super.tearDown(); + } + + public void testNotificationShownOnEnter_WhenIndentDetected() throws Exception { + myFixture.configureByText("Test.java", + "class Test {\n" + + " public void main() {\n" + + " int a;\n" + + " int b;\n" + + " }\n" + + "}"); + + PsiFile file = myFixture.getFile(); + VirtualFile vFile = file.getVirtualFile(); + + Boolean notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); + assert notificationShown == null; + + myFixture.type('\n'); + + notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); + assert notificationShown != null && notificationShown; + } + + public void testNoNotification_WhenNothingDetected() throws Exception { + myFixture.configureByText("Test.java", + "class Test {\n" + + " public void main() {\n" + + " int a;\n" + + " int b;\n" + + " }\n" + + "}"); + + PsiFile file = myFixture.getFile(); + VirtualFile vFile = file.getVirtualFile(); + + Boolean notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); + assert notificationShown == null; + + myFixture.type('\n'); + + notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); + assert notificationShown == null; + } + +} diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 129f41539ba9..12f2211a592d 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -57,6 +57,10 @@ public class BrowserUtil { public static boolean isAbsoluteURL(String url) { return ourExternalPrefix.matcher(url.toLowerCase(Locale.ENGLISH)).find(); } + + public static boolean canBeBrowsed(String url) { + return url != null && !url.startsWith("jar:"); + } public static String getDocURL(String url) { Matcher anchorMatcher = ourAnchorSuffix.matcher(url); diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java index d33dc93e070d..aea21320f433 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowType.java @@ -16,5 +16,5 @@ package com.intellij.openapi.wm; public enum ToolWindowType { - DOCKED, FLOATING, SLIDING + DOCKED, FLOATING, SLIDING, WINDOWED } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java index 836c15ef66c3..370c789437d6 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java @@ -38,6 +38,8 @@ public interface WindowInfo { boolean isFloating(); + boolean isWindowed(); + boolean isSliding(); ToolWindowContentUiType getContentUiType(); diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java index ce3cb33deb90..b7d801edd8bb 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java @@ -69,6 +69,7 @@ public class LightToolWindow extends JPanel { private final TogglePinnedModeAction myToggleAutoHideModeAction = new TogglePinnedModeAction(); private final ToggleDockModeAction myToggleDockModeAction = new ToggleDockModeAction(); private final ToggleFloatingModeAction myToggleFloatingModeAction = new ToggleFloatingModeAction(); + private final ToggleWindowedModeAction myToggleWindowedModeAction = new ToggleWindowedModeAction(); private final ToggleSideModeAction myToggleSideModeAction = new ToggleSideModeAction(); private final ComponentListener myWidthListener = new ComponentAdapter() { @@ -331,15 +332,18 @@ public class LightToolWindow extends JPanel { group.add(myToggleAutoHideModeAction); group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } - else if (type == ToolWindowType.FLOATING) { + else if (type == ToolWindowType.FLOATING || type == ToolWindowType.WINDOWED) { group.add(myToggleAutoHideModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } else if (type == ToolWindowType.SLIDING) { group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } return group; @@ -411,14 +415,9 @@ public class LightToolWindow extends JPanel { } } - private class ToggleDockModeAction extends ToggleAction { + private class ToggleDockModeAction extends ToggleTypeModeAction { public ToggleDockModeAction() { - copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_DOCK_MODE_ACTION_ID)); - } - - @Override - public boolean isSelected(AnActionEvent e) { - return myManager.getToolWindow().getType() == ToolWindowType.DOCKED; + super(ToolWindowType.DOCKED, InternalDecorator.TOGGLE_DOCK_MODE_ACTION_ID); } @Override @@ -435,25 +434,45 @@ public class LightToolWindow extends JPanel { } } - private class ToggleFloatingModeAction extends ToggleAction { + private class ToggleFloatingModeAction extends ToggleTypeModeAction { public ToggleFloatingModeAction() { - copyFrom(ActionManager.getInstance().getAction(InternalDecorator.TOGGLE_FLOATING_MODE_ACTION_ID)); + super(ToolWindowType.FLOATING, InternalDecorator.TOGGLE_FLOATING_MODE_ACTION_ID); + } + } + + private class ToggleWindowedModeAction extends ToggleTypeModeAction { + public ToggleWindowedModeAction() { + super(ToolWindowType.WINDOWED, InternalDecorator.TOGGLE_WINDOWED_MODE_ACTION_ID); + } + + @Override + public void update(@NotNull AnActionEvent e) { + e.getPresentation().setEnabledAndVisible(!SystemInfo.isMac); + } + } + + private class ToggleTypeModeAction extends ToggleAction { + private final ToolWindowType myType; + + public ToggleTypeModeAction(ToolWindowType type, String id) { + myType = type; + copyFrom(ActionManager.getInstance().getAction(id)); } @Override public boolean isSelected(AnActionEvent e) { - return myManager.getToolWindow().getType() == ToolWindowType.FLOATING; + return myManager.getToolWindow().getType() == myType; } @Override public void setSelected(AnActionEvent e, boolean state) { ToolWindow window = myManager.getToolWindow(); ToolWindowType type = window.getType(); - if (type == ToolWindowType.FLOATING) { + if (type == myType) { window.setType(((ToolWindowEx)window).getInternalType(), null); } else { - window.setType(ToolWindowType.FLOATING, null); + window.setType(myType, null); } myManager.setEditorMode(null); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java b/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java index 80952de6d289..682da3e77e3f 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/GotoLineAction.java @@ -31,7 +31,7 @@ public class GotoLineAction extends AnAction implements DumbAware { public void actionPerformed(AnActionEvent e) { final Project project = e.getData(CommonDataKeys.PROJECT); - final Editor editor = e.getData(CommonDataKeys.EDITOR); + final Editor editor = e.getData(CommonDataKeys.EDITOR_EVEN_IF_INACTIVE); if (Boolean.TRUE.equals(e.getData(PlatformDataKeys.IS_MODAL_CONTEXT))) { GotoLineNumberDialog dialog = new GotoLineNumberDialog(project, editor); dialog.show(); @@ -60,7 +60,7 @@ public class GotoLineAction extends AnAction implements DumbAware { presentation.setVisible(false); return; } - Editor editor = event.getData(CommonDataKeys.EDITOR); + Editor editor = event.getData(CommonDataKeys.EDITOR_EVEN_IF_INACTIVE); presentation.setEnabled(editor != null); presentation.setVisible(editor != null); } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java index 99fb583fd864..8e4bd27579ed 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/HideAllToolWindowsAction.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.ToolWindow; +import com.intellij.openapi.wm.ToolWindowType; import com.intellij.openapi.wm.ex.ToolWindowManagerEx; import com.intellij.openapi.wm.impl.DesktopLayout; @@ -51,7 +52,7 @@ public class HideAllToolWindowsAction extends AnAction implements DumbAware { boolean hasVisible = false; for (String id : ids) { ToolWindow toolWindow = toolWindowManager.getToolWindow(id); - if (toolWindow.isVisible()) { + if (toolWindow.isVisible() && toolWindow.getType() != ToolWindowType.WINDOWED) { toolWindow.hide(null); hasVisible = true; } @@ -81,7 +82,8 @@ public class HideAllToolWindowsAction extends AnAction implements DumbAware { ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project); String[] ids = toolWindowManager.getToolWindowIds(); for (String id : ids) { - if (toolWindowManager.getToolWindow(id).isVisible()) { + ToolWindow toolWindow = toolWindowManager.getToolWindow(id); + if (toolWindow.isVisible() && toolWindow.getType() != ToolWindowType.WINDOWED) { presentation.setEnabled(true); presentation.setText(IdeBundle.message("action.hide.all.windows"), true); return; diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java index 9f8d104ebdd2..f0b43e3737ae 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ResizeToolWindowAction.java @@ -99,7 +99,7 @@ public abstract class ResizeToolWindowAction extends AnAction implements DumbAwa window = mgr.getToolWindow(mgr.getActiveToolWindowId()); } - if (window == null || !window.isAvailable() || !window.isVisible() || window.getType() == ToolWindowType.FLOATING || !window.isActive()) { + if (window == null || !window.isAvailable() || !window.isVisible() || window.getType() == ToolWindowType.FLOATING || window.getType() == ToolWindowType.WINDOWED || !window.isActive()) { setDisabled(e); return; } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java index 9c41674642e9..75b646bd3e72 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleDockModeAction.java @@ -74,6 +74,8 @@ public class ToggleDockModeAction extends ToggleAction implements DumbAware { return; } ToolWindow toolWindow=mgr.getToolWindow(id); - presentation.setEnabled(toolWindow.isAvailable()&&ToolWindowType.FLOATING!=toolWindow.getType()); + presentation.setEnabled(toolWindow.isAvailable() + && toolWindow.getType() != ToolWindowType.FLOATING + && toolWindow.getType() != ToolWindowType.WINDOWED); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java new file mode 100644 index 000000000000..b346f88c99a0 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleWindowedModeAction.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2009 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.AnActionEvent; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.Presentation; +import com.intellij.openapi.actionSystem.ToggleAction; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.wm.ToolWindowManager; +import com.intellij.openapi.wm.ToolWindowType; +import com.intellij.openapi.wm.ex.ToolWindowEx; +import com.intellij.openapi.wm.ex.ToolWindowManagerEx; + +public class ToggleWindowedModeAction extends ToggleAction implements DumbAware { + + public boolean isSelected(AnActionEvent event) { + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + return false; + } + ToolWindowManager windowManager = ToolWindowManager.getInstance(project); + String id = windowManager.getActiveToolWindowId(); + if (id == null) { + return false; + } + return ToolWindowType.WINDOWED == windowManager.getToolWindow(id).getType(); + } + + public void setSelected(AnActionEvent event, boolean flag) { + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + return; + } + String id = ToolWindowManager.getInstance(project).getActiveToolWindowId(); + if (id == null) { + return; + } + ToolWindowManagerEx mgr = ToolWindowManagerEx.getInstanceEx(project); + ToolWindowEx toolWindow = (ToolWindowEx)mgr.getToolWindow(id); + ToolWindowType type = toolWindow.getType(); + if (ToolWindowType.WINDOWED == type) { + toolWindow.setType(toolWindow.getInternalType(), null); + } + else { + toolWindow.setType(ToolWindowType.WINDOWED, null); + } + } + + public void update(AnActionEvent event) { + super.update(event); + Presentation presentation = event.getPresentation(); + if (SystemInfo.isMac) { + presentation.setEnabledAndVisible(false); + return; + } + Project project = CommonDataKeys.PROJECT.getData(event.getDataContext()); + if (project == null) { + presentation.setEnabled(false); + return; + } + ToolWindowManager mgr = ToolWindowManager.getInstance(project); + String id = mgr.getActiveToolWindowId(); + presentation.setEnabled(id != null && mgr.getToolWindow(id).isAvailable()); + } +} diff --git a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java index 10d360b2e361..5e5264395153 100644 --- a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java +++ b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java @@ -22,6 +22,7 @@ import com.intellij.openapi.editor.LogicalPosition; import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.wm.IdeFocusManager; import javax.swing.*; import java.awt.*; @@ -49,6 +50,7 @@ public class GotoLineNumberDialog extends DialogWrapper { myEditor.getCaretModel().moveToOffset(offset); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); myEditor.getSelectionModel().removeSelection(); + IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true); super.doOKAction(); } return; @@ -65,6 +67,7 @@ public class GotoLineNumberDialog extends DialogWrapper { myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(Math.max(0, lineNumber - 1), Math.max(0, columnNumber - 1))); myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER); myEditor.getSelectionModel().removeSelection(); + IdeFocusManager.getGlobalInstance().requestFocus(myEditor.getContentComponent(), true); super.doOKAction(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index caf9f0b158f8..903596282727 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -30,6 +30,7 @@ import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.store.ReadOnlyModificationException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DocumentRunnable; +import com.intellij.openapi.fileEditor.impl.LoadTextUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.project.ex.ProjectEx; @@ -49,6 +50,7 @@ import org.jdom.Element; import org.jdom.Parent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.event.HyperlinkEvent; import java.io.File; @@ -138,11 +140,17 @@ public class StorageUtil { return result; } else { + if (ApplicationManager.getApplication().isUnitTestMode() && DEBUG_LOG != null) { + DEBUG_LOG = result.getPath() + ":\n" + content+"\nOld Content:\n"+ LoadTextUtil.loadText(result)+"\n---------"; + } doWrite(requestor, result, virtualFile, content, lineSeparatorIfPrependXmlProlog); return result; } } + @TestOnly + public static String DEBUG_LOG = ""; + private static void doWrite(@NotNull final Object requestor, @NotNull final VirtualFile file, @Nullable final VirtualFile proposedFile, diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java index 843ace06e781..f8fe88eb9982 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorEx.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -108,6 +108,7 @@ public interface EditorEx extends Editor { void reinitSettings(); + void addPropertyChangeListener(@NotNull PropertyChangeListener listener, @NotNull Disposable parentDisposable); void addPropertyChangeListener(@NotNull PropertyChangeListener listener); void removePropertyChangeListener(@NotNull PropertyChangeListener listener); 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 10a2cfe3281f..8ab01eca0b71 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 @@ -1154,6 +1154,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) { myPropertyChangeSupport.addPropertyChangeListener(listener); } + @Override + public void addPropertyChangeListener(@NotNull final PropertyChangeListener listener, @NotNull Disposable parentDisposable) { + addPropertyChangeListener(listener); + Disposer.register(parentDisposable, new Disposable() { + @Override + public void dispose() { + removePropertyChangeListener(listener); + } + }); + } @Override public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index e234be4f0b2a..b8dd4baf2551 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -62,7 +62,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi /** * Holds name of JVM property which presence should trigger debug-aware soft wraps processing. */ - public static final String DEBUG_PROPERTY_NAME = "idea.editor.wrap.soft.debug"; + private static final String DEBUG_PROPERTY_NAME = "idea.editor.wrap.soft.debug"; private static final Logger LOG = Logger.getInstance("#" + SoftWrapModelImpl.class.getName()); @@ -153,7 +153,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi myUseSoftWraps = areSoftWrapsEnabledInEditor(); myEditor.getColorsScheme().getFontPreferences().copyTo(myFontPreferences); - editor.addPropertyChangeListener(this); + editor.addPropertyChangeListener(this, this); myApplianceManager.addListener(myDataMapper); } @@ -789,7 +789,7 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedDocumentLi private class LogicalToVisualTask implements SoftWrapAwareTask { public LogicalPosition input; - public VisualPosition defaultOutput; + private VisualPosition defaultOutput; public VisualPosition output; @Override 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 36dcd15efdc0..5b0beefd98d5 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-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -44,6 +44,7 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.JBColor; import com.intellij.ui.LayeredIcon; +import com.intellij.ui.OnePixelSplitter; import com.intellij.util.IconUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; @@ -54,7 +55,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.border.Border; import java.awt.*; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; @@ -114,7 +114,6 @@ public class EditorWindow { protected EditorWindow(final EditorsSplitters owner) { myOwner = owner; myPanel = new JPanel(new BorderLayout()); - myPanel.setBorder(new AdaptiveBorder()); myPanel.setOpaque(false); myTabbedPane = null; @@ -156,115 +155,6 @@ public class EditorWindow { } } - private static class AdaptiveBorder implements Border { - @Override - public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - Insets insets = ((JComponent)c).getInsets(); - g.setColor(UIUtil.getPanelBackground()); - paintBorder(g, x, y, width, height, insets); - g.setColor(new Color(0, 0, 0, 90)); - paintBorder(g, x, y, width, height, insets); - } - - private static void paintBorder(Graphics g, int x, int y, int width, int height, Insets insets) { - if (insets.left == 1) { - g.drawLine(x, y, x, y + height); - } - - if (insets.right == 1) { - g.drawLine(x + width - 1, y, x + width - 1, y + height); - } - - if (insets.bottom == 1) { - g.drawLine(x, y + height - 1, x + width, y + height - 1); - } - } - - @Override - public Insets getBorderInsets(Component c) { - Container parent = c.getParent(); - if (parent instanceof Splitter) { - boolean editorToTheLeft = false; - boolean editorToTheRight = false; - boolean editorToTheDown = false; - - Splitter splitter = (Splitter)parent; - - boolean vertical = splitter.getOrientation(); - if (vertical && splitter.getFirstComponent() == c) { - editorToTheDown = true; - } else if (!vertical) { - if (splitter.getFirstComponent() == c) { - editorToTheRight = true; - } - if (splitter.getSecondComponent() == c) editorToTheLeft = true; - } - - - //Frame frame = (Frame) SwingUtilities.getAncestorOfClass(Frame.class, c); - //if (frame instanceof IdeFrame) { - // Project project = ((IdeFrame)frame).getProject(); - // ToolWindowManagerEx toolWindowManager = ToolWindowManagerEx.getInstanceEx(project); - // if (!editorToTheLeft) { - // List left = toolWindowManager.getIdsOn(ToolWindowAnchor.LEFT); - // if (left.size() > 0) { - // for (String lid : left) { - // ToolWindow window = toolWindowManager.getToolWindow(lid); - // editorToTheLeft = window != null && window.isVisible() && window.getType() == ToolWindowType.DOCKED; - // if (editorToTheLeft) break; - // } - // } - // } - // - // if (!editorToTheRight) { - // List right = toolWindowManager.getIdsOn(ToolWindowAnchor.RIGHT); - // if (right.size() > 0) { - // for (String lid : right) { - // ToolWindow window = toolWindowManager.getToolWindow(lid); - // editorToTheRight = window != null && window.isVisible() && window.getType() == ToolWindowType.DOCKED; - // if (editorToTheRight) break; - // } - // } - // } - //} - - Splitter outer = nextOuterSplitter(splitter); - if (outer != null) { - boolean outerVertical = outer.getOrientation(); - if (!outerVertical) { - if (splitter.getParent() == outer.getFirstComponent()) editorToTheRight = true; - if (splitter.getParent() == outer.getSecondComponent()) editorToTheLeft = true; - } else { - if (splitter.getParent() == outer.getFirstComponent()) { - editorToTheDown = true; - } - } - } - - int left = editorToTheLeft ? 1 : 0; - int right = editorToTheRight ? 1 : 0; - int bottom = editorToTheDown ? 1 : 0; - return new Insets(0, left, bottom, right); - } - - return new Insets(0, 0, 0, 0); - } - - @Nullable - private static Splitter nextOuterSplitter(Component c) { - Container parent = c.getParent(); - if (parent == null) return null; - Container grandParent = parent.getParent(); - if (grandParent instanceof Splitter) return (Splitter)grandParent; - return null; - } - - @Override - public boolean isBorderOpaque() { - return true; - } - } - void dispose() { try { disposeTabs(); @@ -798,10 +688,8 @@ public class EditorWindow { final EditorWithProviderComposite firstEC = getEditorAt(0); myPanel = new JPanel(new BorderLayout()); myPanel.setOpaque(false); - myPanel.setBorder(new AdaptiveBorder()); - myPanel.setOpaque(false); - final Splitter splitter = new Splitter(orientation == JSplitPane.VERTICAL_SPLIT, 0.5f, 0.1f, 0.9f); + final Splitter splitter = new OnePixelSplitter(orientation == JSplitPane.VERTICAL_SPLIT, 0.5f, 0.1f, 0.9f); final EditorWindow res = new EditorWindow(myOwner); if (myTabbedPane != null) { final EditorWithProviderComposite selectedEditor = getSelectedEditor(); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java index 78068f695d5b..95653ec576ce 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -43,6 +43,7 @@ import com.intellij.openapi.wm.ex.WindowManagerEx; import com.intellij.openapi.wm.impl.FrameTitleBuilder; import com.intellij.openapi.wm.impl.IdePanePanel; import com.intellij.ui.JBColor; +import com.intellij.ui.OnePixelSplitter; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.docking.DockManager; import com.intellij.ui.tabs.JBTabs; @@ -893,7 +894,7 @@ public class EditorsSplitters extends IdePanePanel implements UISettingsListener public void run() { JPanel panel = new JPanel(new BorderLayout()); panel.setOpaque(false); - Splitter splitter = new Splitter(orientation, proportion, 0.1f, 0.9f); + Splitter splitter = new OnePixelSplitter(orientation, proportion, 0.1f, 0.9f); panel.add(splitter, BorderLayout.CENTER); splitter.setFirstComponent(firstComponent); splitter.setSecondComponent(secondComponent); 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 1cf6b6fe5682..ada2456c782e 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 @@ -114,7 +114,8 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec private final List> mySelectionHistory = new ArrayList>(); private Reference myLastSelectedComposite = new WeakReference(null); - private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, null); + private final MergingUpdateQueue myQueue = new MergingUpdateQueue("FileEditorManagerUpdateQueue", 50, true, + MergingUpdateQueue.ANY_COMPONENT); private final BusyObject.Impl.Simple myBusyObject = new BusyObject.Impl.Simple(); diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java index 42e3b17fa366..b373d782b6be 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressDialog.java @@ -44,7 +44,7 @@ import java.io.File; class ProgressDialog implements Disposable { - private ProgressWindow myProgressWindow; + private final ProgressWindow myProgressWindow; private long myLastTimeDrawn = -1; private volatile boolean myShouldShowBackground; private final Alarm myUpdateAlarm = new Alarm(this); @@ -261,14 +261,16 @@ class ProgressDialog implements Disposable { } else { // later to avoid concurrent dispose/addRequest - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - if (!myUpdateAlarm.isDisposed() && myUpdateAlarm.getActiveRequestCount() == 0) { - myUpdateAlarm.addRequest(myUpdateRequest, 500, myProgressWindow.getModalityState()); + if (!myUpdateAlarm.isDisposed() && myUpdateAlarm.getActiveRequestCount() == 0) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + if (!myUpdateAlarm.isDisposed() && myUpdateAlarm.getActiveRequestCount() == 0) { + myUpdateAlarm.addRequest(myUpdateRequest, 500, myProgressWindow.getModalityState()); + } } - } - }); + }); + } } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index 5a0a20351c29..4a05faa4a8f0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -43,6 +43,8 @@ import java.awt.event.WindowEvent; public final class FloatingDecorator extends JDialog { private static final Logger LOG=Logger.getInstance("#com.intellij.openapi.wm.impl.FloatingDecorator"); + static final int DIVIDER_WIDTH = 3; + private static final int ANCHOR_TOP=1; private static final int ANCHOR_LEFT=2; private static final int ANCHOR_BOTTOM=4; @@ -201,7 +203,6 @@ public final class FloatingDecorator extends JDialog { } private final class BorderItem extends JPanel{ - private static final int DIVIDER_WIDTH=3; private static final int RESIZER_WIDTH=10; private final int myAnchor; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 876d4e8c5886..037bb45a7e6d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -65,6 +65,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr private final TogglePinnedModeAction myToggleAutoHideModeAction; private final ToggleDockModeAction myToggleDockModeAction; private final ToggleFloatingModeAction myToggleFloatingModeAction; + private final ToggleWindowedModeAction myToggleWindowedModeAction; private final ToggleSideModeAction myToggleSideModeAction; private final ToggleContentUiTypeAction myToggleContentUiTypeAction; @@ -76,6 +77,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr @NonNls public static final String TOGGLE_PINNED_MODE_ACTION_ID = "TogglePinnedMode"; @NonNls public static final String TOGGLE_DOCK_MODE_ACTION_ID = "ToggleDockMode"; @NonNls public static final String TOGGLE_FLOATING_MODE_ACTION_ID = "ToggleFloatingMode"; + @NonNls public static final String TOGGLE_WINDOWED_MODE_ACTION_ID = "ToggleWindowedMode"; @NonNls public static final String TOGGLE_SIDE_MODE_ACTION_ID = "ToggleSideMode"; @NonNls private static final String TOGGLE_CONTENT_UI_TYPE_ACTION_ID = "ToggleContentUiTypeMode"; @@ -90,6 +92,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDivider = new MyDivider(); myToggleFloatingModeAction = new ToggleFloatingModeAction(); + myToggleWindowedModeAction = new ToggleWindowedModeAction(); myToggleSideModeAction = new ToggleSideModeAction(); myToggleDockModeAction = new ToggleDockModeAction(); myToggleAutoHideModeAction = new TogglePinnedModeAction(); @@ -428,17 +431,24 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr group.add(myToggleAutoHideModeAction); group.add(myToggleDockModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } else if (myInfo.isFloating()) { group.add(myToggleAutoHideModeAction); group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); + } + else if (myInfo.isWindowed()) { + group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); } else if (myInfo.isSliding()) { if (!ToolWindowId.PREVIEW.equals(myInfo.getId())) { group.add(myToggleDockModeAction); } group.add(myToggleFloatingModeAction); + group.add(myToggleWindowedModeAction); group.add(myToggleSideModeAction); } return group; @@ -567,6 +577,35 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } } + private final class ToggleWindowedModeAction extends ToggleAction implements DumbAware { + public ToggleWindowedModeAction() { + copyFrom(ActionManager.getInstance().getAction(TOGGLE_WINDOWED_MODE_ACTION_ID)); + } + + @Override + public final boolean isSelected(final AnActionEvent event) { + return myInfo.isWindowed(); + } + + @Override + public final void setSelected(final AnActionEvent event, final boolean flag) { + if (myInfo.isWindowed()) { + fireTypeChanged(myInfo.getInternalType()); + } + else { + fireTypeChanged(ToolWindowType.WINDOWED); + } + } + + @Override + public void update(@NotNull AnActionEvent e) { + super.update(e); + if (SystemInfo.isMac) { + e.getPresentation().setEnabledAndVisible(false); + } + } + } + private final class ToggleSideModeAction extends ToggleAction implements DumbAware { public ToggleSideModeAction() { copyFrom(ActionManager.getInstance().getAction(TOGGLE_SIDE_MODE_ACTION_ID)); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index e7240a66a5b2..2d727abfdc3e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -77,6 +77,8 @@ import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; +import static com.intellij.openapi.wm.impl.FloatingDecorator.DIVIDER_WIDTH; + /** * @author Anton Katilin * @author Vladimir Kondratyev @@ -90,6 +92,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final DesktopLayout myLayout; private final Map myId2InternalDecorator; private final Map myId2FloatingDecorator; + private final Map myId2WindowedDecorator; private final Map myId2StripeButton; private final Map myId2FocusWatcher; private final Set myDumbAwareIds = Collections.synchronizedSet(ContainerUtil.newTroveSet()); @@ -186,6 +189,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myId2InternalDecorator = new HashMap(); myId2FloatingDecorator = new HashMap(); + myId2WindowedDecorator = new HashMap(); myId2StripeButton = new HashMap(); myId2FocusWatcher = new HashMap(); @@ -702,7 +706,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } private boolean isToHide(final WindowInfoImpl info) { - return (info.isAutoHide() || info.isSliding()) && !(info.isFloating() && hasModalChild(info)); + return (info.isAutoHide() || info.isSliding()) && !(info.isFloating() && hasModalChild(info)) && !info.isWindowed(); } /** @@ -808,6 +812,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // docked and sliding windows appendRemoveDecoratorCmd(id, false, commandsList); } @@ -863,7 +870,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private FloatingDecorator getFloatingDecorator(final String id) { return myId2FloatingDecorator.get(id); } - + /** + * @return windowed decorator for the tool window with specified ID. + */ + private WindowedDecorator getWindowedDecorator(String id) { + return myId2WindowedDecorator.get(id); + } /** * @return internal decorator for the tool window with specified ID. */ @@ -1037,6 +1049,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (toBeShownInfo.isFloating()) { commandsList.add(new AddFloatingDecoratorCmd(decorator, toBeShownInfo)); } + else if (toBeShownInfo.isWindowed()) { + commandsList.add(new AddWindowedDecoratorCmd(decorator, toBeShownInfo)); + } else { // docked and sliding windows // If there is tool window on the same side then we have to hide it, i.e. @@ -1260,6 +1275,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // floating and sliding windows appendRemoveDecoratorCmd(id, false, commandsList); } @@ -1744,6 +1762,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (info.isFloating()) { appendRemoveFloatingDecoratorCmd(info, commandsList); } + else if (info.isWindowed()) { + appendRemoveWindowedDecoratorCmd(info, commandsList); + } else { // docked and sliding windows appendRemoveDecoratorCmd(id, dirtyMode, commandsList); } @@ -1790,6 +1811,11 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements commandsList.add(command); } + private void appendRemoveWindowedDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + final RemoveWindowedDecoratorCmd command = new RemoveWindowedDecoratorCmd(info); + commandsList.add(command); + } + /** * @see com.intellij.openapi.wm.impl.ToolWindowsPane#createAddButtonCmd */ @@ -2108,6 +2134,104 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return ApplicationManager.getApplication().getDisposed(); } } + + /** + * This command creates and shows WindowedDecorator. + */ + private final class AddWindowedDecoratorCmd extends FinalizableCommand { + private final WindowedDecorator myWindowedDecorator; + + /** + * Creates floating decorator for specified floating decorator. + */ + private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + super(myWindowManager.getCommandProcessor()); + myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator); + Window window = myWindowedDecorator.getFrame(); + final Rectangle bounds = info.getFloatingBounds(); + if (bounds != null) { + bounds.setBounds(bounds.x + DIVIDER_WIDTH, bounds.y + DIVIDER_WIDTH, bounds.width - 2 * DIVIDER_WIDTH, bounds.height - 2 * DIVIDER_WIDTH); + } + if (bounds != null && + bounds.width > 0 && + bounds.height > 0 && + myWindowManager.isInsideScreenBounds(bounds.x, bounds.y, bounds.width)) { + window.setBounds(bounds); + } + else { // place new frame at the center of main frame if there are no floating bounds + Dimension size = decorator.getSize(); + if (size.width == 0 || size.height == 0) { + size = decorator.getPreferredSize(); + } + window.setSize(size); + window.setLocationRelativeTo(myFrame); + } + myId2WindowedDecorator.put(info.getId(), myWindowedDecorator); + myWindowedDecorator.addDisposable(new Disposable() { + @Override + public void dispose() { + if (myId2WindowedDecorator.get(info.getId()) != null) { + hideToolWindow(info.getId(), false); + } + } + }); + } + + @Override + public void run() { + try { + myWindowedDecorator.show(false); + Window window = myWindowedDecorator.getFrame(); + JRootPane rootPane = ((RootPaneContainer)window).getRootPane(); + Rectangle rootPaneBounds = rootPane.getBounds(); + Point point = rootPane.getLocationOnScreen(); + Rectangle windowBounds = window.getBounds(); + //Point windowLocation = windowBounds.getLocation(); + //windowLocation.translate(windowLocation.x - point.x, windowLocation.y - point.y); + window.setLocation(2 * windowBounds.x - point.x, 2 * windowBounds.y - point.y); + window.setSize(2 * windowBounds.width - rootPaneBounds.width, 2 * windowBounds.height - rootPaneBounds.height); + } + finally { + finish(); + } + } + } + + /** + * This command hides and destroys floating decorator for tool window + * with specified ID. + */ + private final class RemoveWindowedDecoratorCmd extends FinalizableCommand { + private final WindowedDecorator myWindowedDecorator; + + private RemoveWindowedDecoratorCmd(final WindowInfoImpl info) { + super(myWindowManager.getCommandProcessor()); + myWindowedDecorator = getWindowedDecorator(info.getId()); + myId2WindowedDecorator.remove(info.getId()); + + JRootPane rootPane = ((RootPaneContainer)myWindowedDecorator.getFrame()).getRootPane(); + Rectangle bounds = rootPane.getBounds(); + Point location = rootPane.getLocationOnScreen(); + bounds.setBounds(location.x - DIVIDER_WIDTH, location.y - DIVIDER_WIDTH, bounds.width + 2 * DIVIDER_WIDTH, bounds.height + 2 * DIVIDER_WIDTH); + info.setFloatingBounds(bounds); + } + + @Override + public void run() { + try { + Disposer.dispose(myWindowedDecorator); + } + finally { + finish(); + } + } + + @Override + @Nullable + public Condition getExpireCondition() { + return ApplicationManager.getApplication().getDisposed(); + } + } private final class EditorComponentFocusWatcher extends FocusWatcher { @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java index 8fc9b55d609c..f1d0295c8961 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java @@ -157,7 +157,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo */ @Override public Rectangle getFloatingBounds(){ - return myFloatingBounds; + return myFloatingBounds != null ? new Rectangle(myFloatingBounds) : null; } /** @@ -229,6 +229,11 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return ToolWindowType.FLOATING==myType; } + @Override + public boolean isWindowed(){ + return ToolWindowType.WINDOWED==myType; + } + @Override public boolean isSliding(){ return ToolWindowType.SLIDING==myType; @@ -251,6 +256,9 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo if (ToolWindowType.DOCKED.toString().equalsIgnoreCase(text)) { return ToolWindowType.DOCKED; } + if (ToolWindowType.WINDOWED.toString().equalsIgnoreCase(text)) { + return ToolWindowType.WINDOWED; + } if (ToolWindowType.FLOATING.toString().equalsIgnoreCase(text)) { return ToolWindowType.FLOATING; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java new file mode 100644 index 000000000000..53e29a1a8749 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2014 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.wm.impl; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.FrameWrapper; +import org.jetbrains.annotations.NotNull; + +public final class WindowedDecorator extends FrameWrapper { + private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowedDecorator"); + + private final Project myProject; + + WindowedDecorator(@NotNull Project project, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator) { + super(project); + myProject = project; + setTitle(info.getId() + " - " + myProject.getName()); + setProject(project); + setComponent(internalDecorator); + } + + public Project getProject() { + return myProject; + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java index c191bd2af3eb..b7b0638185bf 100644 --- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java +++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java @@ -304,12 +304,9 @@ public abstract class AbstractExpandableItemsHandler= other.getX() && bounds.intersects(other.getBounds())) { return false; } } diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java index cd82980af2d8..4fdd374d4bca 100644 --- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java +++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java @@ -101,10 +101,8 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, editor.getColorsScheme().setEditorFontSize(table.getFont().getSize()); String text = getText(table, value, row, column); TextAttributes textAttributes = getTextAttributes(table, value, selected, focused, row, column); - panel.setText(text, textAttributes); + panel.setText(text, textAttributes, selected); - ((EditorImpl)editor).setPaintSelection(selected); - editor.getSelectionModel().setSelection(0, selected ? editor.getDocument().getTextLength() : 0); editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground()); editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground()); editor.setBackgroundColor(getCellBackground(table, value, selected, focused, row, column)); @@ -165,6 +163,7 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, private Dimension myPreferredSize; private String myRawText; private TextAttributes myTextAttributes; + private boolean mySelected; public MyPanel(EditorEx editor) { add(editor.getContentComponent()); @@ -178,9 +177,10 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, } } - public void setText(String text, @Nullable TextAttributes textAttributes) { + public void setText(String text, @Nullable TextAttributes textAttributes, boolean selected) { myRawText = text; myTextAttributes = textAttributes; + mySelected = selected; recalculatePreferredSize(); } @@ -277,8 +277,9 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer, ((EditorImpl)myEditor).resetSizes(); + ((EditorImpl)myEditor).setPaintSelection(mySelected); SelectionModel selectionModel = myEditor.getSelectionModel(); - selectionModel.setSelection(0, selectionModel.hasSelection() ? myEditor.getDocument().getTextLength() : 0); + selectionModel.setSelection(0, mySelected ? myEditor.getDocument().getTextLength() : 0); } private static void appendAbbreviated(StringBuilder to, String text, int start, int end, diff --git a/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java b/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java index 3bf745f229ca..cc731d6d61a7 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/MovablePopup.java @@ -93,6 +93,10 @@ public class MovablePopup { } } + public void setBounds(@NotNull Rectangle bounds) { + setBounds(bounds.x, bounds.y, bounds.width, bounds.height); + } + public void setBounds(int x, int y, int width, int height) { if (myViewBounds != null) { myViewBounds.setBounds(x, y, width, height); @@ -102,6 +106,10 @@ public class MovablePopup { } } + public void setLocation(@NotNull Point location) { + setLocation(location.x, location.y); + } + public void setLocation(int x, int y) { if (myViewBounds != null) { myViewBounds.setLocation(x, y); @@ -111,6 +119,10 @@ public class MovablePopup { } } + public void setSize(@NotNull Dimension size) { + setSize(size.width, size.height); + } + public void setSize(int width, int height) { if (myViewBounds != null) { myViewBounds.setSize(width, height); diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 89f48f1340cc..430b5b608017 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -843,6 +843,8 @@ action.ToggleDockMode.text=Dock_ed Mode action.ToggleDockMode.description=Dock/undock active tool window action.ToggleFloatingMode.text=Floating _Mode action.ToggleFloatingMode.description=Float/unfloat active tool window +action.ToggleWindowedMode.text=_Windowed Mode +action.ToggleWindowedMode.description=Window/unwindow active tool window action.ToggleSideMode.text=Split Mode action.ToggleSideMode.description=Tool windows split mode on/off action.ToggleContentUiTypeMode.text=Show Views as Tabs diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml index 10f717aa29d8..9922db4edd17 100644 --- a/platform/platform-resources/src/DefaultColorSchemesManager.xml +++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml @@ -1335,6 +1335,12 @@ + +