Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-03-29 21:56:30 +04:00
78 changed files with 659 additions and 274 deletions
@@ -70,8 +70,7 @@ import org.jetbrains.jps.client.CompileServerClient;
import org.jetbrains.jps.server.ClasspathBootstrap;
import org.jetbrains.jps.server.Server;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import javax.tools.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -586,6 +585,10 @@ public class CompileServerManager implements ApplicationComponent{
cmdLine.addParameter("-XX:ReservedCodeCacheSize=64m");
cmdLine.addParameter("-Xmx" + Registry.intValue("compiler.server.heap.size") + "m");
cmdLine.addParameter("-Djava.awt.headless=true");
final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION);
if (shouldGenerateIndex != null) {
cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex);
}
//noinspection ConstantConditions
if (pingInterval > 0L) {
cmdLine.addParameter("-D" + GlobalOptions.PING_INTERVAL_MS_OPTION + "=" + pingInterval);
@@ -32,20 +32,13 @@ import com.sun.jdi.ReferenceType;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author lex
*/
class ReloadClassesWorker {
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.ReloadClassesWorker");
/**
* number of clasess that will be reloaded in one go.
* Such restriction is needed to deal with big number of classes being reloaded
*/
private static final int CLASSES_CHUNK_SIZE = 100;
private final DebuggerSession myDebuggerSession;
private final HotSwapProgress myProgress;
@@ -111,11 +104,12 @@ class ReloadClassesWorker {
final Project project = debugProcess.getProject();
final BreakpointManager breakpointManager = (DebuggerManagerEx.getInstanceEx(project)).getBreakpointManager();
breakpointManager.disableBreakpoints(debugProcess);
//virtualMachineProxy.suspend();
try {
final Map<ReferenceType, byte[]> redefineMap = new HashMap<ReferenceType,byte[]>();
RedefineProcessor redefineProcessor = new RedefineProcessor(virtualMachineProxy);
int processedClassesCount = 0;
for (final String qualifiedName : modifiedClasses.keySet()) {
processedClassesCount++;
@@ -124,32 +118,30 @@ class ReloadClassesWorker {
myProgress.setFraction(processedClassesCount / (double)modifiedClasses.size());
}
final HotSwapFile fileDescr = modifiedClasses.get(qualifiedName);
final byte[] content;
try {
final byte[] buffer = FileUtil.loadFileBytes(fileDescr.file);
final List<ReferenceType> classes = virtualMachineProxy.classesByName(qualifiedName);
for (final ReferenceType reference : classes) {
redefineMap.put(reference, buffer);
}
content = FileUtil.loadFileBytes(fileDescr.file);
}
catch (IOException e) {
reportProblem(qualifiedName, e);
continue;
}
if (redefineMap.size() >= CLASSES_CHUNK_SIZE) {
// reload this portion of clasess and clear the map to free memory
try {
virtualMachineProxy.redefineClasses(redefineMap);
}
finally {
redefineMap.clear();
}
}
}
if (redefineMap.size() > 0) {
virtualMachineProxy.redefineClasses(redefineMap);
redefineProcessor.processClass(qualifiedName, content);
}
redefineProcessor.processPending();
myProgress.setFraction(1);
myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.classes.reloaded", modifiedClasses.size()));
final int partiallyRedefinedClassesCount = redefineProcessor.getPartiallyRedefinedClassesCount();
if (partiallyRedefinedClassesCount == 0) {
myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION,
DebuggerBundle.message("status.classes.reloaded", redefineProcessor.getProcessedClassesCount()));
}
else {
final String message = DebuggerBundle.message("status.classes.not.all.versions.reloaded", partiallyRedefinedClassesCount,
redefineProcessor.getProcessedClassesCount());
myProgress.addMessage(myDebuggerSession, MessageCategory.WARNING, message);
}
if (LOG.isDebugEnabled()) {
LOG.debug("classes reloaded");
}
@@ -203,11 +195,10 @@ class ReloadClassesWorker {
catch (Exception e) {
processException(e);
}
}
private void reportProblem(final String qualifiedName, @Nullable Exception ex) {
String reason = null;
String reason = null;
if (ex != null) {
reason = ex.getLocalizedMessage();
}
@@ -223,4 +214,78 @@ class ReloadClassesWorker {
StringBuilderSpinAllocator.dispose(buf);
}
}
private static class RedefineProcessor {
/**
* number of classes that will be reloaded in one go.
* Such restriction is needed to deal with big number of classes being reloaded
*/
private static final int CLASSES_CHUNK_SIZE = 100;
private final VirtualMachineProxyImpl myVirtualMachineProxy;
private final Map<ReferenceType, byte[]> myRedefineMap = new HashMap<ReferenceType, byte[]>();
private int myProcessedClassesCount;
private int myPartiallyRedefinedClassesCount;
public RedefineProcessor(VirtualMachineProxyImpl virtualMachineProxy) {
myVirtualMachineProxy = virtualMachineProxy;
}
public void processClass(String qualifiedName, byte[] content) throws Throwable {
final List<ReferenceType> vmClasses = myVirtualMachineProxy.classesByName(qualifiedName);
if (vmClasses.isEmpty()) return;
if (vmClasses.size() == 1) {
myRedefineMap.put(vmClasses.get(0), content);
if (myRedefineMap.size() >= CLASSES_CHUNK_SIZE) {
processChunk();
}
return;
}
int redefinedVersionsCount = 0;
Throwable error = null;
for (ReferenceType vmClass : vmClasses) {
try {
myVirtualMachineProxy.redefineClasses(Collections.singletonMap(vmClass, content));
redefinedVersionsCount++;
}
catch (Throwable t) {
error = t;
}
}
if (redefinedVersionsCount == 0) {
throw error;
}
if (redefinedVersionsCount < vmClasses.size()) {
myPartiallyRedefinedClassesCount++;
}
myProcessedClassesCount++;
}
private void processChunk() throws Throwable {
// reload this portion of classes and clear the map to free memory
try {
myVirtualMachineProxy.redefineClasses(myRedefineMap);
myProcessedClassesCount += myRedefineMap.size();
}
finally {
myRedefineMap.clear();
}
}
public void processPending() throws Throwable {
if (myRedefineMap.size() > 0) {
processChunk();
}
}
public int getProcessedClassesCount() {
return myProcessedClassesCount;
}
public int getPartiallyRedefinedClassesCount() {
return myPartiallyRedefinedClassesCount;
}
}
}
@@ -27,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.OrderRootType;
@@ -371,7 +372,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent
}
}
public abstract class AttachItemActionBase extends AnAction {
public abstract class AttachItemActionBase extends DumbAwareAction {
private VirtualFile myLastChosen = null;
protected AttachItemActionBase(String text) {
@@ -688,7 +688,7 @@ public class GenericsHighlightUtil {
return true;
}
}
if (isUncheckedTypeArgumentConversion(lTypeArg, rTypeArg)) return true;
if (!TypeConversionUtil.typesAgree(lTypeArg, rTypeArg, false)) return true;
}
return false;
}
@@ -730,48 +730,6 @@ public class GenericsHighlightUtil {
return false;
}
private static boolean isUncheckedTypeArgumentConversion (PsiType lTypeArg, PsiType rTypeArg) {
if (lTypeArg instanceof PsiPrimitiveType || rTypeArg instanceof PsiPrimitiveType) return false;
if (lTypeArg.equals(rTypeArg)) return false;
if (lTypeArg instanceof PsiCapturedWildcardType) {
//ignore capture conversion
return isUncheckedTypeArgumentConversion(((PsiCapturedWildcardType)lTypeArg).getWildcard(), rTypeArg);
}
if (rTypeArg instanceof PsiCapturedWildcardType) {
//ignore capture conversion
return isUncheckedTypeArgumentConversion(lTypeArg, ((PsiCapturedWildcardType)rTypeArg).getWildcard());
}
if (lTypeArg instanceof PsiWildcardType || rTypeArg instanceof PsiWildcardType) {
return !lTypeArg.isAssignableFrom(rTypeArg);
}
if (lTypeArg instanceof PsiArrayType && rTypeArg instanceof PsiArrayType) {
return isUncheckedTypeArgumentConversion(((PsiArrayType)rTypeArg).getComponentType(), ((PsiArrayType)lTypeArg).getComponentType());
}
if (lTypeArg instanceof PsiArrayType || rTypeArg instanceof PsiArrayType) return false;
if (lTypeArg instanceof PsiIntersectionType) {
for (PsiType type : ((PsiIntersectionType)lTypeArg).getConjuncts()) {
if (!isUncheckedTypeArgumentConversion(type, rTypeArg)) return false;
}
return true;
}
if (!(lTypeArg instanceof PsiClassType)) {
LOG.error("left: "+lTypeArg + "; "+lTypeArg.getClass());
}
if (rTypeArg instanceof PsiIntersectionType) {
for (PsiType type : ((PsiIntersectionType)rTypeArg).getConjuncts()) {
if (!isUncheckedTypeArgumentConversion(lTypeArg, type)) return false;
}
return true;
}
if (!(rTypeArg instanceof PsiClassType)) {
LOG.error("right :"+rTypeArg + "; "+rTypeArg.getClass());
}
return ((PsiClassType)lTypeArg).resolve() instanceof PsiTypeParameter ||
((PsiClassType)rTypeArg).resolve() instanceof PsiTypeParameter;
}
@Nullable
public static HighlightInfo checkForeachLoopParameterType(PsiForeachStatement statement) {
final PsiParameter parameter = statement.getIterationParameter();
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.folding.impl;
import com.intellij.codeInsight.daemon.impl.CollectHighlightsUtil;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.lang.ASTNode;
@@ -47,7 +48,10 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAware {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.folding.impl.JavaFoldingBuilder");
@@ -312,7 +316,9 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar
if (importKeyword == null) return null;
int startOffset = importKeyword.getTextRange().getEndOffset() + 1;
int endOffset = statements[statements.length - 1].getTextRange().getEndOffset();
return new TextRange(startOffset, endOffset);
if (!hasErrorElementsNearby(element.getContainingFile(), startOffset, endOffset)) {
return new TextRange(startOffset, endOffset);
}
}
if (element instanceof PsiDocComment) {
return element.getTextRange();
@@ -330,6 +336,16 @@ public class JavaFoldingBuilder extends CustomFoldingBuilder implements DumbAwar
return null;
}
public static boolean hasErrorElementsNearby(final PsiFile file, int startOffset, int endOffset) {
endOffset = CharArrayUtil.shiftForward(file.getText(), endOffset, " \t\n");
for (PsiElement element : CollectHighlightsUtil.getElementsInRange(file, startOffset, endOffset)) {
if (element instanceof PsiErrorElement) {
return true;
}
}
return false;
}
@Nullable
private static TextRange getFileHeader(PsiJavaFile file) {
PsiElement first = file.getFirstChild();
@@ -767,7 +767,14 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor {
int minSpaces = 0;
int minLineFeeds = 1;
PsiElement psi = myChild1.getPsi();
if (mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE || psi != null && PsiTreeUtil.hasErrorElements(psi)) {
// We want to avoid situations like below:
// 1. Call 'introduce variable' refactoring for the code like 'System.out.println(1);';
// 2. When KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE is on, the output looks like 'int i = 1; System.out.println(i);';
// That's why we process the option only during the explicit reformat (directly invoked by an user).
if ((mySettings.KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE && FormatterUtil.isFormatterCalledExplicitly())
|| psi != null && PsiTreeUtil.hasErrorElements(psi))
{
minSpaces = 1;
minLineFeeds = 0;
}
@@ -354,7 +354,7 @@ public class TypeConversionUtil {
final PsiClass class1 = PsiUtil.resolveClassInType(typeArg1);
if (class1 instanceof PsiTypeParameter) {
for (PsiType type : class1.getExtendsListTypes()) {
if (TypesDistinctProver.provablyDistinct(type, typeArg2)) return false;
if (TypesDistinctProver.provablyDistinct(type, typeArg2) && !isAssignable(type, typeArg2)) return false;
}
}
}
@@ -746,7 +746,7 @@ public class TypeConversionUtil {
private static boolean isAssignableToWildcard(PsiWildcardType wildcardType, PsiType right) {
if (wildcardType.isSuper()) {
return isAssignable(right, wildcardType.getSuperBound());
return isAssignable(wildcardType.getSuperBound(), right);
}
return isAssignable(wildcardType.getExtendsBound(), right);
}
@@ -859,7 +859,7 @@ public class TypeConversionUtil {
return true;
}
private static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) {
public static boolean typesAgree(PsiType typeLeft, PsiType typeRight, boolean allowUncheckedConversion) {
if (typeLeft instanceof PsiWildcardType) {
final PsiWildcardType leftWildcard = (PsiWildcardType)typeLeft;
final PsiType leftBound = leftWildcard.getBound();
@@ -92,7 +92,10 @@ public class TypesDistinctProver {
for (PsiClassType type : parameter.getExtendsListTypes()) {
if (!TypeConversionUtil.isAssignable(type, substitutedType1 != null ? substitutedType1 : substitutedType2, false)) return true;
}
} else if (provablyDistinct(substitutedType1, substitutedType2)) return true;
} else {
if (provablyDistinct(substitutedType1, substitutedType2)) return true;
if (substitutedType1 instanceof PsiWildcardType && !((PsiWildcardType)substitutedType1).isBounded()) return true;
}
}
return false;
}
@@ -100,8 +103,8 @@ public class TypesDistinctProver {
final PsiClass boundClass1 = classResolveResult1.getElement();
final PsiClass boundClass2 = classResolveResult2.getElement();
return type2 != null && type1 != null && !type1.equals(type2) &&
!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) &&
!InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true);
(!InheritanceUtil.isInheritorOrSelf(boundClass1, boundClass2, true) ||
!InheritanceUtil.isInheritorOrSelf(boundClass2, boundClass1, true));
}
public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) {
@@ -172,4 +172,48 @@ class My<T> {
public void test() {
if (getSuperclass() == List.class);
}
}
class IDEA75178 {
void test(Set<String> labels) {
final Matcher<? super Object> empty = isEmpty();
assertThat(labels, empty);
assertAlsoThat(empty, labels);
}
public static <T> void assertThat(T actual, Matcher<T> matcher) { throw new AssertionError(actual.toString() + matcher.toString());}
public static <T> void assertAlsoThat(Matcher<T> matcher, T actual) { throw new AssertionError(actual.toString() + matcher.toString());}
public static <T> Matcher<? super T> isEmpty() {
return null;
}
static class Matcher<<warning descr="Type parameter 'T' is never used">T</warning>>{}
class Foo {}
void testComment() {
Set<Foo> foos = Collections.emptySet();
assertThatComment(foos, hasSize(0));
}
<E> Matcher<? super Collection<? extends E>> hasSize(int size) {return size == 0 ? null : null;}
<T> void assertThatComment(T actual, Matcher<? super T> matcher){ throw new AssertionError(actual.toString() + matcher.toString());}
}
class IDEA66750 {
public void test() {
List<List<String>> data = new ArrayList<List<String>>();
List<List<?>> y = <error descr="Inconvertible types; cannot cast 'java.util.List<java.util.List<java.lang.String>>' to 'java.util.List<java.util.List<?>>'">(List<List<?>>)data</error>;
System.out.println(y);
ArrayList<Number> al = <error descr="Inconvertible types; cannot cast 'java.util.ArrayList<java.lang.Integer>' to 'java.util.ArrayList<java.lang.Number>'">(ArrayList<Number>) new ArrayList<Integer>(1)</error>;
System.out.println(al);
}
}
class IDEA73377 {
public Iterator<Map.Entry<Map.Entry<?, ?>, ?>> iterator(Map<?, ?> map) {
//noinspection unchecked
return <error descr="Inconvertible types; cannot cast 'java.util.Iterator<java.util.Map.Entry<capture<?>,capture<?>>>' to 'java.util.Iterator<java.util.Map.Entry<java.util.Map.Entry<?,?>,?>>'">(Iterator<Map.Entry<Map.Entry<?, ?>, ?>>)map.entrySet().iterator()</error>;
}
}
@@ -3,7 +3,7 @@
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="IDEA jdk" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="masterDetails">
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -618,7 +618,7 @@ class Test {
doTest(before, toPaste2, expected)
}
def testPlainTextPaste() {
void testPlainTextPaste() {
def before = '''\
line1
line2
@@ -628,7 +628,7 @@ class Test {
def toPaste =
'''\
line to paste #1
line to paste #2
line to paste #2\
'''
@@ -641,10 +641,33 @@ line to paste #1
doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT)
}
def testPlainTextPasteWithCompleteReplacement() {
void "test plain text when pasted string ends by line feed"() {
def before = '''\
line1
line2
<caret>
'''
def toPaste =
'''\
line to paste #1
line to paste #2
'''
def expected = '''\
line1
line2
line to paste #1
line to paste #2
'''
doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT)
}
void "test plain text when caret is after selection"() {
def before = '''\
<selection> line1
line2</selection>\
</selection><caret>\
'''
def toPaste =
@@ -655,32 +678,14 @@ line to paste #2
def expected = '''\
line1
line to paste #1
line to paste #2
'''
doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT)
}
def testPlainTextMultilinePasteWithCaretAfterSelection() {
def before = '''\
<selection> line1</selection><caret>\
'''
def toPaste =
'''\
line to paste #1
line to paste #2
'''
def expected = '''\
line to paste #1
line to paste #2
'''
doTest(before, toPaste, expected, StdFileTypes.PLAIN_TEXT)
}
def testPlainTextThatStartsByLineFeed() {
void testPlainTextThatStartsByLineFeed() {
def before = '''\
line 1
# item1<caret>
@@ -715,6 +720,37 @@ line 1
doTest(before, toPaste2, expected2, StdFileTypes.PLAIN_TEXT)
}
void "test formatter-based paste that starts with white space"() {
def before = '''\
class Test {
int i;
int j;
void test() {
<caret>
}
}
'''
def toPaste = '''\
int i;
int j;\
'''
def expected = '''\
class Test {
int i;
int j;
void test() {
int i;
int j;
}
}
'''
doTest(before, toPaste, expected)
}
def doTest(String before, toPaste, expected, FileType fileType = StdFileTypes.JAVA) {
myFixture.configureByText(fileType, before)
@@ -732,6 +768,7 @@ line 1
finally {
settings.REFORMAT_ON_PASTE = old
}
myFixture.editor.selectionModel.removeSelection()
myFixture.checkResult(expected)
}
}
@@ -167,6 +167,32 @@ class Test {
assertEquals(2, closureFolds.size())
}
public void "test closure folding doesn't expand when editing inside"() {
def text = """\
class Test {
void test() {
new Runnable() {
public void run() {
System.out.println(<caret>);
}
};
}
}
"""
configure text
def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
def closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
assertNotNull closureStartFold
assertFalse closureStartFold.expanded
assert text.substring(closureStartFold.endOffset).startsWith('System') //one line closure
myFixture.type('2')
myFixture.doHighlighting()
closureStartFold = foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable"))
assert closureStartFold
}
public void testFindInFolding() {
def text = """\
class Test {
@@ -436,7 +436,7 @@ public class ClsRepositoryUseTest extends PsiTestCase{
PsiType type1 = aClass.getFields()[1].getType();
PsiElement target1 = PsiUtil.resolveClassInType(type1);
assertNotNull(target1);
PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", RESOLVE_SCOPE);
PsiClass objectClass = myJavaFacade.findClasses("java.lang.Object", RESOLVE_SCOPE)[1];
assertEquals(objectClass, target1);
}
@@ -523,7 +523,7 @@ public class ClsRepositoryUseTest extends PsiTestCase{
assertFalse(type2 instanceof PsiPrimitiveType);
PsiClass target2 = PsiUtil.resolveClassInType(type2);
assertNotNull(target2);
PsiClass objectClass = myJavaFacade.findClass("java.lang.Object", RESOLVE_SCOPE);
PsiClass objectClass = myJavaFacade.findClasses("java.lang.Object", RESOLVE_SCOPE)[1];
assertEquals(objectClass, target2);
parameters[0].getModifierList();
@@ -0,0 +1,54 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.resolve
import com.intellij.openapi.application.ex.PathManagerEx
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.PsiTestUtil
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
/**
* @author peter
*/
class ResolveInLibrariesTest extends JavaCodeInsightFixtureTestCase {
public void "test prefer current library when navigation from its source"() {
def lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib")
def nanoJar = lib.children.find { it.name.startsWith("nanoxml") }
def nanoSrc = lib.findChild("src").children.find { it.name.startsWith("nanoxml") }
def jarCopy = myFixture.copyFileToProject(nanoJar.path, 'lib/nanoJar.jar')
def srcCopy = myFixture.copyFileToProject(nanoSrc.path, 'lib/nanoSrc.zip')
PsiTestUtil.addLibrary(myModule, 'nano1', lib.path, ["/$nanoJar.name!/"] as String[], ["/src/$nanoSrc.name!/"] as String[])
PsiTestUtil.addLibrary(myModule, 'nano2', jarCopy.parent.path, ["/$jarCopy.name!/"] as String[], ["/$srcCopy.name!/"] as String[])
def parsers = JavaPsiFacade.getInstance(project).findClasses('net.n3.nanoxml.IXMLParser', GlobalSearchScope.allScope(project))
assert parsers.size() == 2
def file0 = parsers[0].navigationElement.containingFile
assert file0.virtualFile.path.startsWith(nanoSrc.path)
assert file0.findReferenceAt(file0.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(nanoSrc.path)
def file1 = parsers[1].navigationElement.containingFile
assert file1.virtualFile.path.startsWith(srcCopy.path)
assert file1.findReferenceAt(file1.text.indexOf('IXMLReader reader')).resolve().navigationElement.containingFile.virtualFile.path.startsWith(srcCopy.path)
}
}
@@ -9,4 +9,5 @@ public interface GlobalOptions {
String USE_EXTERNAL_JAVAC_OPTION = "use.external.javac.process";
String HOSTNAME_OPTION = "localhost.name";
String PING_INTERVAL_MS_OPTION = "server.ping.interval";
String GENERATE_CLASSPATH_INDEX_OPTION = "generate.classpath.index";
}
@@ -0,0 +1,18 @@
package org.jetbrains.jps.api;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Eugene Zhuravlev
* Date: 3/29/12
*/
public class SharedThreadPool {
public static final ExecutorService INSTANCE = Executors.newCachedThreadPool();
public static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() {
@Override
public void submit(Runnable runnable) {
INSTANCE.submit(runnable);
}
};
}
@@ -30,7 +30,7 @@ public class BuilderRegistry {
myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors());
runtime.addShutdownHook(new Thread() {
public void run() {
myTasksExecutor.shutdownNow();
myTasksExecutor.shutdown();
}
});
@@ -70,7 +70,7 @@ public class BuilderRegistry {
}
public void shutdown() {
myTasksExecutor.shutdownNow();
myTasksExecutor.shutdown();
}
}
@@ -9,7 +9,9 @@ import com.intellij.util.io.MappingFailedException;
import com.intellij.util.io.PersistentEnumerator;
import org.jetbrains.jps.*;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.incremental.java.ExternalJavacDescriptor;
import org.jetbrains.jps.incremental.java.JavaBuilder;
import org.jetbrains.jps.incremental.java.JavaBuilderLogger;
@@ -21,10 +23,13 @@ import org.jetbrains.jps.incremental.storage.SourceToFormMapping;
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
import org.jetbrains.jps.server.ProjectDescriptor;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
@@ -35,6 +40,8 @@ public class IncProjectBuilder {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.IncProjectBuilder");
public static final String COMPILE_SERVER_NAME = "COMPILE SERVER";
private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index";
private static final boolean GENERATE_CLASSPATH_INDEX = "true".equals(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION));
private final ProjectDescriptor myProjectDescriptor;
private final BuilderRegistry myBuilderRegistry;
@@ -54,6 +61,7 @@ public class IncProjectBuilder {
private float myModulesProcessed = 0.0f;
private final float myTotalModulesWork;
private final int myTotalModuleLevelBuilderCount;
private final List<Future> myAsyncTasks = new ArrayList<Future>();
public IncProjectBuilder(ProjectDescriptor pd, BuilderRegistry builderRegistry, Map<String, String> builderParams, CanceledStatus cs) {
myProjectDescriptor = pd;
@@ -131,6 +139,15 @@ public class IncProjectBuilder {
finally {
memWatcher.stop();
flushContext(context);
// wait for the async tasks
for (Future task : myAsyncTasks) {
try {
task.get();
}
catch (Throwable th) {
LOG.info(th);
}
}
}
}
@@ -309,16 +326,18 @@ public class IncProjectBuilder {
}
}
private void buildChunk(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
private void buildChunk(CompileContext context, final ModuleChunk chunk) throws ProjectBuildException {
boolean doneSomething = false;
try {
context.ensureFSStateInitialized(chunk);
if (context.isMake()) {
processDeletedPaths(context, chunk);
doneSomething |= context.hasRemovedSources();
}
context.onChunkBuildStart(chunk);
runModuleLevelBuilders(context, chunk);
doneSomething = runModuleLevelBuilders(context, chunk);
}
catch (ProjectBuildException e) {
throw e;
@@ -343,11 +362,59 @@ public class IncProjectBuilder {
}
finally {
Paths.CHUNK_REMOVED_SOURCES_KEY.set(context, null);
if (doneSomething && GENERATE_CLASSPATH_INDEX) {
final boolean forTests = context.isCompilingTests();
final Future<?> future = SharedThreadPool.INSTANCE.submit(new Runnable() {
@Override
public void run() {
createClasspathIndex(chunk, forTests);
}
});
myAsyncTasks.add(future);
}
}
}
}
}
private static void createClasspathIndex(final ModuleChunk chunk, boolean forTests) {
final Set<File> outputPaths = new LinkedHashSet<File>();
for (Module module : chunk.getModules()) {
if (forTests) {
outputPaths.add(new File(module.getTestOutputPath()));
}
else {
outputPaths.add(new File(module.getOutputPath()));
}
}
for (File outputRoot : outputPaths) {
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(outputRoot, CLASSPATH_INDEX_FINE_NAME)));
try {
writeIndex(writer, outputRoot, "");
}
finally {
writer.close();
}
}
catch (IOException e) {
// Ignore. Failed to create optional classpath index
}
}
}
private static void writeIndex(final BufferedWriter writer, final File file, final String path) throws IOException {
writer.write(path);
writer.write('\n');
final File[] files = file.listFiles();
if (files != null) {
for (File child : files) {
writeIndex(writer, child, path + "/" + child.getName());
}
}
}
private void processDeletedPaths(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
try {
// cleanup outputs
@@ -420,13 +487,14 @@ public class IncProjectBuilder {
}
}
private void runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
// return true if changed something, false otherwise
private boolean runModuleLevelBuilders(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
boolean doneSomething = false;
boolean rebuildFromScratchRequested = false;
float stageCount = myTotalModuleLevelBuilderCount;
final int modulesInChunk = chunk.getModules().size();
int buildersPassed = 0;
boolean nextPassRequired;
do {
nextPassRequired = false;
context.beforeCompileRound(chunk);
@@ -448,6 +516,8 @@ public class IncProjectBuilder {
}
final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk);
doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE);
if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) {
throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop");
}
@@ -492,6 +562,8 @@ public class IncProjectBuilder {
}
}
while (nextPassRequired);
return doneSomething;
}
private void runProjectLevelBuilders(CompileContext context) throws ProjectBuildException {
@@ -32,7 +32,7 @@ public abstract class ModuleLevelBuilder extends Builder {
}
public static enum ExitCode {
OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED
NOTHING_DONE, OK, ABORT, ADDITIONAL_PASS_REQUIRED, CHUNK_REBUILD_REQUIRED
}
public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
@@ -33,8 +33,7 @@ import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.EmptyVisitor;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import javax.tools.*;
import java.io.*;
import java.net.MalformedURLException;
import java.net.ServerSocket;
@@ -239,7 +238,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
private ExitCode compile(final CompileContext context, ModuleChunk chunk, Collection<File> files, Collection<File> forms)
throws Exception {
ExitCode exitCode = ExitCode.OK;
ExitCode exitCode = ExitCode.NOTHING_DONE;
final boolean hasSourcesToCompile = !files.isEmpty() || !forms.isEmpty();
@@ -264,6 +263,7 @@ public class JavaBuilder extends ModuleLevelBuilder {
DELTA_MAPPINGS_CALLBACK_KEY.set(context, delta.getCallback());
try {
if (hasSourcesToCompile) {
exitCode = ExitCode.OK;
final Set<File> sourcePath = TEMPORARY_SOURCE_ROOTS_KEY.get(context, Collections.<File>emptySet());
final String chunkName = getChunkPresentableName(chunk);
@@ -868,7 +868,8 @@ public class JavaBuilder extends ModuleLevelBuilder {
myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, "OutOfMemoryError: insufficient memory"));
}
else {
myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, line));
final BuildMessage.Kind kind = line.toLowerCase(Locale.US).contains("error")? BuildMessage.Kind.ERROR : BuildMessage.Kind.INFO;
myContext.processMessage(new CompilerMessage(BUILDER_NAME, kind, line));
}
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jps.incremental.resources;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.ModuleChunk;
@@ -38,12 +39,14 @@ public class ResourcesBuilder extends ModuleLevelBuilder {
}
try {
final ResourcePatterns finalPatterns = patterns;
final Ref<Boolean> doneSomething = new Ref<Boolean>(false);
context.processFilesToRecompile(chunk, new FileProcessor() {
public boolean apply(final Module module, final File file, final String sourceRoot) throws IOException {
if (finalPatterns.isResourceFile(file, sourceRoot)) {
try {
context.processMessage(new ProgressMessage("Copying " + file.getPath()));
final String moduleName = module.getName().toLowerCase(Locale.US);
doneSomething.set(true);
copyResource(context, module, file, sourceRoot, context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests()));
}
catch (IOException e) {
@@ -56,7 +59,7 @@ public class ResourcesBuilder extends ModuleLevelBuilder {
}
});
return ExitCode.OK;
return doneSomething.get()? ExitCode.OK : ExitCode.NOTHING_DONE;
}
catch (Exception e) {
throw new ProjectBuildException(e.getMessage(), e);
@@ -2,31 +2,22 @@ package org.jetbrains.jps.javac;
import org.jboss.netty.channel.MessageEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.api.AsyncTaskExecutor;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.client.SimpleProtobufClient;
import org.jetbrains.jps.client.UUIDGetter;
import java.io.File;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Eugene Zhuravlev
* Date: 1/22/12
*/
public class JavacServerClient extends SimpleProtobufClient<JavacServerResponseHandler>{
private static final ExecutorService ourExecutors = Executors.newCachedThreadPool();
private static final AsyncTaskExecutor ASYNC_EXEC = new AsyncTaskExecutor() {
@Override
public void submit(Runnable runnable) {
ourExecutors.submit(runnable);
}
};
public JavacServerClient() {
super(JavacRemoteProto.Message.getDefaultInstance(), ASYNC_EXEC, new UUIDGetter() {
super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.ASYNC_EXEC, new UUIDGetter() {
@NotNull
public UUID getSessionUUID(@NotNull MessageEvent e) {
final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage();
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

@@ -35,7 +35,7 @@ import java.awt.event.MouseEvent;
import java.lang.ref.WeakReference;
public class LineMarkerInfo<T extends PsiElement> {
private final Icon myIcon;
protected final Icon myIcon;
private final WeakReference<T> elementRef;
public final int startOffset;
public final int endOffset;
@@ -157,7 +157,7 @@ public class LineMarkerInfo<T extends PsiElement> {
return myInfo.myIconAlignment;
}
private boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) {
protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) {
return
myInfo.getElement() != null &&
renderer.myInfo.getElement() != null &&
@@ -60,4 +60,27 @@ public class RelatedItemLineMarkerInfo<T extends PsiElement> extends LineMarkerI
public Collection<? extends GotoRelatedItem> createGotoRelatedItems() {
return myTargets.getValue();
}
@Override
public GutterIconRenderer createGutterRenderer() {
if (myIcon == null) return null;
return new RelatedItemLineMarkerGutterIconRenderer<T>(this);
}
private static class RelatedItemLineMarkerGutterIconRenderer<T extends PsiElement> extends LineMarkerGutterIconRenderer<T> {
public RelatedItemLineMarkerGutterIconRenderer(final RelatedItemLineMarkerInfo<T> markerInfo) {
super(markerInfo);
}
@Override
protected boolean looksTheSameAs(@NotNull LineMarkerGutterIconRenderer renderer) {
if (!(renderer instanceof RelatedItemLineMarkerGutterIconRenderer) || !super.looksTheSameAs(renderer)) {
return false;
}
final RelatedItemLineMarkerInfo<?> markerInfo = (RelatedItemLineMarkerInfo<?>)getLineMarkerInfo();
final RelatedItemLineMarkerInfo<?> otherInfo = (RelatedItemLineMarkerInfo<?>)renderer.getLineMarkerInfo();
return markerInfo.myTargets.equals(otherInfo.myTargets);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -379,7 +379,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
// Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent
// adjustment string and apply to each line of the pasted block starting from the second one.
//
// We differentiate three possible states here:
// We differentiate the following possible states here:
// --- pasted block doesn't start new line, i.e. there are non-white space symbols before it at the first line.
// Example:
// old content [pasted line 1
@@ -460,7 +460,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t");
// Handle situation when pasted block doesn't start new line.
// Handle a situation when pasted block doesn't start a new line.
if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') {
int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t");
if (firstNonWsOffset > firstLineStart) {
@@ -550,7 +550,7 @@ public class PasteHandler extends EditorActionHandler implements EditorTextInser
}
}
else {
CharSequence toInsert = chars.subSequence(anchorLineStart, j + diff);
CharSequence toInsert = chars.subSequence(anchorLineStart, diff + startOffset);
for (int line = anchorLine + 1; line <= lastLine; line++) {
document.insertString(document.getLineStartOffset(line), toInsert);
}
@@ -131,7 +131,6 @@ class MoverWrapper {
}
});
}
CodeFoldingManager.getInstance(project).allowFoldingOnCaretLine(editor);
if (hasSelection) {
restoreSelection(editor, selectionStart, selectionEnd, start, myInfo.range2.getStartOffset());
@@ -50,14 +50,4 @@ public abstract class CodeFoldingManager {
public abstract void releaseFoldings(Editor editor);
public abstract void buildInitialFoldings(Editor editor);
/**
* Asks do not perform automatic expansion of fold region that is located on the caret line during the next fold regions update.
* <p/>
* This method is necessary because fold regions that are located on caret line are automatically expanded to prevent problem
* from IDEA-64687. However, we don't want such an expansion when we, for example, move method up or down.
*
* @param editor target editor
*/
public abstract void allowFoldingOnCaretLine(@NotNull Editor editor);
}
@@ -331,9 +331,4 @@ public class CodeFoldingManagerImpl extends CodeFoldingManager implements Projec
document.putUserData(FOLDING_STATE_INFO_IN_DOCUMENT_KEY, null);
}
}
@Override
public void allowFoldingOnCaretLine(@NotNull Editor editor) {
editor.putUserData(UpdateFoldRegionsOperation.ALLOW_FOLDING_ON_CARET_LINE_KEY, true);
}
}
@@ -18,14 +18,12 @@ package com.intellij.codeInsight.folding.impl;
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
@@ -43,9 +41,6 @@ import static com.intellij.util.containers.CollectionFactory.newTroveMap;
* @author cdr
*/
class UpdateFoldRegionsOperation implements Runnable {
static final Key<Boolean> ALLOW_FOLDING_ON_CARET_LINE_KEY = Key.create("AllowFoldingOnCaretLine.KEY");
private final Project myProject;
private final Editor myEditor;
private final PsiFile myFile;
@@ -80,9 +75,6 @@ class UpdateFoldRegionsOperation implements Runnable {
List<FoldRegion> newRegions = addNewRegions(info, foldingModel, rangeToExpandStatusMap, shouldExpand, groupExpand);
applyExpandStatus(newRegions, shouldExpand, groupExpand);
// Reset the key.
myEditor.putUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY, false);
}
private static void applyExpandStatus(@NotNull List<FoldRegion> newRegions,
@@ -147,24 +139,9 @@ class UpdateFoldRegionsOperation implements Runnable {
// Considering that this code is executed only on initial fold regions construction on editor opening.
return !FoldingPolicy.isCollapseByDefault(element);
}
boolean caretInside;
if (myEditor.getUserData(ALLOW_FOLDING_ON_CARET_LINE_KEY) == Boolean.TRUE) {
caretInside = FoldingUtil.caretInsideRange(myEditor, range);
}
else {
final Document document = myEditor.getDocument();
final int firstLine = document.getLineNumber(range.getStartOffset());
final int lastLine = document.getLineNumber(range.getEndOffset());
int caretOffset = myEditor.getCaretModel().getOffset();
if (caretOffset > myEditor.getDocument().getTextLength()) {
return false;
}
final int currentLine = document.getLineNumber(caretOffset);
caretInside = firstLine <= currentLine && currentLine <= lastLine;
}
final Boolean oldStatus = rangeToExpandStatusMap.get(range);
return oldStatus == null || caretInside || oldStatus.booleanValue();
return oldStatus == null || FoldingUtil.caretInsideRange(myEditor, range) || oldStatus.booleanValue();
}
private void removeInvalidRegions(@NotNull EditorFoldingInfo info,
@@ -95,6 +95,7 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
private final JPanel myPanel = new JPanel(new MyLayout());
private String myTitle;
@Nullable
private String myPrompt = "> ";
private final LightVirtualFile myHistoryFile;
private Editor myCurrentEditor;
@@ -316,11 +317,12 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
return myHistoryFile;
}
@Nullable
public String getPrompt() {
return myPrompt;
}
public void setPrompt(String prompt) {
public void setPrompt(@Nullable String prompt) {
// always add space to the prompt otherwise it may look ugly
myPrompt = prompt != null && !prompt.endsWith(" ") ? prompt + " " : prompt;
setPromptInner(myPrompt);
@@ -435,8 +437,10 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
protected String addTextRangeToHistory(TextRange textRange, final EditorEx consoleEditor, boolean preserveMarkup) {
final Document history = myHistoryViewer.getDocument();
final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true);
appendToHistoryDocument(history, myPrompt);
markupModel.addRangeHighlighter(history.getTextLength() - myPrompt.length(), history.getTextLength(), HighlighterLayer.SYNTAX,
if (myPrompt != null) {
appendToHistoryDocument(history, myPrompt);
}
markupModel.addRangeHighlighter(history.getTextLength() - StringUtil.length(myPrompt), history.getTextLength(), HighlighterLayer.SYNTAX,
ConsoleViewContentType.USER_INPUT.getAttributes(),
HighlighterTargetArea.EXACT_RANGE);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@ package com.intellij.formatting;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
@@ -34,7 +33,6 @@ import com.intellij.psi.formatter.PsiBasedFormattingModel;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SequentialTask;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -98,7 +96,7 @@ public class FormatterImpl extends FormatterEx
@Override
public void setProgressTask(@NotNull FormattingProgressTask progressIndicator) {
if (!FormatterUtil.FORMATTER_ACTION_NAMES.contains(CommandProcessor.getInstance().getCurrentCommandName())) {
if (!FormatterUtil.isFormatterCalledExplicitly()) {
return;
}
myProgressTask.set(progressIndicator);
@@ -694,7 +692,7 @@ public class FormatterImpl extends FormatterEx
final boolean keepLineBreaksFlag,
final int keepLineBreaks,
final boolean keepFirstColumn, int prefLineFeeds) {
synchronized(this) {
synchronized(ourSharedSpacing) {
ourSharedSpacing.init(minSpaces, maxSpaces, minLineFeeds, readOnly, safe, keepLineBreaksFlag, keepLineBreaks, keepFirstColumn, prefLineFeeds);
SpacingImpl spacing = ourSharedProperties.get(ourSharedSpacing);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,7 +37,7 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar
IdeView view = e.getData(LangDataKeys.IDE_VIEW);
Project project = e.getData(PlatformDataKeys.PROJECT);
if (view == null) {
if (view == null || project == null) {
return;
}
PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
@@ -29,6 +29,7 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -39,11 +40,9 @@ import java.util.Set;
public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
private final ProjectFileIndex myIndex;
private final LinkedHashSet<VirtualFile> myEntries = new LinkedHashSet<VirtualFile>();
private final List<Module> myModules;
public LibraryRuntimeClasspathScope(final Project project, final List<Module> modules) {
super(project);
myModules = modules;
myIndex = ProjectRootManager.getInstance(project).getFileIndex();
final Set<Sdk> processedSdk = new THashSet<Sdk>();
final Set<Library> processedLibraries = new THashSet<Library>();
@@ -63,8 +62,14 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
}
}
public LibraryRuntimeClasspathScope(Project project, LibraryOrderEntry entry) {
super(project);
myIndex = ProjectRootManager.getInstance(project).getFileIndex();
Collections.addAll(myEntries, entry.getRootFiles(OrderRootType.CLASSES));
}
public int hashCode() {
return myModules.hashCode();
return myEntries.hashCode();
}
public boolean equals(Object object) {
@@ -72,7 +77,7 @@ public class LibraryRuntimeClasspathScope extends GlobalSearchScope {
if (object == null || object.getClass() != LibraryRuntimeClasspathScope.class) return false;
final LibraryRuntimeClasspathScope that = (LibraryRuntimeClasspathScope)object;
return that.myModules.equals(myModules);
return that.myEntries.equals(myEntries);
}
private void buildEntries(@NotNull final Module module,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.actions.ReformatAndOptimizeImportsProcessor;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.TokenType;
@@ -292,7 +293,11 @@ public class FormatterUtil {
private static ASTNode findPreviousWhiteSpace(final ASTNode leafElement, final IElementType whiteSpaceTokenType) {
final int offset = leafElement.getTextRange().getStartOffset() - 1;
if (offset < 0) return null;
final PsiElement found = SourceTreeToPsiMap.treeElementToPsi(leafElement).getContainingFile().findElementAt(offset);
final PsiElement psiElement = SourceTreeToPsiMap.treeElementToPsi(leafElement);
if (psiElement == null) {
return null;
}
final PsiElement found = psiElement.getContainingFile().findElementAt(offset);
if (found == null) return null;
final ASTNode treeElement = found.getNode();
if (treeElement != null && treeElement.getElementType() == whiteSpaceTokenType) return treeElement;
@@ -357,6 +362,9 @@ public class FormatterUtil {
public static void replaceLastWhiteSpace(final ASTNode astNode, final String whiteSpace, final TextRange textRange) {
ASTNode lastWS = TreeUtil.findLastLeaf(astNode);
if (lastWS == null) {
return;
}
if (lastWS.getElementType() != TokenType.WHITE_SPACE) {
lastWS = null;
}
@@ -381,4 +389,11 @@ public class FormatterUtil {
treeParent.replaceChild(lastWS, whiteSpaceElement);
}
}
/**
* @return <code>true</code> explicitly called 'reformat' is in progress at the moment; <code>false</code> otherwise
*/
public static boolean isFormatterCalledExplicitly() {
return FORMATTER_ACTION_NAMES.contains(CommandProcessor.getInstance().getCurrentCommandName());
}
}
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.file.impl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.impl.scopes.LibraryRuntimeClasspathScope;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
@@ -25,6 +26,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.ResolveScopeManager;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.psi.search.DelegatingGlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.containers.ConcurrentFactoryMap;
@@ -91,6 +93,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
List<Module> modulesLibraryUsedIn = new ArrayList<Module>();
List<OrderEntry> orderEntries = projectFileIndex.getOrderEntriesForFile(vFile);
LibraryOrderEntry lib = null;
for (OrderEntry entry : orderEntries) {
ProgressManager.checkCanceled();
@@ -98,12 +101,32 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
return ((ProjectRootManagerEx)myProjectRootManager).getScopeForJdk((JdkOrderEntry)entry);
}
if (entry instanceof LibraryOrderEntry || entry instanceof ModuleOrderEntry) {
if (entry instanceof LibraryOrderEntry) {
lib = (LibraryOrderEntry)entry;
modulesLibraryUsedIn.add(entry.getOwnerModule());
}
else if (entry instanceof ModuleOrderEntry) {
modulesLibraryUsedIn.add(entry.getOwnerModule());
}
}
return ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn);
GlobalSearchScope allCandidates = ((ProjectRootManagerEx)myProjectRootManager).getScopeForLibraryUsedIn(modulesLibraryUsedIn);
if (lib != null) {
final LibraryRuntimeClasspathScope preferred = new LibraryRuntimeClasspathScope(myProject, lib);
// prefer current library
return new DelegatingGlobalSearchScope(allCandidates, preferred) {
@Override
public int compare(VirtualFile file1, VirtualFile file2) {
boolean c1 = preferred.contains(file1);
boolean c2 = preferred.contains(file2);
if (c1 && !c2) return 1;
if (c2 && !c1) return -1;
return super.compare(file1, file2);
}
};
}
return allCandidates;
}
}
@@ -48,6 +48,7 @@ import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import org.intellij.lang.annotations.MagicConstant;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -224,7 +225,7 @@ public abstract class DialogWrapper {
* @param canBeParent can be parent
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
*/
protected DialogWrapper(Component parent, boolean canBeParent) {
protected DialogWrapper(@NotNull Component parent, boolean canBeParent) {
ensureEventDispatchThread();
myPeer = createPeer(parent, canBeParent);
createDefaultActions();
@@ -101,14 +101,14 @@ public class Messages {
/**
* Please, use {@link #showOkCancelDialog} or {@link #showYesNoCancelDialog} if possible (these dialogs implements native OS behavior)!
*/
public static int showDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, @Nullable Icon icon) {
public static int showDialog(@Nullable Project project, String message, String title, String[] options, int defaultOptionIndex, @Nullable Icon icon) {
return showDialog(project, message, title, options, defaultOptionIndex, icon, null);
}
/**
* Please, use {@link #showOkCancelDialog} or {@link #showYesNoCancelDialog} if possible (these dialogs implements native OS behavior)!
*/
public static int showDialog(Project project, String message, String title, String[] options, int defaultOptionIndex, @Nullable Icon icon,
public static int showDialog(@Nullable Project project, String message, String title, String[] options, int defaultOptionIndex, @Nullable Icon icon,
@Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
if (isApplicationInUnitTestOrHeadless()) {
return ourTestImplementation.show(message);
@@ -238,7 +238,7 @@ public class Messages {
/**
* @return <code>0</code> if user pressed "Yes" and returns <code>1</code> if user pressed "No" button.
*/
public static int showYesNoDialog(Project project, String message, String title, String yesText, String noText, @Nullable Icon icon) {
public static int showYesNoDialog(@Nullable Project project, String message, String title, String yesText, String noText, @Nullable Icon icon) {
if (canShowMacSheetPanel()) {
return MacMessages.getInstance().showYesNoDialog(title, message, yesText, noText, WindowManager.getInstance().suggestParentWindow(project));
}
@@ -249,7 +249,7 @@ public class Messages {
/**
* @return <code>0</code> if user pressed "Yes" and returns <code>1</code> if user pressed "No" button.
*/
public static int showYesNoDialog(Project project, String message, String title, @Nullable Icon icon) {
public static int showYesNoDialog(@Nullable Project project, String message, String title, @Nullable Icon icon) {
if (canShowMacSheetPanel()) {
return MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
}
@@ -72,7 +72,7 @@ public abstract class WindowManager {
* that can be parent.
*/
@Nullable
public abstract Window suggestParentWindow(Project project);
public abstract Window suggestParentWindow(@Nullable Project project);
/**
* Get the status bar for the project's main frame
@@ -35,7 +35,7 @@ public class UiNotifyConnector implements Disposable, HierarchyListener{
private final WeakReference<Component> myComponent;
private Activatable myTarget;
public UiNotifyConnector(final Component component, final Activatable target) {
public UiNotifyConnector(@NotNull final Component component, @NotNull final Activatable target) {
myComponent = new WeakReference<Component>(component);
myTarget = target;
if (component.isShowing()) {
@@ -33,7 +33,7 @@ import java.awt.*;
public class HintUtil {
public static final Color INFORMATION_COLOR = new Color(253, 254, 226);
public static final Color QUESTION_COLOR = new Color(181, 208, 251);
private static final Color ERROR_COLOR = new Color(255, 220, 220);
public static final Color ERROR_COLOR = new Color(255, 220, 220);
private static final Icon INFORMATION_ICON = null;
private static final Icon QUESTION_ICON = IconLoader.getIcon("/actions/help.png");
@@ -91,7 +91,7 @@ public class HintUtil {
}
public static JComponent createInformationLabel(final SimpleColoredText text, final Icon icon) {
SimpleColoredComponent highlighted = new SimpleColoredComponent ();
SimpleColoredComponent highlighted = new SimpleColoredComponent();
highlighted.setIcon(icon);
highlighted.setBackground(INFORMATION_COLOR);
@@ -219,6 +219,5 @@ public class HintUtil {
public String toString() {
return "Hint: text='" + (myPane != null ? myPane.getText() : "") + "'";
}
}
}
@@ -32,6 +32,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
@@ -75,6 +76,8 @@ import static java.awt.event.KeyEvent.*;
@SuppressWarnings({"AssignmentToStaticFieldFromInstanceMethod", "SSBasedInspection"})
public class Switcher extends AnAction implements DumbAware {
private static volatile SwitcherPanel SWITCHER = null;
private static final Icon PIN_ON = IconLoader.getIcon("/general/autohideOn.png");
private static final Icon PIN_OFF = IconLoader.getIcon("/general/autohideOff.png");
private static final Color BORDER_COLOR = Gray._135;
private static final Color SEPARATOR_COLOR = BORDER_COLOR.brighter();
@NonNls private static final String SWITCHER_FEATURE_ID = "switcher";
@@ -189,7 +192,7 @@ public class Switcher extends AnAction implements DumbAware {
addKeyListener(this);
setBorder(new EmptyBorder(0, 0, 0, 0));
setBackground(Color.WHITE);
pathLabel.setHorizontalAlignment(SwingConstants.RIGHT);
pathLabel.setHorizontalAlignment(SwingConstants.LEFT);
final Font font = pathLabel.getFont();
pathLabel.setFont(font.deriveFont((float)10));
@@ -204,7 +207,19 @@ public class Switcher extends AnAction implements DumbAware {
};
descriptions.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4));
descriptions.add(pathLabel);
descriptions.add(pathLabel, BorderLayout.CENTER);
final JLabel pinLabel = new JLabel(isPinnedMode() ? PIN_ON : PIN_OFF);
pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode");
pinLabel.setBorder(IdeBorderFactory.createEmptyBorder(0, 10, 0, 0));
descriptions.add(pinLabel, BorderLayout.EAST);
pinLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE = !UISettings.getInstance().HIDE_SWITCHER_ON_CONTROL_RELEASE;
pinLabel.setIcon(isPinnedMode() ? PIN_ON : PIN_OFF);
pinLabel.setToolTipText(isPinnedMode() ? "Pinned mode" : "Floating mode");
}
});
twManager = ToolWindowManager.getInstance(project);
final DefaultListModel twModel = new DefaultListModel();
for (String id : twManager.getToolWindowIds()) {
@@ -285,6 +300,7 @@ public class Switcher extends AnAction implements DumbAware {
final VirtualFile[] recentFiles = ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles());
final int maxFiles = Math.max(editors.size(), recentFiles.length);
final int len = isPinnedMode() ? maxFiles : Math.min(toolWindows.getModel().getSize(), maxFiles);
boolean firstRecentMarked = false;
for (int i = 0; i < len; i++) {
final FileInfo info = new FileInfo(recentFiles[i], null);
boolean add = true;
@@ -298,6 +314,10 @@ public class Switcher extends AnAction implements DumbAware {
}
if (add) {
filesData.add(info);
if (!firstRecentMarked) {
firstRecentMarked = true;
info.isSeparator = true;
}
}
}
if (editors.size() == 1 && (filesData.isEmpty() || !editors.get(0).getFirst().equals(filesData.get(0).getFirst()))) {
@@ -743,6 +763,7 @@ public class Switcher extends AnAction implements DumbAware {
public SwitcherSpeedSearch() {
super(SwitcherPanel.this);
addChangeListener(this);
setComparator(new SpeedSearchComparator(false, true));
}
@Override
@@ -805,6 +826,7 @@ public class Switcher extends AnAction implements DumbAware {
private final Project myProject;
private final SpeedSearchBase mySearch;
private boolean hide = false;
private boolean separator = false;
public VirtualFilesRenderer(Project project, SpeedSearchBase search) {
myProject = project;
@@ -817,10 +839,12 @@ public class Switcher extends AnAction implements DumbAware {
final VirtualFile virtualFile = ((FileInfo)value).first;
final String name = virtualFile.getPresentableName();
setIcon(IconUtil.getIcon(virtualFile, Iconable.ICON_FLAG_READ_STATUS, myProject));
separator = ((FileInfo)value).isSeparator;
if ( mySearch != null && mySearch.isPopupActive()) {
hide = mySearch.matchingFragments(name) == null && !StringUtil.isEmpty(mySearch.getEnteredPrefix());
}
final FileStatus fileStatus = FileStatusManager.getInstance(myProject).getStatus(virtualFile);
final TextAttributes attributes = new TextAttributes(fileStatus.getColor(), null, null, EffectType.LINE_UNDERSCORE, Font.PLAIN);
append(name, SimpleTextAttributes.fromTextAttributes(attributes));
@@ -835,10 +859,14 @@ public class Switcher extends AnAction implements DumbAware {
}
super.doPaint(g);
config.restore();
if (separator) {
UIUtil.drawDottedLine(g, 0, 0, getWidth(), 0, Color.WHITE, Color.BLACK);
}
}
}
private static class FileInfo extends Pair<VirtualFile, EditorWindow> {
boolean isSeparator = false;
public FileInfo(VirtualFile first, EditorWindow second) {
super(first, second);
}
@@ -36,6 +36,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.net.IOExceptionDialog;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.io.IOException;
@@ -157,7 +158,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
if (needToRestart) {
notifyPluginsWereInstalled();
notifyPluginsWereInstalled(list.size() == 1 ? list.get(0).getName() : null);
}
}
}
@@ -256,7 +257,7 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
}
}
private static void notifyPluginsWereInstalled() {
private static void notifyPluginsWereInstalled(@Nullable String pluginName) {
final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
final boolean restartCapable = app.isRestartCapable();
String message = "<html>";
@@ -265,7 +266,8 @@ public class ActionInstallPlugin extends AnAction implements DumbAware {
message += "<br><a href=";
message += restartCapable ? "\"restart\">Restart now" : "\"shutdown\">Shutdown";
message += "</a></html>";
Notifications.Bus.notify(new Notification(IdeBundle.message("title.plugin.error"), IdeBundle.message("title.plugin.error"),
Notifications.Bus.notify(new Notification("Plugins Lifecycle Group",
pluginName != null ? "Plugin \'" + pluginName + "\' was successfully installed" : "Plugins were installed",
message, NotificationType.INFORMATION, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
@@ -53,15 +53,17 @@ public class DetectedPluginsPanel extends OrderPanel<PluginDownloader> {
final int row,
final int column) {
final PluginDownloader downloader = (PluginDownloader)value;
append(downloader.getPluginName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(PluginId.getId(downloader.getPluginId()));
final String loadedVersion = downloader.getPluginVersion();
if (loadedVersion != null || (ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null)) {
final String installedVersion = ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null
? "v. " + ideaPluginDescriptor.getVersion() + (loadedVersion != null ? " -> " : "")
: "";
final String availableVersion = loadedVersion != null ? loadedVersion : "";
append(" (" + installedVersion + availableVersion + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
if (downloader != null) {
append(downloader.getPluginName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
final IdeaPluginDescriptor ideaPluginDescriptor = PluginManager.getPlugin(PluginId.getId(downloader.getPluginId()));
final String loadedVersion = downloader.getPluginVersion();
if (loadedVersion != null || (ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null)) {
final String installedVersion = ideaPluginDescriptor != null && ideaPluginDescriptor.getVersion() != null
? "v. " + ideaPluginDescriptor.getVersion() + (loadedVersion != null ? " -> " : "")
: "";
final String availableVersion = loadedVersion != null ? loadedVersion : "";
append(" (" + installedVersion + availableVersion + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}
}
});
@@ -57,7 +57,7 @@ public final class TestWindowManager extends WindowManagerEx implements Applicat
return null;
}
public final Window suggestParentWindow(final Project project) {
public final Window suggestParentWindow(@Nullable final Project project) {
return null;
}
@@ -69,7 +69,7 @@
</component>
</children>
</grid>
<grid id="eecc0" binding="myPlaceHolder" layout-manager="BorderLayout" hgap="0" vgap="0">
<grid id="eecc0" binding="myPlaceHolder" layout-manager="GridBagLayout">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
@@ -30,10 +30,7 @@ import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.*;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
@@ -278,4 +275,26 @@ import java.util.Collection;
}
}.execute().throwException();
}
public static void addLibrary(final Module module,
final String libName, final String libDir,
final String[] classRoots,
final String[] sourceRoots) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, libDir);
final Library library = model.getModuleLibraryTable().createLibrary(libName);
final Library.ModifiableModel libModifiableModel = library.getModifiableModel();
for (String classRoot : classRoots) {
libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES);
}
for (String sourceRoot : sourceRoots) {
libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES);
}
libModifiableModel.commit();
model.commit();
}
});
}
}
@@ -30,9 +30,9 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder {
}
@Override
public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
public ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk) || AndroidJpsUtil.isLightBuild(context)) {
return ModuleLevelBuilder.ExitCode.OK;
return ExitCode.NOTHING_DONE;
}
try {
@@ -48,6 +48,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder {
final AndroidFileSetStorage storage = new AndroidFileSetStorage(context.getDataManager().getDataStorageRoot(), "libs_packaging");
try {
boolean doneSomething = false;
for (Module module : chunk.getModules()) {
final AndroidFacet facet = AndroidJpsUtil.getFacet(module);
if (facet == null || !facet.isLibrary()) {
@@ -82,7 +83,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder {
if (subdirs.size() > 0) {
context.processMessage(new ProgressMessage(AndroidJpsBundle.message("android.jps.progress.library.packaging", module.getName())));
final File outputJarFile = new File(outputDirectoryForPackagedFiles, AndroidCommonUtils.CLASSES_JAR_FILE_NAME);
doneSomething = true;
try {
AndroidCommonUtils.packClassFilesIntoJar(ArrayUtil.EMPTY_STRING_ARRAY, ArrayUtil.toStringArray(subdirs), outputJarFile);
storage.update(module.getName(), newState);
@@ -94,7 +95,7 @@ public class AndroidLibraryPackagingBuilder extends ModuleLevelBuilder {
}
}
}
return success ? ModuleLevelBuilder.ExitCode.OK : ModuleLevelBuilder.ExitCode.ABORT;
return success ? (doneSomething? ExitCode.OK : ExitCode.NOTHING_DONE) : ExitCode.ABORT;
}
finally {
storage.close();
@@ -61,7 +61,7 @@ public class AndroidSourceGeneratingBuilder extends ModuleLevelBuilder {
@Override
public ModuleLevelBuilder.ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
if (context.isCompilingTests() || !AndroidJpsUtil.containsAndroidFacet(chunk)) {
return ModuleLevelBuilder.ExitCode.OK;
return ExitCode.NOTHING_DONE;
}
try {
@@ -30,6 +30,7 @@ import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.ArrayUtil;
public class EclipseLibrariesModificationsTest extends EclipseVarsTest {
@@ -38,22 +39,8 @@ public class EclipseLibrariesModificationsTest extends EclipseVarsTest {
final Project project = getProject();
final String path = project.getBaseDir().getPath() + "/test";
final Module module = EclipseClasspathTest.setUpModule(path, project);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
final String parentUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, model.getContentRoots()[0].getParent().getPath());
final Library library = model.getModuleLibraryTable().createLibrary("created");
final Library.ModifiableModel libModifiableModel = library.getModifiableModel();
for (String classRoot : classRoots) {
libModifiableModel.addRoot(parentUrl + classRoot, OrderRootType.CLASSES);
}
for (String sourceRoot : sourceRoots) {
libModifiableModel.addRoot(parentUrl + sourceRoot, OrderRootType.SOURCES);
}
libModifiableModel.commit();
model.commit();
}
});
PsiTestUtil.addLibrary(module, "created", ModuleRootManager.getInstance(module).getContentRoots()[0].getParent().getPath(), classRoots,
sourceRoots);
EclipseClasspathTest.checkModule(project.getBaseDir().getPath() + "/expected", module);
}
@@ -49,7 +49,7 @@ public class GroovyBuilder extends ModuleLevelBuilder {
try {
final List<File> toCompile = collectChangedFiles(context, chunk);
if (toCompile.isEmpty()) {
return ExitCode.OK;
return ExitCode.NOTHING_DONE;
}
String moduleOutput = getModuleOutput(context, chunk);
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.folding;
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
import com.intellij.codeInsight.folding.impl.JavaFoldingBuilder;
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.CustomFoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
@@ -194,7 +195,7 @@ public class GroovyFoldingBuilder extends CustomFoldingBuilder implements Groovy
int start = first.getTextRange().getStartOffset();
int end = marker.getTextRange().getEndOffset();
int tail = "import ".length();
if (start + tail < end) {
if (start + tail < end && !JavaFoldingBuilder.hasErrorElementsNearby(first.getContainingFile(), start, end)) {
descriptors.add(new FoldingDescriptor(first.getNode(), new TextRange(start + tail, end)));
}
}
@@ -47,6 +47,25 @@ class GroovyFoldingTest extends LightCodeInsightFixtureTestCase {
assert assertNoFolding(myFixture.file.text.indexOf(marker)), marker
}
public void testEditingImports() {
configure """
import java.util.List
import java.util.Map
<caret>
println 'hello'
class Foo { List a; Map b; }
"""
assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10)
myFixture.type 'import '
myFixture.doHighlighting()
assert !myFixture.editor.foldingModel.getCollapsedRegionAtOffset(10)
}
void testOpenBlock() {
configure '''def foo() {print 'a'}
def bar() {
@@ -252,7 +252,7 @@ public abstract class TestObject implements JavaCommandLine {
@Override
public ExecutionResult execute(final Executor executor, @NotNull final ProgramRunner runner) throws ExecutionException {
final JUnitProcessHandler handler = createHandler();
final JUnitProcessHandler handler = createHandler(executor);
final RunnerSettings runnerSettings = getRunnerSettings();
JavaRunConfigurationExtensionManager.getInstance().attachExtensionsToProcess(myConfiguration, handler, runnerSettings);
final TestProxy unboundOutputRoot = new TestProxy(new RootTestInfo());
@@ -360,19 +360,20 @@ public abstract class TestObject implements JavaCommandLine {
TestsUIUtil.notifyByBalloon(myProject, model != null ? model.getRoot() : null, consoleProperties);
}
protected JUnitProcessHandler createHandler() throws ExecutionException {
appendForkInfo();
protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException {
appendForkInfo(executor);
return JUnitProcessHandler.runCommandLine(CommandLineBuilder.createFromJavaParameters(myJavaParameters, myProject, true));
}
private void appendForkInfo() throws ExecutionException {
private void appendForkInfo(Executor executor) throws ExecutionException {
final String forkMode = myConfiguration.getForkMode();
if (Comparing.strEqual(forkMode, "none")) {
return;
}
if (myRunnerSettings.getData() instanceof DebuggingRunnerData) {
throw new CantRunException("Debug is disabled in fork mode.<br/>Please change fork mode to &lt;none&gt; to debug.");
if (myRunnerSettings.getData() != null) {
final String actionName = executor.getActionName();
throw new CantRunException(actionName + " is disabled in fork mode.<br/>Please change fork mode to &lt;none&gt; to " + actionName.toLowerCase() + ".");
}
final JavaParameters javaParameters = getJavaParameters();
@@ -87,8 +87,8 @@ public class TestPackage extends TestObject {
}
@Override
protected JUnitProcessHandler createHandler() throws ExecutionException {
final JUnitProcessHandler handler = super.createHandler();
protected JUnitProcessHandler createHandler(Executor executor) throws ExecutionException {
final JUnitProcessHandler handler = super.createHandler(executor);
final SearchForTestsTask[] tasks = new SearchForTestsTask[1];
handler.addProcessListener(new ProcessAdapter() {
@Override
@@ -17,7 +17,6 @@ package com.intellij.junit4;
import org.junit.Ignore;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.builders.JUnit3Builder;
import org.junit.internal.requests.ClassRequest;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.runner.Description;
@@ -151,7 +150,7 @@ public class JUnit4TestRunnerUtil {
}
try {
if (clazz.getMethod("suite", new Class[0]) != null && !methodName.equals("suite")) {
return Request.runner(new JUnit3Builder().runnerForClass(clazz)).filterWith(Description.createTestDescription(clazz, methodName));
return Request.classWithoutSuiteMethod(clazz).filterWith(Description.createTestDescription(clazz, methodName));
}
}
catch (Throwable e) {
@@ -21,6 +21,8 @@ import com.intellij.psi.PsiReference;
import org.jetbrains.idea.maven.indices.MavenIndicesTestFixture;
import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndicesTestCase {
@@ -70,10 +72,11 @@ public class MavenExtensionCompletionAndResolutionTest extends MavenDomWithIndic
List<String> actual = getCompletionVariants(myProjectPom);
if (actual.isEmpty()) {
if (!new HashSet<String>(actual).equals(new HashSet<String>(Arrays.asList("maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin")))) {
MavenProjectIndicesManager instance = MavenProjectIndicesManager.getInstance(myProject);
System.out.println("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins"));
System.out.println("Indexes: " + instance.getIndices());
throw new AssertionError("GetArtifacts: " + instance.getArtifactIds("org.apache.maven.plugins") + "Indexes: " + instance.getIndices());
}
assertUnorderedElementsAreEqual(actual, "maven-compiler-plugin", "maven-war-plugin", "maven-eclipse-plugin", "maven-surefire-plugin");
@@ -164,6 +164,7 @@ error.exception.while.reloading=Exception while reloading classes : {0} : {1}
status.hotswap.loaded.classes.up.to.date=Loaded classes are up to date. Nothing to reload
error.io.error=I/O error
status.classes.reloaded={0,number} {0,choice, 0#classes|1#class|2#classes} reloaded
status.classes.not.all.versions.reloaded=For {0} of {1} {1,choice, 1#class|2#classes} not all versions were reloaded
error.cannot.create.void.value=Cannot create void value
warning.range.too.big=Range specified is too big. {0} needs too much resources to perform requested operation. Are you sure you want to continue?
title.range.too.big=Range is Too Big
@@ -17,13 +17,11 @@ package com.intellij.xml.util;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.PsiAnchor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.xmlb.JDOMXIncluder;
@@ -82,12 +80,7 @@ class InclusionProvider implements CachedValueProvider<PsiElement[]> {
final XmlTag[] includeTag = extractXpointer(rootTag, xpointer);
PsiElement[] result = new PsiElement[includeTag.length];
for (int i = 0; i < includeTag.length; i++) {
XmlTag xmlTag = includeTag[i];
final PsiElement psiElement = xmlTag.copy();
psiElement.putUserData(XmlElement.INCLUDING_ELEMENT, xincludeTag.getParentTag());
psiElement.putUserData(XmlUtil.ORIGINAL_ELEMENT, PsiAnchor.create(xmlTag));
result[i] = psiElement;
//result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag());
result[i] = new IncludedXmlTag(includeTag[i], xincludeTag.getParentTag());
}
return result;
}