mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Generated
+2
-2
@@ -1,11 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Netty">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/netty-3.2.5.Final.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/netty-3.3.0.Final.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/netty-3.2.5.Final-sources.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/lib/src/netty-3.3.0.Final-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.intellij.images.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -65,7 +66,7 @@ public class ImageInfoReader {
|
||||
|
||||
@Nullable
|
||||
private static Info read(@NotNull final byte[] data) {
|
||||
final DataInputStream is = new DataInputStream(new ByteArrayInputStream(data));
|
||||
final DataInputStream is = new DataInputStream(new UnsyncByteArrayInputStream(data));
|
||||
try {
|
||||
return readFileData(is);
|
||||
}
|
||||
|
||||
@@ -966,7 +966,8 @@ public class CompileDriver {
|
||||
boolean didSomething = false;
|
||||
|
||||
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
|
||||
GenericCompilerRunner runner = new GenericCompilerRunner(context, myCompilerFilter, compilerManager, isRebuild, onlyCheckStatus);
|
||||
GenericCompilerRunner runner = new GenericCompilerRunner(context, isRebuild, onlyCheckStatus,
|
||||
compilerManager.getCompilers(GenericCompiler.class, myCompilerFilter));
|
||||
try {
|
||||
didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus);
|
||||
|
||||
|
||||
@@ -53,14 +53,12 @@ public class GenericCompilerRunner {
|
||||
private final Project myProject;
|
||||
|
||||
public GenericCompilerRunner(CompileContext context,
|
||||
CompilerFilter compilerFilter,
|
||||
CompilerManager compilerManager,
|
||||
boolean forceCompile,
|
||||
boolean onlyCheckStatus) {
|
||||
boolean onlyCheckStatus, final GenericCompiler[] compilers) {
|
||||
myContext = context;
|
||||
myForceCompile = forceCompile;
|
||||
myOnlyCheckStatus = onlyCheckStatus;
|
||||
myCompilers = compilerManager.getCompilers(GenericCompiler.class, compilerFilter);
|
||||
myCompilers = compilers;
|
||||
myProject = myContext.getProject();
|
||||
}
|
||||
|
||||
@@ -69,7 +67,7 @@ public class GenericCompilerRunner {
|
||||
try {
|
||||
for (GenericCompiler<?,?,?> compiler : myCompilers) {
|
||||
if (compiler.getOrderPlace().equals(place)) {
|
||||
didSomething = invokeCompiler(compiler);
|
||||
didSomething |= invokeCompiler(compiler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.compiler.generic;
|
||||
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class SingleTargetCompilerInstance<Item extends CompileItem<K,S,O>, K,S, O> extends
|
||||
GenericCompilerInstance<BuildTarget, Item, K, S, O> {
|
||||
protected SingleTargetCompilerInstance(CompileContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<BuildTarget> getAllTargets() {
|
||||
return Collections.singletonList(BuildTarget.DEFAULT);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<BuildTarget> getSelectedTargets() {
|
||||
return getAllTargets();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<GenericCompilerCacheState<K, S, O>> obsoleteItems) {
|
||||
}
|
||||
}
|
||||
-2
@@ -16,8 +16,6 @@
|
||||
package com.intellij.openapi.compiler.generic;
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
|
||||
+1
@@ -99,6 +99,7 @@ public class BuildArtifactsBeforeRunTaskProvider extends BeforeRunTaskProvider<B
|
||||
}
|
||||
|
||||
public BuildArtifactsBeforeRunTask createTask(RunConfiguration runConfiguration) {
|
||||
if (myProject.isDefault()) return null;
|
||||
return new BuildArtifactsBeforeRunTask(myProject);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,9 +61,16 @@ public class RequestHint {
|
||||
private boolean myMethodExecuted;
|
||||
|
||||
public SmartStepFilter(PsiMethod psiMethod) {
|
||||
myDeclaringClassName = JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass());
|
||||
myTargetMethodName = psiMethod.isConstructor()? "<init>" : psiMethod.getName();
|
||||
myTargetMethodSignature = JVMNameUtil.getJVMSignature(psiMethod);
|
||||
this(JVMNameUtil.getJVMQualifiedName(psiMethod.getContainingClass()),
|
||||
psiMethod.isConstructor()? "<init>" : psiMethod.getName(),
|
||||
JVMNameUtil.getJVMSignature(psiMethod));
|
||||
}
|
||||
|
||||
public SmartStepFilter(@NotNull JVMName declaringClassName, @NonNls String targetMethodName,
|
||||
@NotNull JVMName targetMethodSignature) {
|
||||
myDeclaringClassName = declaringClassName;
|
||||
myTargetMethodName = targetMethodName;
|
||||
myTargetMethodSignature = targetMethodSignature;
|
||||
}
|
||||
|
||||
public String getTargetMethodName() {
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -106,14 +107,7 @@ public class JavaExecutionUtil {
|
||||
|
||||
@Nullable
|
||||
public static String getRuntimeQualifiedName(final PsiClass aClass) {
|
||||
final PsiClass containingClass = aClass.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
final String parentName = getRuntimeQualifiedName(containingClass);
|
||||
return parentName + "$" + aClass.getName();
|
||||
}
|
||||
else {
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
return ClassUtil.getJVMClassName(aClass);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+1
-2
@@ -16,7 +16,6 @@
|
||||
package com.intellij.psi.impl.file;
|
||||
|
||||
import com.intellij.ide.projectView.ProjectView;
|
||||
import com.intellij.ide.projectView.impl.ProjectViewPane;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.GlobalUndoableAction;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
@@ -139,7 +138,7 @@ public class PsiPackageImplementationHelperImpl extends PsiPackageImplementation
|
||||
final ProjectView projectView = ProjectView.getInstance(project);
|
||||
PsiDirectory[] directories = suggestMostAppropriateDirectories(psiPackage);
|
||||
if (directories.length == 0) return;
|
||||
projectView.getProjectViewPaneById(ProjectViewPane.ID).select(directories[0], directories[0].getVirtualFile(), requestFocus);
|
||||
projectView.select(directories[0], directories[0].getVirtualFile(), requestFocus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<margin top="2" left="0" bottom="2" right="3"/>
|
||||
<text resource-bundle="messages/IdeBundle" key="unscramble.use.unscrambler.checkbox"/>
|
||||
</properties>
|
||||
</component>
|
||||
@@ -81,11 +82,12 @@
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<margin top="2" left="0" bottom="2" right="3"/>
|
||||
<text value="Automatically detect and analyze thread dumps copied to the clipboard outside of IntelliJ IDEA"/>
|
||||
</properties>
|
||||
</component>
|
||||
<grid id="28646" binding="myBottomPanel" custom-create="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<margin top="0" left="3" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
|
||||
@@ -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.
|
||||
@@ -16,15 +16,15 @@
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.NullableComputable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -347,18 +347,26 @@ public class ExceptionUtil {
|
||||
|
||||
@NotNull
|
||||
public static List<PsiClassType> getUnhandledCloserExceptions(final PsiResourceVariable resource, @Nullable final PsiElement topElement) {
|
||||
final PsiType resourceType = resource.getType();
|
||||
if (resourceType instanceof PsiClassType) {
|
||||
final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
|
||||
if (resourceClass != null) {
|
||||
final PsiMethod[] closers = resourceClass.findMethodsByName("close", false);
|
||||
for (final PsiMethod method : closers) {
|
||||
if (method.getParameterList().getParametersCount() == 0) {
|
||||
return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY);
|
||||
final Project project = resource.getProject();
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
|
||||
final PsiClass autoCloseable = facade.findClass(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, ProjectScope.getLibrariesScope(project));
|
||||
if (autoCloseable != null) {
|
||||
final PsiMethod[] methods = autoCloseable.findMethodsByName("close", false);
|
||||
if (methods.length == 1) {
|
||||
final MethodSignature signature = methods[0].getSignature(PsiSubstitutor.EMPTY);
|
||||
final PsiType resourceType = resource.getType();
|
||||
if (resourceType instanceof PsiClassType) {
|
||||
final PsiClass resourceClass = ((PsiClassType)resourceType).resolve();
|
||||
if (resourceClass != null) {
|
||||
final PsiMethod method = MethodSignatureUtil.findMethodBySignature(resourceClass, signature, true);
|
||||
if (method != null) {
|
||||
return getUnhandledExceptions(method, resource, topElement, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import static com.intellij.lang.PsiBuilderUtil.expect;
|
||||
import static com.intellij.lang.PsiBuilderUtil.nextTokenType;
|
||||
@@ -86,7 +87,7 @@ public class DeclarationParser {
|
||||
}
|
||||
parseClassBodyDeclarations(builderWrapper, isAnnotation);
|
||||
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -139,7 +140,7 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
if (declarationsAfterEnd) {
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +427,7 @@ public class DeclarationParser {
|
||||
final boolean anno, final boolean constructor) {
|
||||
parseParameterList(builder);
|
||||
|
||||
eatBrackets(builder, constructor, JavaErrorMessages.message("expected.semicolon"));
|
||||
eatBrackets(builder, constructor, "expected.semicolon");
|
||||
|
||||
if (areTypeAnnotationsSupported(builder)) {
|
||||
final PsiBuilder.Marker receiver = builder.mark();
|
||||
@@ -489,8 +490,8 @@ public class DeclarationParser {
|
||||
builder.advanceLexer();
|
||||
|
||||
final IElementType delimiter = resources ? JavaTokenType.SEMICOLON : JavaTokenType.COMMA;
|
||||
final String noDelimiterMsg = JavaErrorMessages.message(resources ? "expected.semicolon" : "expected.comma");
|
||||
final String noElementMsg = JavaErrorMessages.message(resources ? "expected.resource" : "expected.parameter");
|
||||
final String noDelimiterMsg = resources ? "expected.semicolon" : "expected.comma";
|
||||
final String noElementMsg = resources ? "expected.resource" : "expected.parameter";
|
||||
|
||||
PsiBuilder.Marker invalidElements = null;
|
||||
String errorMessage = null;
|
||||
@@ -548,7 +549,7 @@ public class DeclarationParser {
|
||||
|
||||
if (invalidElements == null) {
|
||||
if (builder.getTokenType() == delimiter) {
|
||||
error(builder, noElementMsg);
|
||||
error(builder, JavaErrorMessages.message(noElementMsg));
|
||||
builder.advanceLexer();
|
||||
if (noElements && resources) {
|
||||
noElements = false;
|
||||
@@ -557,7 +558,7 @@ public class DeclarationParser {
|
||||
}
|
||||
else {
|
||||
invalidElements = builder.mark();
|
||||
errorMessage = delimiterExpected ? noDelimiterMsg : noElementMsg;
|
||||
errorMessage = JavaErrorMessages.message(delimiterExpected ? noDelimiterMsg : noElementMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +614,7 @@ public class DeclarationParser {
|
||||
|
||||
if (expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
if (!resource) {
|
||||
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, JavaErrorMessages.message("expected.rparen"));
|
||||
eatBrackets(builder, typeInfo != null && typeInfo.isVarArg, "expected.rparen");
|
||||
done(param, JavaElementType.PARAMETER);
|
||||
return param;
|
||||
}
|
||||
@@ -624,7 +625,7 @@ public class DeclarationParser {
|
||||
return modListInfo.first;
|
||||
}
|
||||
|
||||
if (expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"))) {
|
||||
if (expectOrError(builder, JavaTokenType.EQ, "expected.eq")) {
|
||||
if (myExpressionParser.parse(builder) == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
@@ -720,7 +721,8 @@ public class DeclarationParser {
|
||||
return declaration;
|
||||
}
|
||||
|
||||
private static boolean eatBrackets(final PsiBuilder builder, final boolean isError, @Nullable final String error) {
|
||||
private static boolean eatBrackets(final PsiBuilder builder, final boolean isError,
|
||||
@Nullable @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorKey) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACKET) return true;
|
||||
|
||||
final PsiBuilder.Marker marker = isError ? builder.mark() : null;
|
||||
@@ -735,7 +737,7 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
if (marker != null) {
|
||||
marker.error(error);
|
||||
marker.error(errorKey != null ? JavaErrorMessages.message(errorKey):null);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -840,9 +842,9 @@ public class DeclarationParser {
|
||||
pair = builder.mark();
|
||||
}
|
||||
|
||||
final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"));
|
||||
final boolean hasName = expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier");
|
||||
|
||||
expectOrError(builder, JavaTokenType.EQ, JavaErrorMessages.message("expected.eq"));
|
||||
expectOrError(builder, JavaTokenType.EQ, "expected.eq");
|
||||
|
||||
parseAnnotationValue(builder);
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -404,7 +404,7 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker refExpr = expr.precede();
|
||||
myReferenceParser.parseReferenceParameterList(builder, false, false);
|
||||
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, JavaErrorMessages.message("expected.identifier"))) {
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.IDENTIFIER, "expected.identifier")) {
|
||||
refExpr.done(JavaElementType.REFERENCE_EXPRESSION);
|
||||
startMarker.drop();
|
||||
return refExpr;
|
||||
@@ -726,7 +726,7 @@ public class ExpressionParser {
|
||||
}
|
||||
bracketCount++;
|
||||
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, JavaErrorMessages.message("expected.rbracket"))) {
|
||||
if (!JavaParserUtil.expectOrError(builder, JavaTokenType.RBRACKET, "expected.rbracket")) {
|
||||
newExpr.done(JavaElementType.NEW_EXPRESSION);
|
||||
return newExpr;
|
||||
}
|
||||
@@ -812,7 +812,7 @@ public class ExpressionParser {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, JavaErrorMessages.message("expected.rparen"));
|
||||
final boolean closed = JavaParserUtil.expectOrError(builder, JavaTokenType.RPARENTH, "expected.rparen");
|
||||
|
||||
list.done(JavaElementType.EXPRESSION_LIST);
|
||||
if (!closed) {
|
||||
@@ -827,35 +827,29 @@ public class ExpressionParser {
|
||||
|
||||
@Nullable
|
||||
private static IElementType getGtTokenType(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker sp = builder.mark();
|
||||
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.GT) {
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTGTEQ;
|
||||
}
|
||||
else {
|
||||
tokenType = JavaTokenType.GTGTGT;
|
||||
}
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTEQ;
|
||||
if (tokenType != JavaTokenType.GT) return tokenType;
|
||||
|
||||
if (builder.rawLookup(1) == JavaTokenType.GT) {
|
||||
if (builder.rawLookup(2) == JavaTokenType.GT) {
|
||||
if (builder.rawLookup(3) == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTGTEQ;
|
||||
}
|
||||
else {
|
||||
tokenType = JavaTokenType.GTGT;
|
||||
tokenType = JavaTokenType.GTGTGT;
|
||||
}
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GE;
|
||||
else if (builder.rawLookup(2) == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GTGTEQ;
|
||||
}
|
||||
else {
|
||||
tokenType = JavaTokenType.GTGT;
|
||||
}
|
||||
}
|
||||
else if (builder.rawLookup(1) == JavaTokenType.EQ) {
|
||||
tokenType = JavaTokenType.GE;
|
||||
}
|
||||
|
||||
sp.rollbackTo();
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -258,9 +259,10 @@ public class JavaParserUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, final String errorMessage) {
|
||||
public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType,
|
||||
@PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String errorMessageKey) {
|
||||
if (!PsiBuilderUtil.expect(builder, expectedType)) {
|
||||
error(builder, errorMessage);
|
||||
error(builder, JavaErrorMessages.message(errorMessageKey));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -275,7 +277,7 @@ public class JavaParserUtil {
|
||||
}
|
||||
|
||||
public static void semicolon(final PsiBuilder builder) {
|
||||
expectOrError(builder, JavaTokenType.SEMICOLON, JavaErrorMessages.message("expected.semicolon"));
|
||||
expectOrError(builder, JavaTokenType.SEMICOLON, "expected.semicolon");
|
||||
}
|
||||
|
||||
public static PsiBuilder braceMatchingBuilder(final PsiBuilder builder) {
|
||||
|
||||
@@ -293,7 +293,7 @@ public class ReferenceParser {
|
||||
if (expect(builder, JavaTokenType.GT)) {
|
||||
break;
|
||||
}
|
||||
else if (!expectOrError(builder, JavaTokenType.COMMA, JavaErrorMessages.message("expected.gt.or.comma"))) {
|
||||
else if (!expectOrError(builder, JavaTokenType.COMMA, "expected.gt.or.comma")) {
|
||||
isOk = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ public class StatementParser {
|
||||
|
||||
parseStatements(builder, parseUntilEof ? BraceMode.TILL_LAST : BraceMode.TILL_FIRST);
|
||||
|
||||
final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
final boolean greedyBlock = !expectOrError(builder, JavaTokenType.RBRACE, "expected.rbrace");
|
||||
builder.getTokenType(); // eat spaces
|
||||
|
||||
done(codeBlock, JavaElementType.CODE_BLOCK);
|
||||
@@ -543,7 +543,7 @@ public class StatementParser {
|
||||
}
|
||||
}
|
||||
|
||||
expectOrError(builder, JavaTokenType.COLON, JavaErrorMessages.message("expected.colon"));
|
||||
expectOrError(builder, JavaTokenType.COLON, "expected.colon");
|
||||
|
||||
done(statement, JavaElementType.SWITCH_LABEL_STATEMENT);
|
||||
return statement;
|
||||
|
||||
@@ -328,6 +328,7 @@ expected.lparen.or.lbracket='(' or '[' expected
|
||||
expected.array.initializer=Array initializer expected
|
||||
unexpected.tokens=Unexpected tokens
|
||||
expected.gt.or.comma='>' or ',' expected.
|
||||
string.expected=String literal expected
|
||||
else.without.if='else' without 'if'
|
||||
catch.without.try='catch' without 'try'
|
||||
finally.without.try='finally' without 'try'
|
||||
|
||||
+19
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
class C {
|
||||
static class E extends Exception { }
|
||||
static class E1 extends E { }
|
||||
@@ -10,6 +25,8 @@ class C {
|
||||
@Override public void close() throws E3 { }
|
||||
}
|
||||
|
||||
static interface I extends AutoCloseable { }
|
||||
|
||||
void m1() {
|
||||
try (MyResource r = new MyResource()) { r.doSomething(); }
|
||||
catch (E1 | E2 | E3 ignore) { }
|
||||
@@ -24,6 +41,8 @@ class C {
|
||||
catch (E3 e) { }
|
||||
|
||||
try (MyResource r = <error descr="Unhandled exception: C.E1">new MyResource()</error>) { }
|
||||
|
||||
try (<error descr="Unhandled exception from auto-closeable resource: java.lang.Exception">I r = null</error>) { System.out.println(r); }
|
||||
}
|
||||
|
||||
void m2() throws Exception {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:Binary2.java
|
||||
PsiAssignmentExpression:a > = b
|
||||
PsiBinaryExpression:a >
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:b
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:b('b')
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:Binary3.java
|
||||
PsiAssignmentExpression:a >/**/= b
|
||||
PsiBinaryExpression:a >
|
||||
PsiReferenceExpression:a
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:a('a')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiComment(C_STYLE_COMMENT)('/**/')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:b
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:b('b')
|
||||
@@ -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.
|
||||
@@ -54,7 +54,7 @@ public class JavaLexerTest extends LexerTestCase {
|
||||
"DOUBLE_LITERAL ('1e137')");
|
||||
}
|
||||
|
||||
public void testTigerNumericLiterals() throws Exception {
|
||||
public void testTigerNumericLiterals() {
|
||||
doTest("0xap0f 0xab.p0F 0x.abcP0f 0xabc.defP0F",
|
||||
"FLOAT_LITERAL ('0xap0f')\nWHITE_SPACE (' ')\n" +
|
||||
"FLOAT_LITERAL ('0xab.p0F')\nWHITE_SPACE (' ')\n" +
|
||||
@@ -115,7 +115,7 @@ public class JavaLexerTest extends LexerTestCase {
|
||||
"DOUBLE_LITERAL ('0xa_bc.de_fP1_234D')");
|
||||
}
|
||||
|
||||
public void testMalformedCoinLiterals() throws Exception {
|
||||
public void testMalformedCoinLiterals() {
|
||||
doTest("0_ _1 0_8 0x_f 0b_1 0B2 0x1.0_p-1 1.0e_1022",
|
||||
"INTEGER_LITERAL ('0')\nIDENTIFIER ('_')\nWHITE_SPACE (' ')\n" +
|
||||
"IDENTIFIER ('_1')\nWHITE_SPACE (' ')\n" +
|
||||
@@ -127,6 +127,13 @@ public class JavaLexerTest extends LexerTestCase {
|
||||
"DOUBLE_LITERAL ('1.0e')\nIDENTIFIER ('_1022')");
|
||||
}
|
||||
|
||||
public void testMalformedOperators() {
|
||||
doTest("(i > = 0)",
|
||||
"LPARENTH ('(')\nIDENTIFIER ('i')\nWHITE_SPACE (' ')\n" +
|
||||
"GT ('>')\nWHITE_SPACE (' ')\nEQ ('=')\n" +
|
||||
"WHITE_SPACE (' ')\nINTEGER_LITERAL ('0')\nRPARENTH (')')\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Lexer createLexer() {
|
||||
return new JavaLexer(LanguageLevel.HIGHEST);
|
||||
|
||||
+3
-1
@@ -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.
|
||||
@@ -32,6 +32,8 @@ public class ExpressionParserTest extends JavaParsingTestCase {
|
||||
|
||||
public void testBinary0() { doParserTest("a + b"); }
|
||||
public void testBinary1() { doParserTest("a < b"); }
|
||||
public void testBinary2() { doParserTest("a > = b"); }
|
||||
public void testBinary3() { doParserTest("a >/**/= b"); }
|
||||
|
||||
public void testCond0() { doParserTest("cond ? true : false"); }
|
||||
public void testCond1() { doParserTest("cond ?"); }
|
||||
|
||||
@@ -245,26 +245,19 @@ public class ClassUtil {
|
||||
|
||||
@Nullable
|
||||
public static String getJVMClassName(PsiClass aClass) {
|
||||
final String qName = aClass.getQualifiedName();
|
||||
if (qName == null) return null;
|
||||
return replaceDotsWithDollars(qName, aClass);
|
||||
}
|
||||
|
||||
private static String replaceDotsWithDollars(final String qName, PsiClass aClass) {
|
||||
StringBuilder qNameBuffer = new StringBuilder(qName);
|
||||
|
||||
int fromIndex = qNameBuffer.length();
|
||||
PsiElement parent = aClass.getParent();
|
||||
while (parent instanceof PsiClass) {
|
||||
final int dotIndex = qNameBuffer.lastIndexOf(".", fromIndex);
|
||||
if (dotIndex < 0) break;
|
||||
qNameBuffer.replace(dotIndex, dotIndex + 1, "$");
|
||||
fromIndex = dotIndex - 1;
|
||||
parent = parent.getParent();
|
||||
final PsiClass containingClass = aClass.getContainingClass();
|
||||
if (containingClass != null) {
|
||||
String parentName = getJVMClassName(containingClass);
|
||||
if (parentName == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parentName + "$" + aClass.getName();
|
||||
}
|
||||
return qNameBuffer.toString();
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static PsiClass findPsiClassByJVMName(final PsiManager manager, final String jvmClassName) {
|
||||
return findPsiClass(manager, jvmClassName.replace('/', '.'), null, true);
|
||||
|
||||
+4
-1
@@ -42,6 +42,9 @@ public class DefaultLightProjectDescriptor implements LightProjectDescriptor {
|
||||
|
||||
@Override
|
||||
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
|
||||
model.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(LanguageLevel.HIGHEST);
|
||||
LanguageLevelModuleExtension extension = model.getModuleExtension(LanguageLevelModuleExtension.class);
|
||||
if (extension != null) {
|
||||
extension.setLanguageLevel(LanguageLevel.HIGHEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,160 +1,10 @@
|
||||
package org.jetbrains.jps.incremental;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.ether.dependencyView.Mappings;
|
||||
import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 9/17/11
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class Builder {
|
||||
private static final Key<Set<File>> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
|
||||
private static final Key<Set<File>> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
|
||||
|
||||
public static enum ExitCode {
|
||||
OK, ABORT, ADDITIONAL_PASS_REQUIRED
|
||||
}
|
||||
|
||||
public abstract String getName();
|
||||
|
||||
public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
|
||||
|
||||
public abstract String getDescription();
|
||||
|
||||
public void cleanupResources(CompileContext context, ModuleChunk chunk) {
|
||||
ALL_AFFECTED_FILES_KEY.set(context, null);
|
||||
ALL_COMPILED_FILES_KEY.set(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param delta
|
||||
* @param chunk
|
||||
* @param filesToCompile files compiled in this round
|
||||
* @param successfullyCompiled
|
||||
* @return true if additional compilation pass is required, false otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
public final boolean updateMappings(CompileContext context, final Mappings delta, ModuleChunk chunk, Collection<File> filesToCompile, Collection<File> successfullyCompiled) throws Exception {
|
||||
try {
|
||||
boolean additionalPassRequired = false;
|
||||
|
||||
final Set<String> removedPaths = getRemovedPaths(context);
|
||||
|
||||
final Mappings globalMappings = context.getDataManager().getMappings();
|
||||
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (globalMappings) {
|
||||
if (!context.isProjectRebuild() && context.shouldDifferentiate(chunk, context.isCompilingTests())) {
|
||||
final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
|
||||
final Set<File> allAffectedFiles = getAllAffectedFilesContainer(context);
|
||||
|
||||
// mark as affected all files that were dirty before compilation
|
||||
allAffectedFiles.addAll(filesToCompile);
|
||||
// accumulate all successfully compiled in this round
|
||||
allCompiledFiles.addAll(successfullyCompiled);
|
||||
// unmark as affected all successfully compiled
|
||||
allAffectedFiles.removeAll(successfullyCompiled);
|
||||
|
||||
final HashSet<File> affectedBeforeDif = new HashSet<File>(allAffectedFiles);
|
||||
|
||||
final boolean incremental = globalMappings.differentiate(
|
||||
delta, removedPaths, successfullyCompiled, allCompiledFiles, allAffectedFiles
|
||||
);
|
||||
|
||||
if (incremental) {
|
||||
final Set<File> newlyAffectedFiles = new HashSet<File>(allAffectedFiles);
|
||||
newlyAffectedFiles.removeAll(affectedBeforeDif);
|
||||
newlyAffectedFiles.removeAll(allCompiledFiles); // the diff operation may have affected the class already compiled in thic compilation round
|
||||
|
||||
if (!newlyAffectedFiles.isEmpty()) {
|
||||
for (File file : newlyAffectedFiles) {
|
||||
context.markDirty(file);
|
||||
}
|
||||
additionalPassRequired = context.isMake() && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
additionalPassRequired = context.isMake();
|
||||
context.markDirtyRecursively(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
globalMappings.integrate(delta, successfullyCompiled, removedPaths);
|
||||
}
|
||||
|
||||
return additionalPassRequired;
|
||||
}
|
||||
catch(RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw ((IOException)cause);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// delete all class files that according to mappings correspond to given sources
|
||||
public static void deleteCorrespondingOutputFiles(CompileContext context, Map<File, Module> sources) throws Exception {
|
||||
if (!context.isProjectRebuild() && !sources.isEmpty()) {
|
||||
for (Map.Entry<File, Module> pair : sources.entrySet()) {
|
||||
final File file = pair.getKey();
|
||||
final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
|
||||
final String moduleName = pair.getValue().getName().toLowerCase(Locale.US);
|
||||
final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests());
|
||||
final Collection<String> outputs = srcToOut.getState(srcPath);
|
||||
if (outputs != null) {
|
||||
for (String output : outputs) {
|
||||
FileUtil.delete(new File(output));
|
||||
}
|
||||
srcToOut.remove(srcPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected) throws Exception {
|
||||
final Set<Module> chunkModules = new HashSet<Module>(chunk.getModules());
|
||||
if (!chunkModules.isEmpty()) {
|
||||
for (File file : affected) {
|
||||
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file);
|
||||
if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.module)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set<File> getAllAffectedFilesContainer(CompileContext context) {
|
||||
Set<File> allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context);
|
||||
if (allAffectedFiles == null) {
|
||||
allAffectedFiles = new HashSet<File>();
|
||||
ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles);
|
||||
}
|
||||
return allAffectedFiles;
|
||||
}
|
||||
|
||||
private static Set<File> getAllCompiledFilesContainer(CompileContext context) {
|
||||
Set<File> allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
|
||||
if (allCompiledFiles == null) {
|
||||
allCompiledFiles = new HashSet<File>();
|
||||
ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
|
||||
}
|
||||
return allCompiledFiles;
|
||||
}
|
||||
|
||||
private static Set<String> getRemovedPaths(CompileContext context) {
|
||||
final Set<String> removed = Paths.CHUNK_REMOVED_SOURCES_KEY.get(context);
|
||||
return removed != null? removed : Collections.<String>emptySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.jetbrains.jps.incremental;
|
||||
|
||||
import org.jetbrains.jps.incremental.groovy.GroovyBuilder;
|
||||
import org.jetbrains.jps.incremental.java.JavaBuilder;
|
||||
import org.jetbrains.jps.incremental.resourses.ResourcesBuilder;
|
||||
import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -16,7 +16,7 @@ public class BuilderRegistry {
|
||||
private static class Holder {
|
||||
static final BuilderRegistry ourInstance = new BuilderRegistry();
|
||||
}
|
||||
private final Map<BuilderCategory, List<Builder>> myBuilders = new HashMap<BuilderCategory, List<Builder>>();
|
||||
private final Map<BuilderCategory, List<ModuleLevelBuilder>> myBuilders = new HashMap<BuilderCategory, List<ModuleLevelBuilder>>();
|
||||
private ExecutorService myTasksExecutor;
|
||||
|
||||
public static BuilderRegistry getInstance() {
|
||||
@@ -25,7 +25,7 @@ public class BuilderRegistry {
|
||||
|
||||
private BuilderRegistry() {
|
||||
for (BuilderCategory category : BuilderCategory.values()) {
|
||||
myBuilders.put(category, new ArrayList<Builder>());
|
||||
myBuilders.put(category, new ArrayList<ModuleLevelBuilder>());
|
||||
}
|
||||
final Runtime runtime = Runtime.getRuntime();
|
||||
myTasksExecutor = Executors.newFixedThreadPool(runtime.availableProcessors());
|
||||
@@ -60,7 +60,7 @@ public class BuilderRegistry {
|
||||
return Collections.emptyList(); // todo
|
||||
}
|
||||
|
||||
public List<Builder> getBuilders(BuilderCategory category){
|
||||
public List<ModuleLevelBuilder> getBuilders(BuilderCategory category){
|
||||
return Collections.unmodifiableList(myBuilders.get(category)); // todo
|
||||
}
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ public class IncProjectBuilder {
|
||||
finally {
|
||||
try {
|
||||
for (BuilderCategory category : BuilderCategory.values()) {
|
||||
for (Builder builder : myBuilderRegistry.getBuilders(category)) {
|
||||
for (ModuleLevelBuilder builder : myBuilderRegistry.getBuilders(category)) {
|
||||
builder.cleanupResources(context, chunk);
|
||||
}
|
||||
}
|
||||
@@ -334,7 +334,7 @@ public class IncProjectBuilder {
|
||||
}
|
||||
|
||||
private void runBuilders(CompileContext context, ModuleChunk chunk, BuilderCategory category) throws ProjectBuildException {
|
||||
final List<Builder> builders = myBuilderRegistry.getBuilders(category);
|
||||
final List<ModuleLevelBuilder> builders = myBuilderRegistry.getBuilders(category);
|
||||
if (builders.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -347,16 +347,16 @@ public class IncProjectBuilder {
|
||||
do {
|
||||
nextPassRequired = false;
|
||||
context.beforeNextCompileRound(chunk);
|
||||
for (Builder builder : builders) {
|
||||
final Builder.ExitCode buildResult = builder.build(context, chunk);
|
||||
for (ModuleLevelBuilder builder : builders) {
|
||||
final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk);
|
||||
|
||||
if (buildResult == Builder.ExitCode.ABORT) {
|
||||
if (buildResult == ModuleLevelBuilder.ExitCode.ABORT) {
|
||||
throw new ProjectBuildException("Builder " + builder.getDescription() + " requested build stop");
|
||||
}
|
||||
if (myCancelStatus.isCanceled()) {
|
||||
throw new ProjectBuildException(CANCELED_MESSAGE);
|
||||
}
|
||||
if (buildResult == Builder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
|
||||
if (buildResult == ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED) {
|
||||
if (!nextPassRequired) {
|
||||
// recalculate basis
|
||||
myModulesProcessed -= (stagesPassed * modulesInChunk) / stageCount;
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package org.jetbrains.jps.incremental;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.ether.dependencyView.Mappings;
|
||||
import org.jetbrains.jps.Module;
|
||||
import org.jetbrains.jps.ModuleChunk;
|
||||
import org.jetbrains.jps.incremental.storage.SourceToOutputMapping;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 9/17/11
|
||||
*/
|
||||
public abstract class ModuleLevelBuilder extends Builder {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.Builder");
|
||||
|
||||
private static final Key<Set<File>> ALL_AFFECTED_FILES_KEY = Key.create("_all_affected_files_");
|
||||
private static final Key<Set<File>> ALL_COMPILED_FILES_KEY = Key.create("_all_compiled_files_");
|
||||
|
||||
public static enum ExitCode {
|
||||
OK, ABORT, ADDITIONAL_PASS_REQUIRED
|
||||
}
|
||||
|
||||
public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
|
||||
|
||||
public void cleanupResources(CompileContext context, ModuleChunk chunk) {
|
||||
ALL_AFFECTED_FILES_KEY.set(context, null);
|
||||
ALL_COMPILED_FILES_KEY.set(context, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* @param delta
|
||||
* @param chunk
|
||||
* @param filesToCompile files compiled in this round
|
||||
* @param successfullyCompiled
|
||||
* @return true if additional compilation pass is required, false otherwise
|
||||
* @throws Exception
|
||||
*/
|
||||
public final boolean updateMappings(CompileContext context, final Mappings delta, ModuleChunk chunk, Collection<File> filesToCompile, Collection<File> successfullyCompiled) throws Exception {
|
||||
try {
|
||||
boolean additionalPassRequired = false;
|
||||
|
||||
final Set<String> removedPaths = getRemovedPaths(context);
|
||||
|
||||
final Mappings globalMappings = context.getDataManager().getMappings();
|
||||
|
||||
//noinspection SynchronizationOnLocalVariableOrMethodParameter
|
||||
synchronized (globalMappings) {
|
||||
if (!context.isProjectRebuild() && context.shouldDifferentiate(chunk, context.isCompilingTests())) {
|
||||
final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
|
||||
final Set<File> allAffectedFiles = getAllAffectedFilesContainer(context);
|
||||
|
||||
// mark as affected all files that were dirty before compilation
|
||||
allAffectedFiles.addAll(filesToCompile);
|
||||
// accumulate all successfully compiled in this round
|
||||
allCompiledFiles.addAll(successfullyCompiled);
|
||||
// unmark as affected all successfully compiled
|
||||
allAffectedFiles.removeAll(successfullyCompiled);
|
||||
|
||||
final HashSet<File> affectedBeforeDif = new HashSet<File>(allAffectedFiles);
|
||||
|
||||
final boolean incremental = globalMappings.differentiate(
|
||||
delta, removedPaths, successfullyCompiled, allCompiledFiles, allAffectedFiles
|
||||
);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Differentiate Results:");
|
||||
|
||||
LOG.debug(" Compiled Files:");
|
||||
|
||||
for (final File c : allCompiledFiles) {
|
||||
LOG.debug(" " + c.getAbsolutePath());
|
||||
}
|
||||
|
||||
LOG.debug(" Affected Files:");
|
||||
|
||||
for (final File c : allAffectedFiles) {
|
||||
LOG.debug(" " + c.getAbsolutePath());
|
||||
}
|
||||
|
||||
LOG.debug("End Of Differentiate Results.");
|
||||
}
|
||||
|
||||
if (incremental) {
|
||||
final Set<File> newlyAffectedFiles = new HashSet<File>(allAffectedFiles);
|
||||
newlyAffectedFiles.removeAll(affectedBeforeDif);
|
||||
newlyAffectedFiles.removeAll(allCompiledFiles); // the diff operation may have affected the class already compiled in thic compilation round
|
||||
|
||||
if (!newlyAffectedFiles.isEmpty()) {
|
||||
for (File file : newlyAffectedFiles) {
|
||||
context.markDirty(file);
|
||||
}
|
||||
additionalPassRequired = context.isMake() && chunkContainsAffectedFiles(context, chunk, newlyAffectedFiles);
|
||||
}
|
||||
}
|
||||
else {
|
||||
additionalPassRequired = context.isMake();
|
||||
context.markDirtyRecursively(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
globalMappings.integrate(delta, successfullyCompiled, removedPaths);
|
||||
}
|
||||
|
||||
return additionalPassRequired;
|
||||
}
|
||||
catch(RuntimeException e) {
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause instanceof IOException) {
|
||||
throw ((IOException)cause);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// delete all class files that according to mappings correspond to given sources
|
||||
public static void deleteCorrespondingOutputFiles(CompileContext context, Map<File, Module> sources) throws Exception {
|
||||
if (!context.isProjectRebuild() && !sources.isEmpty()) {
|
||||
for (Map.Entry<File, Module> pair : sources.entrySet()) {
|
||||
final File file = pair.getKey();
|
||||
final String srcPath = FileUtil.toSystemIndependentName(file.getPath());
|
||||
final String moduleName = pair.getValue().getName().toLowerCase(Locale.US);
|
||||
final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests());
|
||||
final Collection<String> outputs = srcToOut.getState(srcPath);
|
||||
if (outputs != null) {
|
||||
for (String output : outputs) {
|
||||
FileUtil.delete(new File(output));
|
||||
}
|
||||
srcToOut.remove(srcPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean chunkContainsAffectedFiles(CompileContext context, ModuleChunk chunk, final Set<File> affected) throws Exception {
|
||||
final Set<Module> chunkModules = new HashSet<Module>(chunk.getModules());
|
||||
if (!chunkModules.isEmpty()) {
|
||||
for (File file : affected) {
|
||||
final RootDescriptor moduleAndRoot = context.getModuleAndRoot(file);
|
||||
if (moduleAndRoot != null && chunkModules.contains(moduleAndRoot.module)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set<File> getAllAffectedFilesContainer(CompileContext context) {
|
||||
Set<File> allAffectedFiles = ALL_AFFECTED_FILES_KEY.get(context);
|
||||
if (allAffectedFiles == null) {
|
||||
allAffectedFiles = new HashSet<File>();
|
||||
ALL_AFFECTED_FILES_KEY.set(context, allAffectedFiles);
|
||||
}
|
||||
return allAffectedFiles;
|
||||
}
|
||||
|
||||
private static Set<File> getAllCompiledFilesContainer(CompileContext context) {
|
||||
Set<File> allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
|
||||
if (allCompiledFiles == null) {
|
||||
allCompiledFiles = new HashSet<File>();
|
||||
ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
|
||||
}
|
||||
return allCompiledFiles;
|
||||
}
|
||||
|
||||
private static Set<String> getRemovedPaths(CompileContext context) {
|
||||
final Set<String> removed = Paths.CHUNK_REMOVED_SOURCES_KEY.get(context);
|
||||
return removed != null? removed : Collections.<String>emptySet();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.jetbrains.jps.incremental;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ProjectLevelBuilder extends Builder {
|
||||
private final ProjectLevelBuilderCategory myCategory;
|
||||
|
||||
protected ProjectLevelBuilder(ProjectLevelBuilderCategory category) {
|
||||
myCategory = category;
|
||||
}
|
||||
|
||||
public abstract void build(CompileContext context);
|
||||
|
||||
public ProjectLevelBuilderCategory getCategory() {
|
||||
return myCategory;
|
||||
}
|
||||
|
||||
public static enum ProjectLevelBuilderCategory { TRANSLATOR, PACKAGER }
|
||||
}
|
||||
@@ -29,7 +29,7 @@ import java.util.*;
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 10/25/11
|
||||
*/
|
||||
public class GroovyBuilder extends Builder {
|
||||
public class GroovyBuilder extends ModuleLevelBuilder {
|
||||
public static final String BUILDER_NAME = "groovy";
|
||||
private final boolean myForStubs;
|
||||
private final String myBuilderName;
|
||||
@@ -43,7 +43,7 @@ public class GroovyBuilder extends Builder {
|
||||
return myBuilderName;
|
||||
}
|
||||
|
||||
public Builder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
|
||||
public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk) throws ProjectBuildException {
|
||||
ExitCode exitCode = ExitCode.OK;
|
||||
final Map<File, Module> toCompile = new HashMap<File, Module>();
|
||||
try {
|
||||
@@ -104,12 +104,13 @@ public class GroovyBuilder extends Builder {
|
||||
|
||||
// todo CompilerUtil.addLocaleOptions()
|
||||
//todo different outputs in a chunk
|
||||
//todo xmx
|
||||
//todo module jdk path
|
||||
final List<String> cmd = ExternalProcessUtil.buildJavaCommandLine(
|
||||
SystemProperties.getJavaHome() + "/bin/java",
|
||||
"org.jetbrains.groovy.compiler.rt.GroovycRunner",
|
||||
Collections.<String>emptyList(), new ArrayList<String>(cp),
|
||||
Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5858"*/),
|
||||
Arrays.asList("-Xmx384m"/*, "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239"*/),
|
||||
Arrays.<String>asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath())
|
||||
);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ import java.util.concurrent.ExecutorService;
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 9/21/11
|
||||
*/
|
||||
public class JavaBuilder extends Builder{
|
||||
public class JavaBuilder extends ModuleLevelBuilder {
|
||||
public static final String BUILDER_NAME = "java";
|
||||
private static final String JAVA_EXTENSION = ".java";
|
||||
private static final String FORM_EXTENSION = ".form";
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.jps.incremental.resourses;
|
||||
package org.jetbrains.jps.incremental.resources;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -19,7 +19,7 @@ import java.util.Locale;
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 10/6/11
|
||||
*/
|
||||
public class ResourcesBuilder extends Builder{
|
||||
public class ResourcesBuilder extends ModuleLevelBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.resourses.ResourcesBuilder");
|
||||
public static final String BUILDER_NAME = "resources";
|
||||
|
||||
@@ -172,9 +172,23 @@ class DependencyContext {
|
||||
public Logger<S> getLogger(final com.intellij.openapi.diagnostic.Logger log) {
|
||||
return new Logger<S>() {
|
||||
@Override
|
||||
public void debug(S s) {
|
||||
public void debug(String comment, S s) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(getValue(s));
|
||||
log.debug(comment + getValue(s));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String comment, String t) {
|
||||
if (log.isDebugEnabled()){
|
||||
log.debug(comment + t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String comment, boolean t) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(comment + Boolean.toString(t));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,5 +23,7 @@ package org.jetbrains.ether.dependencyView;
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public interface Logger<T> {
|
||||
void debug(T t);
|
||||
void debug(String comment, T t);
|
||||
void debug(String comment, String t);
|
||||
void debug(String comment, boolean t);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.jetbrains.ether.dependencyView;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
@@ -22,7 +21,7 @@ import java.util.*;
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public class Mappings {
|
||||
private final static Logger LOG = Logger.getInstance ("#org.jetbrains.ether.dependencyView.Mappings");
|
||||
private final static Logger LOG = Logger.getInstance("#org.jetbrains.ether.dependencyView.Mappings");
|
||||
|
||||
private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab";
|
||||
private final static String CLASS_TO_CLASS = "classToClass.tab";
|
||||
@@ -38,12 +37,20 @@ public class Mappings {
|
||||
private DependencyContext myContext;
|
||||
private org.jetbrains.ether.dependencyView.Logger<DependencyContext.S> myDebugS;
|
||||
|
||||
private void debug(final String s) {
|
||||
private static void debug(final String s) {
|
||||
LOG.debug(s);
|
||||
}
|
||||
|
||||
private void debug(final DependencyContext.S s) {
|
||||
myDebugS.debug(s);
|
||||
private void debug(final String comment, final DependencyContext.S s) {
|
||||
myDebugS.debug(comment, s);
|
||||
}
|
||||
|
||||
private void debug(final String comment, final String s) {
|
||||
myDebugS.debug(comment, s);
|
||||
}
|
||||
|
||||
private void debug(final String comment, final boolean s) {
|
||||
myDebugS.debug(comment, s);
|
||||
}
|
||||
|
||||
private MultiMaplet<DependencyContext.S, DependencyContext.S> myClassToSubclasses;
|
||||
@@ -534,16 +541,25 @@ public class Mappings {
|
||||
final Collection<UsageRepr.Usage> affectedUsages,
|
||||
final Collection<DependencyContext.S> dependants,
|
||||
final boolean usages) {
|
||||
debug("Affecting subclasses of class: ", className);
|
||||
|
||||
final DependencyContext.S fileName = myClassToSourceFile.get(className);
|
||||
|
||||
if (fileName == null) {
|
||||
debug("No source file detected for class ", className);
|
||||
debug("End of affectSubclasses");
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Source file name: ", fileName);
|
||||
|
||||
if (usages) {
|
||||
debug("Class usages affection requested");
|
||||
|
||||
final ClassRepr classRepr = reprByName(className);
|
||||
|
||||
if (classRepr != null) {
|
||||
debug("Added class usage for ", classRepr.name);
|
||||
affectedUsages.add(classRepr.createUsage());
|
||||
}
|
||||
}
|
||||
@@ -579,6 +595,7 @@ public class Mappings {
|
||||
dependents.addAll(deps);
|
||||
}
|
||||
|
||||
debug("Affect field usage referenced of class ", p);
|
||||
affectedUsages
|
||||
.add(rootUsage instanceof UsageRepr.FieldAssignUsage ? field.createAssignUsage(myContext, p) : field.createUsage(myContext, p));
|
||||
}
|
||||
@@ -598,6 +615,8 @@ public class Mappings {
|
||||
dependents.addAll(deps);
|
||||
}
|
||||
|
||||
debug("Affect method usage referenced of class ", p);
|
||||
|
||||
affectedUsages
|
||||
.add(rootUsage instanceof UsageRepr.MetaMethodUsage ? method.createMetaUsage(myContext, p) : method.createUsage(myContext, p));
|
||||
}
|
||||
@@ -730,32 +749,38 @@ public class Mappings {
|
||||
|
||||
// Public branch --- hopeless
|
||||
if ((member.access & Opcodes.ACC_PUBLIC) > 0) {
|
||||
debug("Switched to non-incremental mode");
|
||||
debug("Public access, switching to a non-incremental mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Protected branch
|
||||
if ((member.access & Opcodes.ACC_PROTECTED) > 0) {
|
||||
debug("Softening non-incremental decision: adding all relevant subclasses for a recompilation");
|
||||
debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
|
||||
debug("Root class: ", owner);
|
||||
|
||||
final Collection<DependencyContext.S> propagated = self.propagateFieldAccess(isField ? member.name : myContext.get(""), owner);
|
||||
|
||||
for (DependencyContext.S className : propagated) {
|
||||
affectedFiles.add(new File(myContext.getValue(myClassToSourceFile.get(className))));
|
||||
final String fileName = myContext.getValue(myClassToSourceFile.get(className));
|
||||
debug("Adding ", fileName);
|
||||
affectedFiles.add(new File(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
debug("Softening non-incremental decision: adding all package classes for a recompilation");
|
||||
|
||||
final String packageName = ClassRepr.getPackageName(myContext.getValue(isField ? owner : member.name));
|
||||
|
||||
debug("Softening non-incremental decision: adding all package classes for a recompilation");
|
||||
debug("Package name: ", packageName);
|
||||
|
||||
// Package-local branch
|
||||
for (Map.Entry<DependencyContext.S, DependencyContext.S> e : myClassToSourceFile.entrySet()) {
|
||||
final DependencyContext.S className = e.getKey();
|
||||
final DependencyContext.S fileName = e.getValue();
|
||||
|
||||
if (ClassRepr.getPackageName(myContext.getValue(className)).equals(packageName)) {
|
||||
affectedFiles.add(new File(myContext.getValue(fileName)));
|
||||
final String f = myContext.getValue(fileName);
|
||||
debug("Adding: ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,6 +792,8 @@ public class Mappings {
|
||||
final Collection<File> filesToCompile,
|
||||
final Collection<File> compiledFiles,
|
||||
final Collection<File> affectedFiles) {
|
||||
debug("Begin of Differentiate:");
|
||||
|
||||
delta.compensateRemovedContent(filesToCompile);
|
||||
|
||||
final Util u = new Util(delta);
|
||||
@@ -798,14 +825,12 @@ public class Mappings {
|
||||
|
||||
final Difference.Specifier<ClassRepr> classDiff = Difference.make(pastClasses, classes);
|
||||
|
||||
debug("Processing changed classes");
|
||||
|
||||
debug("Processing changed classes:");
|
||||
for (Pair<ClassRepr, Difference> changed : classDiff.changed()) {
|
||||
final ClassRepr it = changed.first;
|
||||
final ClassRepr.Diff diff = (ClassRepr.Diff)changed.second;
|
||||
|
||||
debug("Changed: ");
|
||||
debug(it.name);
|
||||
debug("Changed: ", it.name);
|
||||
|
||||
final int addedModifiers = diff.addedModifiers();
|
||||
final int removedModifiers = diff.removedModifiers();
|
||||
@@ -815,24 +840,34 @@ public class Mappings {
|
||||
final boolean signatureChanged = (diff.base() & Difference.SIGNATURE) > 0;
|
||||
|
||||
if (superClassChanged || interfacesChanged || signatureChanged) {
|
||||
debug("Superclass changed: ", superClassChanged);
|
||||
debug("Interfaces changed: ", interfacesChanged);
|
||||
debug("Signature changed ", signatureChanged);
|
||||
|
||||
final boolean extendsChanged = superClassChanged && !diff.extendsAdded();
|
||||
final boolean interfacesRemoved = interfacesChanged && !diff.interfaces().removed().isEmpty();
|
||||
|
||||
debug("Extends changed: ", extendsChanged);
|
||||
debug("Interfaces removed: ", interfacesRemoved);
|
||||
|
||||
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, extendsChanged || interfacesRemoved || signatureChanged);
|
||||
}
|
||||
|
||||
if ((diff.addedModifiers() & Opcodes.ACC_INTERFACE) > 0 || (diff.removedModifiers() & Opcodes.ACC_INTERFACE) > 0) {
|
||||
debug("Class-to-interface or interface-to-class conversion detected, added class usage to affected usages");
|
||||
affectedUsages.add(it.createUsage());
|
||||
}
|
||||
|
||||
if (it.isAnnotation() && it.policy == RetentionPolicy.SOURCE) {
|
||||
debug("Annotation, retention policy = SOURCE => a switch to non-incremental mode requested");
|
||||
if (!incrementalDecision(it.outerClassName, it, affectedFiles)) {
|
||||
debug("End of Differentiate, returning false");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((addedModifiers & Opcodes.ACC_PROTECTED) > 0) {
|
||||
debug("Introduction of 'protected' modifier detected, adding class usage + inheritance constraint to affected usages");
|
||||
final UsageRepr.Usage usage = it.createUsage();
|
||||
|
||||
affectedUsages.add(usage);
|
||||
@@ -840,6 +875,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if (diff.packageLocalOn()) {
|
||||
debug("Introduction of 'package local' access detected, adding class usage + package constraint to affected usages");
|
||||
final UsageRepr.Usage usage = it.createUsage();
|
||||
|
||||
affectedUsages.add(usage);
|
||||
@@ -847,54 +883,64 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if ((addedModifiers & Opcodes.ACC_FINAL) > 0 || (addedModifiers & Opcodes.ACC_PRIVATE) > 0) {
|
||||
debug("Introduction of 'private' or 'final' modifier(s) detected, adding class usage to affected usages");
|
||||
affectedUsages.add(it.createUsage());
|
||||
}
|
||||
|
||||
if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0) {
|
||||
affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
|
||||
}
|
||||
|
||||
if ((addedModifiers & Opcodes.ACC_STATIC) > 0 ||
|
||||
(removedModifiers & Opcodes.ACC_STATIC) > 0 ||
|
||||
(addedModifiers & Opcodes.ACC_ABSTRACT) > 0) {
|
||||
if ((addedModifiers & Opcodes.ACC_ABSTRACT) > 0 || (addedModifiers & Opcodes.ACC_STATIC) > 0) {
|
||||
debug("Introduction of 'abstract' or 'static' modifier(s) detected, adding class new usage to affected usages");
|
||||
affectedUsages.add(UsageRepr.createClassNewUsage(myContext, it.name));
|
||||
}
|
||||
|
||||
if (it.isAnnotation()) {
|
||||
debug("Class is annotation, performing annotation-specific analysis");
|
||||
|
||||
if (diff.retentionChanged()) {
|
||||
debug("Retention policy change detected, adding class usage to affected usages");
|
||||
affectedUsages.add(it.createUsage());
|
||||
}
|
||||
else {
|
||||
final Collection<ElementType> removedtargets = diff.targets().removed();
|
||||
|
||||
if (removedtargets.contains(ElementType.LOCAL_VARIABLE)) {
|
||||
debug("Annotation, removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
|
||||
debug("Removed target contains LOCAL_VARIABLE => a switch to non-incremental mode requested");
|
||||
if (!incrementalDecision(it.outerClassName, it, affectedFiles)) {
|
||||
debug("End of Differentiate, returning false");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!removedtargets.isEmpty()) {
|
||||
debug("Removed some annotation targets, adding annotation query");
|
||||
annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
|
||||
.createAnnotationUsage(myContext, TypeRepr.createClassType(myContext, it.name), null, removedtargets));
|
||||
}
|
||||
|
||||
for (MethodRepr m : diff.methods().added()) {
|
||||
if (!m.hasValue()) {
|
||||
debug("Added method with no default value: ", m.name);
|
||||
debug("Adding class usage to affected usages");
|
||||
affectedUsages.add(it.createUsage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug("End of annotation-specific analysis");
|
||||
}
|
||||
|
||||
debug("Processing added methods: ");
|
||||
for (MethodRepr m : diff.methods().added()) {
|
||||
debug("Method: ", m.name);
|
||||
|
||||
if (it.isAnnotation()) {
|
||||
debug("Class is annotation, skipping method analysis");
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
|
||||
(it.access & Opcodes.ACC_ABSTRACT) > 0 ||
|
||||
(m.access & Opcodes.ACC_ABSTRACT) > 0) {
|
||||
debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
|
||||
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
|
||||
}
|
||||
|
||||
@@ -908,6 +954,7 @@ public class Mappings {
|
||||
}
|
||||
else {
|
||||
propagated = u.propagateMethodAccess(m.name, it.name);
|
||||
debug("Conservative case on overriding methods, affecting method usages");
|
||||
u.affectMethodUsages(m, propagated, m.createMetaUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
}
|
||||
@@ -924,10 +971,12 @@ public class Mappings {
|
||||
|
||||
for (MethodRepr mm : lessSpecific) {
|
||||
if (!mm.equals(m)) {
|
||||
debug("Found less specific method, affecting method usages");
|
||||
u.affectMethodUsages(mm, propagated, mm.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
}
|
||||
|
||||
debug("Processing affected by specificity methods");
|
||||
for (Pair<MethodRepr, ClassRepr> p : affectedMethods) {
|
||||
final MethodRepr mm = p.first;
|
||||
final ClassRepr cc = p.second;
|
||||
@@ -936,7 +985,12 @@ public class Mappings {
|
||||
|
||||
}
|
||||
else {
|
||||
debug("Method: ", mm.name);
|
||||
debug("Class : ", cc.name);
|
||||
|
||||
if (overrides.satisfy(mm)) {
|
||||
debug("Current method overrides that found");
|
||||
|
||||
final Option<Boolean> subtypeOf = u.isSubtypeOf(mm.type, m.type);
|
||||
|
||||
if (weakerAccess(mm.access, m.access) ||
|
||||
@@ -949,11 +1003,15 @@ public class Mappings {
|
||||
final DependencyContext.S file = myClassToSourceFile.get(cc.name);
|
||||
|
||||
if (file != null) {
|
||||
affectedFiles.add(new File(myContext.getValue(file)));
|
||||
final String f = myContext.getValue(file);
|
||||
debug("Complex condition is satisfied, affecting file ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Current method does not override that found");
|
||||
|
||||
final Collection<DependencyContext.S> yetPropagated = self.propagateMethodAccess(mm.name, cc.name);
|
||||
final Collection<DependencyContext.S> deps = myClassToClassDependency.get(cc.name);
|
||||
|
||||
@@ -961,6 +1019,7 @@ public class Mappings {
|
||||
dependants.addAll(deps);
|
||||
}
|
||||
|
||||
debug("Affecting method usages for that found");
|
||||
u.affectMethodUsages(mm, yetPropagated, mm.createUsage(myContext, cc.name), affectedUsages, dependants);
|
||||
}
|
||||
}
|
||||
@@ -977,19 +1036,26 @@ public class Mappings {
|
||||
final DependencyContext.S outerClass = r.outerClassName;
|
||||
|
||||
if (u.methodVisible(outerClass, m)) {
|
||||
affectedFiles.add(new File(myContext.getValue(sourceFileName)));
|
||||
final String f = myContext.getValue(sourceFileName);
|
||||
debug("Affecting file due to local overriding: ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of added methods processing");
|
||||
|
||||
debug("Processing removed methods:");
|
||||
for (MethodRepr m : diff.methods().removed()) {
|
||||
debug("Method ", m.name);
|
||||
|
||||
final Collection<Pair<MethodRepr, ClassRepr>> overridenMethods = u.findOverridenMethods(m, it);
|
||||
final Collection<DependencyContext.S> propagated = u.propagateMethodAccess(m.name, it.name);
|
||||
|
||||
if (overridenMethods.size() == 0) {
|
||||
debug("No overridden methods found, affecting method usages");
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
else {
|
||||
@@ -1006,6 +1072,7 @@ public class Mappings {
|
||||
}
|
||||
|
||||
if (!clear) {
|
||||
debug("No clearly overridden methods found, affecting method usages");
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
}
|
||||
@@ -1046,21 +1113,31 @@ public class Mappings {
|
||||
final DependencyContext.S source = myClassToSourceFile.get(p);
|
||||
|
||||
if (source != null) {
|
||||
affectedFiles.add(new File(myContext.getValue(source)));
|
||||
final String f = myContext.getValue(source);
|
||||
debug(
|
||||
"Removed method is not abstract & is overrides some abstract method which is not then over-overriden in subclass ",
|
||||
p);
|
||||
debug("Affecting subclass source file ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of removed methods processing");
|
||||
|
||||
debug("Processing changed methods:");
|
||||
for (Pair<MethodRepr, Difference> mr : diff.methods().changed()) {
|
||||
final MethodRepr m = mr.first;
|
||||
final MethodRepr.Diff d = (MethodRepr.Diff)mr.second;
|
||||
final boolean throwsChanged = (d.exceptions().added().size() > 0) || (d.exceptions().changed().size() > 0);
|
||||
|
||||
debug("Method: ", m.name);
|
||||
|
||||
if (it.isAnnotation()) {
|
||||
if (d.defaultRemoved()) {
|
||||
debug("Class is annotation, default value is removed => adding annotation query");
|
||||
final List<DependencyContext.S> l = new LinkedList<DependencyContext.S>();
|
||||
l.add(m.name);
|
||||
annotationQuery.add((UsageRepr.AnnotationUsage)UsageRepr
|
||||
@@ -1076,6 +1153,7 @@ public class Mappings {
|
||||
final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();
|
||||
|
||||
if (d.packageLocalOn()) {
|
||||
debug("Method became package-local, affecting method usages outside the package");
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
|
||||
|
||||
for (UsageRepr.Usage usage : usages) {
|
||||
@@ -1089,6 +1167,7 @@ public class Mappings {
|
||||
|
||||
if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0 || throwsChanged) {
|
||||
if (!affected) {
|
||||
debug("Return type, throws list or signature changed --- affecting method usages");
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
|
||||
affectedUsages.addAll(usages);
|
||||
}
|
||||
@@ -1098,11 +1177,13 @@ public class Mappings {
|
||||
(d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
|
||||
(d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0) {
|
||||
if (!affected) {
|
||||
debug("Added static or private specifier or removed static specifier --- affecting method usages");
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
|
||||
affectedUsages.addAll(usages);
|
||||
}
|
||||
|
||||
if ((d.addedModifiers() & Opcodes.ACC_STATIC) > 0) {
|
||||
debug("Added static specifier --- affecting subclasses");
|
||||
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
|
||||
}
|
||||
}
|
||||
@@ -1110,11 +1191,13 @@ public class Mappings {
|
||||
if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0 ||
|
||||
(d.addedModifiers() & Opcodes.ACC_PUBLIC) > 0 ||
|
||||
(d.addedModifiers() & Opcodes.ACC_ABSTRACT) > 0) {
|
||||
debug("Added final, public or abstract specifier --- affecting subclasses");
|
||||
u.affectSubclasses(it.name, affectedFiles, affectedUsages, dependants, false);
|
||||
}
|
||||
|
||||
if ((d.addedModifiers() & Opcodes.ACC_PROTECTED) > 0 && !((d.removedModifiers() & Opcodes.ACC_PRIVATE) > 0)) {
|
||||
if (!constrained) {
|
||||
debug("Added public or package-local method became protected --- affect method usages with protected constraint");
|
||||
if (!affected) {
|
||||
u.affectMethodUsages(m, propagated, m.createUsage(myContext, it.name), usages, dependants);
|
||||
affectedUsages.addAll(usages);
|
||||
@@ -1129,10 +1212,14 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of changed methods processing");
|
||||
|
||||
final int mask = Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
|
||||
|
||||
debug("Processing added fields");
|
||||
for (FieldRepr f : diff.fields().added()) {
|
||||
debug("Field: ", f.name);
|
||||
|
||||
final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
|
||||
final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
|
||||
final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
|
||||
@@ -1141,32 +1228,34 @@ public class Mappings {
|
||||
if (!fPrivate) {
|
||||
final Collection<DependencyContext.S> subClasses = getAllSubclasses(it.name);
|
||||
|
||||
if (subClasses != null) {
|
||||
for (final DependencyContext.S subClass : subClasses) {
|
||||
final ClassRepr r = u.reprByName(subClass);
|
||||
final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass);
|
||||
for (final DependencyContext.S subClass : subClasses) {
|
||||
final ClassRepr r = u.reprByName(subClass);
|
||||
final DependencyContext.S sourceFileName = myClassToSourceFile.get(subClass);
|
||||
|
||||
if (r != null && sourceFileName != null) {
|
||||
if (r.isLocal) {
|
||||
if (r != null && sourceFileName != null) {
|
||||
if (r.isLocal) {
|
||||
debug("Affecting local subclass (introduced field can potentially hide surrounding method parameters/local variables): ",
|
||||
sourceFileName);
|
||||
affectedFiles.add(new File(myContext.getValue(sourceFileName)));
|
||||
}
|
||||
else {
|
||||
final DependencyContext.S outerClass = r.outerClassName;
|
||||
|
||||
if (!empty(outerClass) && u.fieldVisible(outerClass, f)) {
|
||||
debug("Affecting inner subclass (introduced field can potentially hide surrounding class fields): ", sourceFileName);
|
||||
affectedFiles.add(new File(myContext.getValue(sourceFileName)));
|
||||
}
|
||||
else {
|
||||
final DependencyContext.S outerClass = r.outerClassName;
|
||||
|
||||
if (!empty(outerClass) && u.fieldVisible(outerClass, f)) {
|
||||
affectedFiles.add(new File(myContext.getValue(sourceFileName)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Collection<DependencyContext.S> propagated = u.propagateFieldAccess(f.name, subClass);
|
||||
u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants);
|
||||
debug("Affecting field usages referenced from subclass ", subClass);
|
||||
final Collection<DependencyContext.S> propagated = u.propagateFieldAccess(f.name, subClass);
|
||||
u.affectFieldUsages(f, propagated, f.createUsage(myContext, subClass), affectedUsages, dependants);
|
||||
|
||||
final Collection<DependencyContext.S> deps = myClassToClassDependency.get(subClass);
|
||||
final Collection<DependencyContext.S> deps = myClassToClassDependency.get(subClass);
|
||||
|
||||
if (deps != null) {
|
||||
dependants.addAll(deps);
|
||||
}
|
||||
if (deps != null) {
|
||||
dependants.addAll(deps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1186,6 +1275,7 @@ public class Mappings {
|
||||
final Collection<DependencyContext.S> propagated = o.propagateFieldAccess(ff.name, cc.name);
|
||||
final Set<UsageRepr.Usage> localUsages = new HashSet<UsageRepr.Usage>();
|
||||
|
||||
debug("Affecting usages of overridden field in class ", cc.name);
|
||||
u.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, dependants);
|
||||
|
||||
if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
|
||||
@@ -1214,16 +1304,16 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of added fields processing");
|
||||
|
||||
debug("Processing removed fields");
|
||||
|
||||
debug("Processing removed fields:");
|
||||
for (FieldRepr f : diff.fields().removed()) {
|
||||
debug("Field ");
|
||||
debug(f.name);
|
||||
debug("Field: ", it.name);
|
||||
|
||||
if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & mask) == mask && f.hasValue()) {
|
||||
debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
|
||||
if (!incrementalDecision(it.name, f, affectedFiles)) {
|
||||
debug("End of Differentiate, returning false");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1231,20 +1321,20 @@ public class Mappings {
|
||||
final Collection<DependencyContext.S> propagated = u.propagateFieldAccess(f.name, it.name);
|
||||
u.affectFieldUsages(f, propagated, f.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
debug("End of removed fields processing");
|
||||
|
||||
debug("Processing changed fields");
|
||||
|
||||
debug("Processing changed fields:");
|
||||
for (Pair<FieldRepr, Difference> f : diff.fields().changed()) {
|
||||
final Difference d = f.second;
|
||||
final FieldRepr field = f.first;
|
||||
|
||||
debug("Field ");
|
||||
debug(field.name);
|
||||
debug("Field: ", it.name);
|
||||
|
||||
if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & mask) == mask) {
|
||||
if ((d.base() & Difference.ACCESS) > 0 || (d.base() & Difference.VALUE) > 0) {
|
||||
debug("Inline field changed it's access or value => a switch to non-incremental mode requested");
|
||||
if (!incrementalDecision(it.name, field, affectedFiles)){
|
||||
if (!incrementalDecision(it.name, field, affectedFiles)) {
|
||||
debug("End of Differentiate, returning false");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1254,6 +1344,7 @@ public class Mappings {
|
||||
final Collection<DependencyContext.S> propagated = u.propagateFieldAccess(field.name, it.name);
|
||||
|
||||
if ((d.base() & Difference.TYPE) > 0 || (d.base() & Difference.SIGNATURE) > 0) {
|
||||
debug("Type or signature changed --- affecting field usages");
|
||||
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
else if ((d.base() & Difference.ACCESS) > 0) {
|
||||
@@ -1261,7 +1352,7 @@ public class Mappings {
|
||||
(d.removedModifiers() & Opcodes.ACC_STATIC) > 0 ||
|
||||
(d.addedModifiers() & Opcodes.ACC_PRIVATE) > 0 ||
|
||||
(d.addedModifiers() & Opcodes.ACC_VOLATILE) > 0) {
|
||||
|
||||
debug("Added/removed static modifier or added private/volatile modifier --- affecting field usages");
|
||||
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), affectedUsages, dependants);
|
||||
}
|
||||
else {
|
||||
@@ -1269,12 +1360,14 @@ public class Mappings {
|
||||
final Set<UsageRepr.Usage> usages = new HashSet<UsageRepr.Usage>();
|
||||
|
||||
if ((d.addedModifiers() & Opcodes.ACC_FINAL) > 0) {
|
||||
debug("Added final modifier --- affecting field assign usages");
|
||||
u.affectFieldUsages(field, propagated, field.createAssignUsage(myContext, it.name), usages, dependants);
|
||||
affectedUsages.addAll(usages);
|
||||
affected = true;
|
||||
}
|
||||
|
||||
if ((d.removedModifiers() & Opcodes.ACC_PUBLIC) > 0) {
|
||||
debug("Removed public modifier, affecting field usages with appropriate constraint");
|
||||
if (!affected) {
|
||||
u.affectFieldUsages(field, propagated, field.createUsage(myContext, it.name), usages, dependants);
|
||||
affectedUsages.addAll(usages);
|
||||
@@ -1293,12 +1386,18 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of changed fields processing");
|
||||
}
|
||||
debug("End of changed classes processing");
|
||||
|
||||
debug("Processing removed classes:");
|
||||
for (ClassRepr c : classDiff.removed()) {
|
||||
debug("Adding usages of class ", c.name);
|
||||
affectedUsages.add(c.createUsage());
|
||||
}
|
||||
debug("End of removed classes processing.");
|
||||
|
||||
debug("Processing added classes:");
|
||||
for (ClassRepr c : classDiff.added()) {
|
||||
final Collection<DependencyContext.S> depClasses = myClassToClassDependency.get(c.name);
|
||||
|
||||
@@ -1307,12 +1406,16 @@ public class Mappings {
|
||||
final DependencyContext.S fName = myClassToSourceFile.get(depClass);
|
||||
|
||||
if (fName != null) {
|
||||
affectedFiles.add(new File(myContext.getValue(fName)));
|
||||
final String f = myContext.getValue(fName);
|
||||
debug("Adding dependent file ", f);
|
||||
affectedFiles.add(new File(f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
debug("End of added classes processing.");
|
||||
|
||||
debug("Checking dependent files:");
|
||||
if (dependants != null) {
|
||||
final Set<DependencyContext.S> dependentFiles = new HashSet<DependencyContext.S>();
|
||||
|
||||
@@ -1332,6 +1435,8 @@ public class Mappings {
|
||||
continue filewise;
|
||||
}
|
||||
|
||||
debug("Dependent file: ", depFile);
|
||||
|
||||
final Collection<UsageRepr.Cluster> depClusters = mySourceFileToUsages.get(depFile);
|
||||
|
||||
for (UsageRepr.Cluster depCluster : depClusters) {
|
||||
@@ -1347,6 +1452,7 @@ public class Mappings {
|
||||
final Util.UsageConstraint constraint = usageConstraints.get(usage);
|
||||
|
||||
if (constraint == null) {
|
||||
debug("Added file with no constraints");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
@@ -1354,6 +1460,7 @@ public class Mappings {
|
||||
final Set<DependencyContext.S> residenceClasses = depCluster.getResidence(usage);
|
||||
for (DependencyContext.S residentName : residenceClasses) {
|
||||
if (constraint.checkResidence(residentName)) {
|
||||
debug("Added file with satisfied constraint");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
@@ -1369,6 +1476,7 @@ public class Mappings {
|
||||
for (UsageRepr.Usage usage : annotationUsages) {
|
||||
for (UsageRepr.AnnotationUsage query : annotationQuery) {
|
||||
if (query.satisfies(usage)) {
|
||||
debug("Added file due to annotation query");
|
||||
affectedFiles.add(theFile);
|
||||
continue filewise;
|
||||
}
|
||||
@@ -1381,6 +1489,13 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
if (removed != null) {
|
||||
for (String r : removed) {
|
||||
affectedFiles.remove(new File(r));
|
||||
}
|
||||
}
|
||||
|
||||
debug("End of Differentiate, returning true");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1425,7 +1540,6 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
myClassToSubclasses.putAll(delta.myClassToSubclasses);
|
||||
mySourceFileToClasses.putAll(delta.mySourceFileToClasses);
|
||||
mySourceFileToUsages.putAll(delta.mySourceFileToUsages);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -44,5 +44,5 @@ xmlrpc-2.0.jar
|
||||
xpp3-1.1.4-min.jar
|
||||
xstream.jar
|
||||
swingx-core-1.6.2.jar
|
||||
netty-3.2.5.Final.jar
|
||||
netty-3.3.0.Final.jar
|
||||
protobuf-2.3.0.jar
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -17,7 +17,6 @@
|
||||
package com.intellij.execution.ui.actions;
|
||||
|
||||
import com.intellij.execution.ui.layout.Grid;
|
||||
import com.intellij.execution.ui.layout.GridCell;
|
||||
import com.intellij.execution.ui.layout.Tab;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
@@ -74,11 +73,6 @@ public abstract class BaseViewAction extends DumbAwareAction {
|
||||
return e.getData(ViewContext.CONTENT_KEY);
|
||||
}
|
||||
|
||||
protected static boolean isDetached(ViewContext context, Content content) {
|
||||
final GridCell cell = context.findCellFor(content);
|
||||
return cell != null && cell.isDetached();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static Tab getTabFor(final ViewContext context, final Content[] content) {
|
||||
Grid grid = context.findGridFor(content[0]);
|
||||
|
||||
@@ -72,12 +72,6 @@ public interface CellTransform {
|
||||
|
||||
interface Facade {
|
||||
void minimize(Content content, Restore restore);
|
||||
|
||||
void moveToTab(final Content content);
|
||||
|
||||
void moveToGrid(final Content content);
|
||||
|
||||
Restore detach(final Content[] content);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,10 @@
|
||||
|
||||
package com.intellij.execution.ui.layout;
|
||||
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
public interface GridCell {
|
||||
boolean isDetached();
|
||||
|
||||
int getContentCount();
|
||||
|
||||
void attach();
|
||||
|
||||
void minimize(final Content content);
|
||||
|
||||
ActionCallback detach();
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public interface Tab {
|
||||
void setDetached(final PlaceInGrid placeInGrid, final boolean detached);
|
||||
|
||||
int getIndex();
|
||||
int getDefaultIndex();
|
||||
|
||||
boolean isDetached(final PlaceInGrid placeInGrid);
|
||||
}
|
||||
@@ -32,4 +32,8 @@ public interface View {
|
||||
void assignTab(Tab tab);
|
||||
|
||||
void setTabIndex(int tabIndex);
|
||||
|
||||
int getWindow();
|
||||
|
||||
void setWindow(int windowNumber);
|
||||
}
|
||||
@@ -51,29 +51,29 @@ public class DefaultWordsScanner implements WordsScanner {
|
||||
|
||||
public void processWords(CharSequence fileText, Processor<WordOccurrence> processor) {
|
||||
myLexer.start(fileText);
|
||||
WordOccurrence occurence = null; // shared occurence
|
||||
WordOccurrence occurrence = null; // shared occurrence
|
||||
|
||||
while (myLexer.getTokenType() != null) {
|
||||
final IElementType type = myLexer.getTokenType();
|
||||
if (myIdentifierTokenSet.contains(type)) {
|
||||
if (occurence == null) {
|
||||
occurence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
|
||||
if (occurrence == null) {
|
||||
occurrence = new WordOccurrence(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
|
||||
}
|
||||
else {
|
||||
occurence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
|
||||
occurrence.init(fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE);
|
||||
}
|
||||
if (!processor.process(occurence)) return;
|
||||
if (!processor.process(occurrence)) return;
|
||||
}
|
||||
else if (myCommentTokenSet.contains(type)) {
|
||||
if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurence, false)) return;
|
||||
if (!stripWords(processor, fileText,myLexer.getTokenStart(),myLexer.getTokenEnd(), WordOccurrence.Kind.COMMENTS,occurrence, false)) return;
|
||||
}
|
||||
else if (myLiteralTokenSet.contains(type)) {
|
||||
if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurence, myMayHaveFileRefsInLiterals)) return;
|
||||
if (!stripWords(processor, fileText, myLexer.getTokenStart(),myLexer.getTokenEnd(),WordOccurrence.Kind.LITERALS,occurrence, myMayHaveFileRefsInLiterals)) return;
|
||||
}
|
||||
else {
|
||||
// process all word-like characters as words
|
||||
// Plugin writers may have (Maximka in JavaScript especially) some keyword token types omitted from the identifierTokenSet
|
||||
if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurence, false)) return;
|
||||
if (!stripWords(processor, fileText, myLexer.getTokenStart(), myLexer.getTokenEnd(), WordOccurrence.Kind.CODE, occurrence, false)) return;
|
||||
}
|
||||
myLexer.advance();
|
||||
}
|
||||
|
||||
+7
-3
@@ -268,10 +268,14 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr
|
||||
myScrollPane.setViewportBorder(JBScrollPane.createIndentBorder());
|
||||
|
||||
final DefaultActionGroup actions = new DefaultActionGroup();
|
||||
actions.add(new BackAction());
|
||||
actions.add(new ForwardAction());
|
||||
final BackAction back = new BackAction();
|
||||
final ForwardAction forward = new ForwardAction();
|
||||
actions.add(back);
|
||||
actions.add(forward);
|
||||
actions.add(myExternalDocAction = new ExternalDocAction());
|
||||
|
||||
back.registerCustomShortcutSet(CustomShortcutSet.fromString("LEFT"), this);
|
||||
forward.registerCustomShortcutSet(CustomShortcutSet.fromString("RIGHT"), this);
|
||||
myExternalDocAction.registerCustomShortcutSet(CustomShortcutSet.fromString("UP"), this);
|
||||
if (additionalActions != null) {
|
||||
for (final AnAction action : additionalActions) {
|
||||
actions.add(action);
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -76,7 +77,7 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
|
||||
|
||||
public RunContentManager getContentManager() {
|
||||
if (myContentManager == null) {
|
||||
myContentManager = new RunContentManagerImpl(myProject);
|
||||
myContentManager = new RunContentManagerImpl(myProject, DockManager.getInstance(myProject));
|
||||
Disposer.register(myProject, myContentManager);
|
||||
}
|
||||
return myContentManager;
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.runners.GenericProgramRunner;
|
||||
import com.intellij.execution.ui.layout.impl.DockableGridContainerFactory;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.impl.ContentManagerWatcher;
|
||||
import com.intellij.openapi.Disposable;
|
||||
@@ -47,6 +48,7 @@ import com.intellij.openapi.wm.ToolWindowManager;
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerAdapter;
|
||||
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
|
||||
import com.intellij.ui.content.*;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -65,13 +67,17 @@ public class RunContentManagerImpl implements RunContentManager, Disposable {
|
||||
private static final Key<RunContentDescriptor> DESCRIPTOR_KEY = new Key<RunContentDescriptor>("Descriptor");
|
||||
|
||||
private final Project myProject;
|
||||
private DockableGridContainerFactory myContentFactory;
|
||||
private final Map<String, ContentManager> myToolwindowIdToContentManagerMap = new HashMap<String, ContentManager>();
|
||||
|
||||
private final Map<RunContentListener, Disposable> myListeners = new HashMap<RunContentListener, Disposable>();
|
||||
private final LinkedList<String> myToolwindowIdZbuffer = new LinkedList<String>();
|
||||
|
||||
public RunContentManagerImpl(Project project) {
|
||||
public RunContentManagerImpl(Project project, DockManager dockManager) {
|
||||
myProject = project;
|
||||
myContentFactory = new DockableGridContainerFactory();
|
||||
dockManager.register(DockableGridContainerFactory.TYPE, myContentFactory);
|
||||
Disposer.register(myProject, myContentFactory);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.actions;
|
||||
|
||||
import com.intellij.execution.ui.actions.BaseViewAction;
|
||||
import com.intellij.execution.ui.layout.Grid;
|
||||
import com.intellij.execution.ui.layout.GridCell;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
public class AttachCellAction extends BaseViewAction {
|
||||
|
||||
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
if (content.length == 0 || !isDetached(context, content[0])) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Grid grid = context.findGridFor(content[0]);
|
||||
|
||||
GridCell cell = grid.getCellFor(content[0]);
|
||||
if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) {
|
||||
setEnabled(e, cell.getContentCount() == 1);
|
||||
} else {
|
||||
setEnabled(e, true);
|
||||
if (cell.getContentCount() > 1) {
|
||||
e.getPresentation().setText(ActionsBundle.message("action.Runner.AttachCells.text", cell.getContentCount()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
context.findCellFor(content[0]).attach();
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,19 @@ package com.intellij.execution.ui.layout.actions;
|
||||
import com.intellij.execution.ui.actions.BaseViewAction;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class CloseViewAction extends BaseViewAction {
|
||||
private static final Icon ICON = IconLoader.getIcon("/actions/closeNew.png");
|
||||
private static final Icon HOVERED_ICON = IconLoader.getIcon("/actions/closeNewHovered.png");
|
||||
|
||||
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
setEnabled(e, isEnabled(context, content, e.getPlace()));
|
||||
e.getPresentation().setIcon(ICON);
|
||||
e.getPresentation().setHoveredIcon(HOVERED_ICON);
|
||||
}
|
||||
|
||||
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.actions;
|
||||
|
||||
import com.intellij.execution.ui.actions.BaseViewAction;
|
||||
import com.intellij.execution.ui.layout.Grid;
|
||||
import com.intellij.execution.ui.layout.GridCell;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.idea.ActionsBundle;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
public class DetachCellAction extends BaseViewAction {
|
||||
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
if (content.length == 0 || isDetached(context, content[0])) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Grid grid = context.findGridFor(content[0]);
|
||||
if (grid == null) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace()) || (ViewContext.TAB_POPUP_PLACE.equals(e.getPlace()))) {
|
||||
setEnabled(e, grid.getContents().size() == 1);
|
||||
}
|
||||
else {
|
||||
GridCell cell = grid.getCellFor(content[0]);
|
||||
if (ViewContext.CELL_TOOLBAR_PLACE.equals(e.getPlace()) && content.length == 1) {
|
||||
setEnabled(e, cell.getContentCount() == 1);
|
||||
} else {
|
||||
setEnabled(e, true);
|
||||
if (cell.getContentCount() > 1) {
|
||||
e.getPresentation().setText(ActionsBundle.message("action.Runner.DetachCells.text", cell.getContentCount()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
context.findCellFor(content[0]).detach();
|
||||
}
|
||||
}
|
||||
+4
-8
@@ -39,19 +39,15 @@ public class MinimizeViewAction extends BaseViewAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isDetached(context, content[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ViewContext.TAB_TOOLBAR_PLACE.equals(place) || ViewContext.TAB_POPUP_PLACE.equals(place)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
Tab tab = getTabFor(context, content);
|
||||
if (tab == null) {
|
||||
return false;
|
||||
}
|
||||
return tab.isDefault();
|
||||
return !tab.isDefault();
|
||||
}
|
||||
else {
|
||||
return getTabFor(context, content) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.actions;
|
||||
|
||||
import com.intellij.execution.ui.actions.BaseViewAction;
|
||||
import com.intellij.execution.ui.layout.Grid;
|
||||
import com.intellij.execution.ui.layout.Tab;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
public class MoveToGridAction extends BaseViewAction {
|
||||
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
if (!context.isMoveToGridActionEnabled() || content.length != 1) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDetached(context, content[0])) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Grid grid = context.findGridFor(content[0]);
|
||||
if (grid == null) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
Tab tab = context.getTabFor(grid);
|
||||
setEnabled(e, tab != null && !tab.isDefault() && grid.getContents().size() == 1);
|
||||
}
|
||||
|
||||
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
context.getCellTransform().moveToGrid(content[0]);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.actions;
|
||||
|
||||
import com.intellij.execution.ui.actions.BaseViewAction;
|
||||
import com.intellij.execution.ui.layout.Grid;
|
||||
import com.intellij.execution.ui.layout.Tab;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.ui.content.Content;
|
||||
|
||||
public class MoveToTabAction extends BaseViewAction {
|
||||
protected void update(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
if (!context.isMoveToGridActionEnabled() || content.length != 1) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
if (isDetached(context, content[0])) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
Grid grid = context.findGridFor(content[0]);
|
||||
if (grid == null) {
|
||||
setEnabled(e, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Tab tab = context.getTabFor(grid);
|
||||
|
||||
if (ViewContext.TAB_TOOLBAR_PLACE.equals(e.getPlace())) {
|
||||
setEnabled(e, false);
|
||||
} else {
|
||||
setEnabled(e, tab != null && tab.isDefault());
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(final AnActionEvent e, final ViewContext context, final Content[] content) {
|
||||
context.getCellTransform().moveToTab(content[0]);
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import javax.swing.*;
|
||||
abstract class AbstractTab {
|
||||
|
||||
int myIndex;
|
||||
int myDefaultIndex = -1;
|
||||
String myDisplayName;
|
||||
Icon myIcon;
|
||||
|
||||
@@ -38,6 +39,7 @@ abstract class AbstractTab {
|
||||
|
||||
void copyFrom(final AbstractTab from) {
|
||||
myIndex = from.myIndex;
|
||||
myDefaultIndex = from.myDefaultIndex;
|
||||
myDisplayName = from.myDisplayName;
|
||||
myIcon = from.myIcon;
|
||||
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.impl;
|
||||
|
||||
import com.intellij.ui.docking.DockContainer;
|
||||
import com.intellij.ui.docking.DockContainerFactory;
|
||||
import com.intellij.ui.docking.DockableContent;
|
||||
|
||||
/**
|
||||
* @author Dennis.Ushakov
|
||||
*/
|
||||
public class DockableGridContainerFactory implements DockContainerFactory {
|
||||
public static final String TYPE = "runner-grid";
|
||||
|
||||
@Override
|
||||
public DockContainer createContainer(DockableContent content) {
|
||||
final RunnerContentUi.DockableGrid dockableGrid = (RunnerContentUi.DockableGrid)content;
|
||||
return new RunnerContentUi(dockableGrid.getRunnerUi(), dockableGrid.getOriginalRunnerUi(), dockableGrid.getWindow());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {}
|
||||
}
|
||||
@@ -18,18 +18,16 @@ package com.intellij.execution.ui.layout.impl;
|
||||
|
||||
import com.intellij.execution.ui.layout.*;
|
||||
import com.intellij.execution.ui.layout.actions.MinimizeViewAction;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.ui.popup.ComponentPopupBuilder;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.DimensionService;
|
||||
import com.intellij.openapi.util.MutualMap;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.ui.content.Content;
|
||||
import com.intellij.ui.docking.DockContainer;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.ui.switcher.SwitchTarget;
|
||||
import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
@@ -43,15 +41,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class GridCellImpl implements GridCell, Disposable {
|
||||
|
||||
public class GridCellImpl implements GridCell {
|
||||
private final GridImpl myContainer;
|
||||
|
||||
private final MutualMap<Content, TabInfo> myContents = new MutualMap<Content, TabInfo>(true);
|
||||
@@ -62,16 +59,12 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
private final PlaceInGrid myPlaceInGrid;
|
||||
|
||||
private final ViewContextEx myContext;
|
||||
private CellTransform.Restore.List myRestoreFromDetach;
|
||||
private JBPopup myPopup;
|
||||
private boolean myDisposed;
|
||||
|
||||
public GridCellImpl(ViewContextEx context, @NotNull GridImpl container, GridImpl.Placeholder placeholder, PlaceInGrid placeInGrid) {
|
||||
myContext = context;
|
||||
myContainer = container;
|
||||
|
||||
Disposer.register(container, this);
|
||||
|
||||
myPlaceInGrid = placeInGrid;
|
||||
myPlaceholder = placeholder;
|
||||
myTabs = new JBTabsImpl(myContext.getProject(), myContext.getActionManager(), myContext.getFocusManager(), container).setDataProvider(new DataProvider() {
|
||||
@@ -97,23 +90,17 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
}
|
||||
}).setSideComponentVertical(!context.getLayoutSettings().isToolbarHorizontal())
|
||||
.setStealthTabMode(true)
|
||||
.setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false);
|
||||
.setFocusCycle(false).setPaintFocus(true).setProvideSwitchTargets(false).setTabDraggingEnabled(true);
|
||||
|
||||
myTabs.addTabMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(final MouseEvent e) {
|
||||
if (UIUtil.isCloseClick(e)) {
|
||||
if (isDetached()) {
|
||||
myPopup.cancel();
|
||||
myPopup = null;
|
||||
}
|
||||
else {
|
||||
minimize(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
rebuildPopupGroup();
|
||||
myTabs.addListener(new TabsListener() {
|
||||
myTabs.addListener(new TabsListener.Adapter() {
|
||||
|
||||
public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) {
|
||||
if (oldSelection != null && myContext.isStateBeingRestored()) {
|
||||
@@ -181,7 +168,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (myPlaceholder.isNull() && !isDetached()) {
|
||||
if (myPlaceholder.isNull()) {
|
||||
myPlaceholder.setContent(myTabs.getComponent());
|
||||
}
|
||||
|
||||
@@ -211,7 +198,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
|
||||
ActionGroup group = (ActionGroup)myContext.getActionManager().getAction(RunnerContentUi.VIEW_TOOLBAR);
|
||||
tabInfo.setTabLabelActions(group, ViewContext.CELL_TOOLBAR_PLACE);
|
||||
|
||||
tabInfo.setDragOutDelegate(((RunnerContentUi)myContext).myDragOutDelegate);
|
||||
return tabInfo;
|
||||
}
|
||||
|
||||
@@ -248,7 +235,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
return myMinimizedContents.contains(content);
|
||||
}
|
||||
|
||||
public java.util.List<SwitchTarget> getTargets(boolean onlyVisible) {
|
||||
public List<SwitchTarget> getTargets(boolean onlyVisible) {
|
||||
if (myTabs.getPresentation().isHideTabs()) return new ArrayList<SwitchTarget>();
|
||||
|
||||
return myTabs.getTargets(onlyVisible, false);
|
||||
@@ -287,7 +274,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TabInfo getTabFor(Content content) {
|
||||
TabInfo getTabFor(Content content) {
|
||||
return myContents.getValue(content);
|
||||
}
|
||||
|
||||
@@ -306,14 +293,21 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
restoreProportions();
|
||||
|
||||
Content[] contents = getContents();
|
||||
int window = 0;
|
||||
for (Content each : contents) {
|
||||
if (myContainer.getStateFor(each).isMinimizedInGrid()) {
|
||||
final View view = myContainer.getStateFor(each);
|
||||
if (view.isMinimizedInGrid()) {
|
||||
minimize(each);
|
||||
}
|
||||
window = view.getWindow();
|
||||
}
|
||||
|
||||
if (!isRestoringFromDetach() && myContainer.getTab().isDetached(myPlaceInGrid) && contents.length > 0) {
|
||||
_detach(!myContext.isStateBeingRestored()).notifyWhenDone(result);
|
||||
final Tab tab = myContainer.getTab();
|
||||
final boolean detached = (tab != null && tab.isDetached(myPlaceInGrid)) || window != myContext.getWindow();
|
||||
if (detached && contents.length > 0) {
|
||||
if (tab != null) {
|
||||
tab.setDetached(myPlaceInGrid, false);
|
||||
}
|
||||
myContext.detachTo(window, this).notifyWhenDone(result);
|
||||
} else {
|
||||
result.setDone();
|
||||
}
|
||||
@@ -321,7 +315,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
private Content[] getContents() {
|
||||
Content[] getContents() {
|
||||
return myContents.getKeys().toArray(new Content[myContents.size()]);
|
||||
}
|
||||
|
||||
@@ -339,6 +333,14 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
for (Content each : myMinimizedContents) {
|
||||
saveState(each, true);
|
||||
}
|
||||
|
||||
final DimensionService service = DimensionService.getInstance();
|
||||
final Dimension size = myContext.getContentManager().getComponent().getSize();
|
||||
service.setSize(getDimensionKey(), size, myContext.getProject());
|
||||
if (myContext.getWindow() != 0) {
|
||||
final JFrame frame = (JFrame)DockManager.getInstance(myContext.getProject()).getIdeFrame((DockContainer)myContext);
|
||||
service.setLocation(getDimensionKey(), frame.getLocationOnScreen());
|
||||
}
|
||||
}
|
||||
|
||||
public void saveProportions() {
|
||||
@@ -350,8 +352,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
state.setMinimizedInGrid(minimized);
|
||||
state.setPlaceInGrid(myPlaceInGrid);
|
||||
state.assignTab(myContainer.getTabIndex());
|
||||
|
||||
state.getTab().setDetached(myPlaceInGrid, isDetached());
|
||||
state.setWindow(myContext.getWindow());
|
||||
}
|
||||
|
||||
public void restoreProportions() {
|
||||
@@ -362,7 +363,7 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
for (Content each : myContents.getKeys()) {
|
||||
final TabInfo eachTab = getTabFor(each);
|
||||
boolean isSelected = eachTab != null && myTabs.getSelectedInfo() == eachTab;
|
||||
if (isSelected && (isShowing || isDetached())) {
|
||||
if (isSelected && isShowing) {
|
||||
myContext.getContentManager().addSelectedContent(each);
|
||||
}
|
||||
else {
|
||||
@@ -391,147 +392,22 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
public ActionCallback detach() {
|
||||
return _detach(true);
|
||||
@Nullable
|
||||
public Point getLocation() {
|
||||
return DimensionService.getInstance().getLocation(getDimensionKey(), myContext.getProject());
|
||||
}
|
||||
|
||||
private ActionCallback _detach(final boolean requestFocus) {
|
||||
myContext.saveUiState();
|
||||
|
||||
final DimensionService dimService = DimensionService.getInstance();
|
||||
Point storedLocation = dimService.getLocation(getDimensionKey(), myContext.getProject());
|
||||
Dimension storedSize = dimService.getSize(getDimensionKey(), myContext.getProject());
|
||||
|
||||
final IdeFrame frame = WindowManager.getInstance().getIdeFrame(myContext.getProject());
|
||||
final Rectangle targetBounds = frame.suggestChildFrameBounds();
|
||||
|
||||
|
||||
if (storedLocation != null && storedSize != null) {
|
||||
targetBounds.setLocation(storedLocation);
|
||||
targetBounds.setSize(storedSize);
|
||||
}
|
||||
|
||||
final ActionCallback result = new ActionCallback();
|
||||
|
||||
if (storedLocation == null || storedSize == null) {
|
||||
if (myContents.size() > 0) {
|
||||
myContext.validate(myContents.getKeys().iterator().next(), new ActiveRunnable() {
|
||||
public ActionCallback run() {
|
||||
if (!myTabs.getComponent().isShowing()) {
|
||||
detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result);
|
||||
} else {
|
||||
detachForShowingTabs(requestFocus).notifyWhenDone(result);
|
||||
}
|
||||
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
detachTo(targetBounds.getLocation(), targetBounds.getSize(), false, requestFocus).notifyWhenDone(result);
|
||||
|
||||
return result;
|
||||
@Nullable
|
||||
public Dimension getSize() {
|
||||
return DimensionService.getInstance().getSize(getDimensionKey(), myContext.getProject());
|
||||
}
|
||||
|
||||
private ActionCallback detachForShowingTabs(boolean requestFocus) {
|
||||
return detachTo(myTabs.getComponent().getLocationOnScreen(), myTabs.getComponent().getSize(), false, requestFocus);
|
||||
}
|
||||
|
||||
private ActionCallback detachTo(Point screenPoint, Dimension size, boolean dragging, final boolean requestFocus) {
|
||||
if (isDetached()) {
|
||||
if (myPopup != null) {
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
}
|
||||
|
||||
final Content[] contents = getContents();
|
||||
|
||||
myRestoreFromDetach = new CellTransform.Restore.List();
|
||||
|
||||
myRestoreFromDetach.add(myPlaceholder.detach());
|
||||
myRestoreFromDetach.add(myContainer.detach(contents));
|
||||
myRestoreFromDetach.add(new CellTransform.Restore() {
|
||||
public ActionCallback restoreInGrid() {
|
||||
ensureVisible();
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
});
|
||||
|
||||
myPopup = createPopup(dragging, requestFocus);
|
||||
myPopup.setSize(size);
|
||||
myPopup.setLocation(screenPoint);
|
||||
myPopup.show(myContext.getContentManager().getComponent());
|
||||
|
||||
myContext.saveUiState();
|
||||
|
||||
myTabs.updateTabActions(true);
|
||||
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
|
||||
private void ensureVisible() {
|
||||
if (myTabs.getSelectedInfo() != null) {
|
||||
myContext.select(getContentFor(myTabs.getSelectedInfo()), true);
|
||||
}
|
||||
}
|
||||
|
||||
private JBPopup createPopup(boolean dragging, final boolean requestFocus) {
|
||||
Wrapper wrapper = new Wrapper(myTabs.getComponent());
|
||||
wrapper.setBorder(new EmptyBorder(1, 0, 0, 0));
|
||||
final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(wrapper, myTabs.getComponent())
|
||||
.setTitle(myContainer.getSessionName())
|
||||
.setMovable(true)
|
||||
.setRequestFocus(requestFocus)
|
||||
.setFocusable(true)
|
||||
.setResizable(true)
|
||||
.setDimensionServiceKey(myContext.getProject(), getDimensionKey(), true)
|
||||
.setCancelOnOtherWindowOpen(false)
|
||||
.setCancelOnClickOutside(false)
|
||||
.setCancelKeyEnabled(true)
|
||||
.setLocateByContent(dragging)
|
||||
.setLocateWithinScreenBounds(!dragging)
|
||||
.setCancelKeyEnabled(false)
|
||||
.setBelongsToGlobalPopupStack(false)
|
||||
.setModalContext(false)
|
||||
.setCancelCallback(new Computable<Boolean>() {
|
||||
public Boolean compute() {
|
||||
if (myDisposed || myContents.size() == 0) return Boolean.TRUE;
|
||||
myRestoreFromDetach.restoreInGrid();
|
||||
myRestoreFromDetach = null;
|
||||
myContext.saveUiState();
|
||||
myTabs.updateTabActions(true);
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
});
|
||||
|
||||
return builder.createPopup();
|
||||
}
|
||||
|
||||
public void attach() {
|
||||
if (isDetached()) {
|
||||
myPopup.cancel();
|
||||
myPopup = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isDetached() {
|
||||
return myRestoreFromDetach != null && !myRestoreFromDetach.isRestoringNow();
|
||||
}
|
||||
|
||||
public boolean isRestoringFromDetach() {
|
||||
return myRestoreFromDetach != null && myRestoreFromDetach.isRestoringNow();
|
||||
}
|
||||
|
||||
|
||||
private String getDimensionKey() {
|
||||
return "GridCell.Tab." + myContainer.getTab().getIndex() + "." + myPlaceInGrid.name();
|
||||
}
|
||||
|
||||
public boolean isValidForCalculatePropertions() {
|
||||
return !isDetached() && getContentCount() > 0;
|
||||
public boolean isValidForCalculateProportions() {
|
||||
return getContentCount() > 0;
|
||||
}
|
||||
|
||||
public void minimize(Content content) {
|
||||
@@ -553,13 +429,4 @@ public class GridCellImpl implements GridCell, Disposable {
|
||||
updateSelection(myTabs.getComponent().getRootPane() != null);
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
myDisposed = true;
|
||||
|
||||
if (myPopup != null) {
|
||||
myPopup.cancel();
|
||||
myPopup = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform.Facade, DataProvider {
|
||||
public class GridImpl extends Wrapper implements Grid, Disposable, DataProvider {
|
||||
private final ThreeComponentsSplitter myTopSplit = new ThreeComponentsSplitter();
|
||||
private final Splitter mySplitter = new Splitter(true);
|
||||
|
||||
@@ -152,8 +152,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
|
||||
public boolean updateGridUI() {
|
||||
for (final GridCellImpl cell : myPlaceInGrid2Cell.values()) {
|
||||
final boolean eachToHide = myContents.size() == 1 && !cell.isDetached();
|
||||
cell.setHideTabs(eachToHide);
|
||||
cell.setHideTabs(myContents.size() == 1);
|
||||
}
|
||||
|
||||
final Content onlyContent = myContents.get(0);
|
||||
@@ -252,7 +251,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
|
||||
final GridCellImpl cell = myPlaceInGrid2Cell.get(placeInGrid);
|
||||
|
||||
if (!cell.isValidForCalculatePropertions()) return;
|
||||
if (!cell.isValidForCalculateProportions()) return;
|
||||
|
||||
final TabImpl tab = (TabImpl)getTab();
|
||||
|
||||
@@ -335,19 +334,12 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
ArrayList<Content> result = new ArrayList<Content>();
|
||||
|
||||
for (Content each : getContents()) {
|
||||
if (!isDetached(each)) {
|
||||
result.add(each);
|
||||
}
|
||||
result.add(each);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDetached(Content content) {
|
||||
return getCellFor(content).isDetached();
|
||||
}
|
||||
|
||||
public List<Content> getContents() {
|
||||
return myContents;
|
||||
}
|
||||
@@ -360,28 +352,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
});
|
||||
}
|
||||
|
||||
public void moveToTab(final Content content) {
|
||||
myViewContext.getCellTransform().moveToTab(content);
|
||||
}
|
||||
|
||||
public void moveToGrid(final Content content) {
|
||||
myViewContext.getCellTransform().moveToGrid(content);
|
||||
}
|
||||
|
||||
public CellTransform.Restore detach(final Content[] content) {
|
||||
final CellTransform.Restore.List restore = new CellTransform.Restore.List();
|
||||
restore.add(myViewContext.getCellTransform().detach(content));
|
||||
restore.add(new CellTransform.Restore() {
|
||||
public ActionCallback restoreInGrid() {
|
||||
revalidate();
|
||||
repaint();
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
});
|
||||
|
||||
return restore;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Object getData(@NonNls final String dataId) {
|
||||
if (ViewContext.CONTEXT_KEY.is(dataId)) {
|
||||
@@ -394,10 +364,6 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getSessionName() {
|
||||
return mySessionName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SwitchTarget getCellFor(Component c) {
|
||||
Component eachParent = c;
|
||||
@@ -419,9 +385,7 @@ public class GridImpl extends Wrapper implements Grid, Disposable, CellTransform
|
||||
Collection<GridCellImpl> cells = myPlaceInGrid2Cell.values();
|
||||
ArrayList<SwitchTarget> result = new ArrayList<SwitchTarget>();
|
||||
for (GridCellImpl each : cells) {
|
||||
if (!each.isDetached()) {
|
||||
result.addAll(each.getTargets(onlyVisible));
|
||||
}
|
||||
result.addAll(each.getTargets(onlyVisible));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* 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.execution.ui.layout.impl;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsUtil;
|
||||
import com.intellij.ui.tabs.UiDecorator;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.ui.tabs.impl.TabLabel;
|
||||
import com.intellij.util.ui.SameColor;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Dennis.Ushakov
|
||||
*/
|
||||
public class
|
||||
JBRunnerTabs extends JBTabsImpl {
|
||||
public JBRunnerTabs(@Nullable Project project, ActionManager actionManager, IdeFocusManager focusManager, @NotNull Disposable parent) {
|
||||
super(project, actionManager, focusManager, parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintFirstGhost(Graphics2D g2d) {}
|
||||
|
||||
@Override
|
||||
protected void paintLastGhost(Graphics2D g2d) {}
|
||||
|
||||
public boolean isGhostsAlwaysVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void doPaintInactive(Graphics2D g2d,
|
||||
boolean leftGhostExists,
|
||||
TabLabel label,
|
||||
Rectangle effectiveBounds,
|
||||
boolean rightGhostExists) {
|
||||
Insets insets = getTabsBorder().getEffectiveBorder();
|
||||
|
||||
int _x = effectiveBounds.x + insets.left;
|
||||
int _y = effectiveBounds.y + insets.top + 5;
|
||||
int _width = effectiveBounds.width - insets.left - insets.right;
|
||||
int _height = effectiveBounds.height - insets.top - insets.bottom - 5;
|
||||
_height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
|
||||
g2d
|
||||
.setPaint(new GradientPaint(_x, _y, new Color(255, 255, 255, 180), _x, _y + effectiveBounds.height, new Color(255, 255, 255, 100)));
|
||||
g2d.fillRect(_x, _y, _width, _height);
|
||||
|
||||
g2d.setColor(new Color(255, 255, 255, 100));
|
||||
g2d.drawRect(_x, _y, _width - 1, _height - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPaintBackground(Graphics2D g2d, Rectangle clip) {
|
||||
g2d.setColor(UIUtil.getPanelBackground());
|
||||
g2d.fill(clip);
|
||||
|
||||
g2d.setColor(new Color(0, 0, 0, 50));
|
||||
g2d.fill(clip);
|
||||
|
||||
List<TabInfo> visibleInfos = getVisibleInfos();
|
||||
|
||||
Insets insets = getTabsBorder().getEffectiveBorder();
|
||||
|
||||
int maxOffset = 0;
|
||||
int maxLength = 0;
|
||||
|
||||
for (int i = visibleInfos.size() - 1; i >= 0; i--) {
|
||||
TabInfo visibleInfo = visibleInfos.get(i);
|
||||
TabLabel tabLabel = myInfo2Label.get(visibleInfo);
|
||||
Rectangle r = tabLabel.getBounds();
|
||||
if (r.width == 0 || r.height == 0) continue;
|
||||
maxOffset = r.x + r.width;
|
||||
maxLength = r.height;
|
||||
break;
|
||||
}
|
||||
|
||||
maxOffset++;
|
||||
|
||||
Rectangle r2 = getBounds();
|
||||
|
||||
Rectangle rectangle;
|
||||
int y = r2.y + insets.top;
|
||||
int height = maxLength - insets.top - insets.bottom;
|
||||
height -= TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT;
|
||||
|
||||
rectangle = new Rectangle(maxOffset, y, r2.width - maxOffset - insets.left - insets.right, height);
|
||||
|
||||
g2d.setPaint(UIUtil.getPanelBackground());
|
||||
g2d.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||
g2d.fillRect(0, 0, rectangle.x + rectangle.width, 5);
|
||||
g2d.fillRect(2, maxLength, getSize().width, getSize().height);
|
||||
g2d.drawLine(0, 0, 0, getSize().height);
|
||||
}
|
||||
|
||||
protected void paintSelectionAndBorder(Graphics2D g2d) {
|
||||
if (getSelectedInfo() == null) return;
|
||||
|
||||
TabLabel label = getSelectedLabel();
|
||||
Rectangle r = label.getBounds();
|
||||
r = new Rectangle(r.x, r.y + 5, r.width, r.height - 5);
|
||||
|
||||
ShapeInfo selectedShape = _computeSelectedLabelShape(r);
|
||||
|
||||
Insets insets = getTabsBorder().getEffectiveBorder();
|
||||
Insets i = selectedShape.path.transformInsets(insets);
|
||||
|
||||
int _x = r.x;
|
||||
int _y = r.y;
|
||||
int _height = r.height;
|
||||
|
||||
if (!isHideTabs()) {
|
||||
g2d.setPaint(new GradientPaint(_x, _y, new SameColor(255), _x, _y + _height, UIUtil.getPanelBackground()));
|
||||
|
||||
g2d.fill(selectedShape.fillPath.getShape());
|
||||
|
||||
g2d.setColor(new Color(255, 255, 255, 180));
|
||||
g2d.draw(selectedShape.fillPath.getShape());
|
||||
}
|
||||
g2d.setColor(UIUtil.getPanelBackground());
|
||||
g2d.fillRect(2, selectedShape.labelPath.getMaxY() - 3, selectedShape.path.getMaxX() - 3, 4);
|
||||
g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1);
|
||||
g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4,
|
||||
selectedShape.path.getMaxX() - 1, getHeight() - 1);
|
||||
|
||||
if (isHideTabs()) return;
|
||||
g2d.setColor(new Color(0, 0, 0, 50));
|
||||
g2d.drawLine(1, selectedShape.labelPath.getMaxY(), 1, getHeight() - 1);
|
||||
g2d.drawLine(selectedShape.path.getMaxX() - 1, selectedShape.labelPath.getMaxY() - 4,
|
||||
selectedShape.path.getMaxX() - 1, getHeight() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
return Gray._142;
|
||||
}
|
||||
|
||||
protected ShapeInfo _computeSelectedLabelShape(Rectangle r) {
|
||||
final ShapeInfo shape = new ShapeInfo();
|
||||
|
||||
shape.path = getEffectiveLayout().createShapeTransform(getSize());
|
||||
shape.insets = shape.path.transformInsets(getLayoutInsets());
|
||||
shape.labelPath = shape.path.createTransform(r);
|
||||
|
||||
shape.labelBottomY = shape.labelPath.getMaxY() - shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1);
|
||||
shape.labelTopY = shape.labelPath.getY() + shape.labelPath.deltaY(1);
|
||||
shape.labelLeftX = shape.labelPath.getX();
|
||||
shape.labelRightX = shape.labelPath.getMaxX() - shape.labelPath.deltaX(1);
|
||||
|
||||
int leftX = shape.insets.left;
|
||||
|
||||
shape.path.moveTo(leftX, shape.labelBottomY);
|
||||
shape.path.lineTo(shape.labelLeftX, shape.labelBottomY);
|
||||
shape.path.lineTo(shape.labelLeftX, shape.labelTopY);
|
||||
shape.path.lineTo(shape.labelRightX, shape.labelTopY);
|
||||
shape.path.lineTo(shape.labelRightX, shape.labelBottomY);
|
||||
|
||||
int lastX = shape.path.getWidth() - shape.path.deltaX(shape.insets.right);
|
||||
|
||||
shape.path.lineTo(lastX, shape.labelBottomY);
|
||||
shape.path.lineTo(lastX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
|
||||
shape.path.lineTo(leftX, shape.labelBottomY + shape.labelPath.deltaY(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT - 1));
|
||||
|
||||
shape.path.closePath();
|
||||
shape.fillPath = shape.path.copy();
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getToolbarInset() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
public boolean shouldAddToGlobal(Point point) {
|
||||
final TabLabel label = getSelectedLabel();
|
||||
if (label == null || point == null) {
|
||||
return true;
|
||||
}
|
||||
final Rectangle bounds = label.getBounds();
|
||||
return point.y <= bounds.y + bounds.height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle layout(JComponent c, Rectangle bounds) {
|
||||
if (c instanceof Toolbar) {
|
||||
bounds.height -= 5;
|
||||
return super.layout(c, bounds);
|
||||
}
|
||||
if (c instanceof GridImpl) {
|
||||
bounds.x -= 1;
|
||||
bounds.width += 1;
|
||||
}
|
||||
return super.layout(c, bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDropOver(TabInfo over, RelativePoint relativePoint) {
|
||||
super.processDropOver(over, relativePoint);
|
||||
final Point point = relativePoint.getPoint(getComponent());
|
||||
for (Map.Entry<TabInfo, TabLabel> entry : myInfo2Label.entrySet()) {
|
||||
final TabLabel label = entry.getValue();
|
||||
if (label.getBounds().contains(point) && myDropInfo != entry.getKey()) {
|
||||
select(entry.getKey(), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TabLabel createTabLabel(TabInfo info) {
|
||||
return new MyTabLabel(this, info);
|
||||
}
|
||||
|
||||
private static class MyTabLabel extends TabLabel {
|
||||
public MyTabLabel(JBTabsImpl tabs, final TabInfo info) {
|
||||
super(tabs, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(UiDecorator.UiDecoration decoration) {
|
||||
setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
|
||||
myLabel.setFont(UIUtil.getLabelFont(UIUtil.FontSize.SMALL));
|
||||
setBorder(new EmptyBorder(7, 5, 7, 5));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTabActionsAutoHide(boolean autoHide) {
|
||||
super.setTabActionsAutoHide(autoHide);
|
||||
apply(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTabActions(ActionGroup group) {
|
||||
super.setTabActions(group);
|
||||
if (myActionPanel != null) {
|
||||
final JComponent wrapper = (JComponent)myActionPanel.getComponent(0);
|
||||
wrapper.remove(0);
|
||||
wrapper.add(Box.createHorizontalStrut(6), BorderLayout.WEST);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSelectedOffset() {
|
||||
return getNonSelectedOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
+478
-130
@@ -28,21 +28,28 @@ import com.intellij.openapi.util.ActiveRunnable;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.awt.RelativeRectangle;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.components.panels.Wrapper;
|
||||
import com.intellij.ui.content.*;
|
||||
import com.intellij.ui.docking.DockContainer;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.ui.docking.DockableContent;
|
||||
import com.intellij.ui.docking.DragSession;
|
||||
import com.intellij.ui.docking.impl.DockManagerImpl;
|
||||
import com.intellij.ui.switcher.QuickActionProvider;
|
||||
import com.intellij.ui.switcher.SwitchProvider;
|
||||
import com.intellij.ui.switcher.SwitchTarget;
|
||||
import com.intellij.ui.tabs.JBTabs;
|
||||
import com.intellij.ui.tabs.TabInfo;
|
||||
import com.intellij.ui.tabs.TabsListener;
|
||||
import com.intellij.ui.tabs.UiDecorator;
|
||||
import com.intellij.ui.tabs.impl.JBTabsImpl;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.AbstractLayoutManager;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -50,13 +57,15 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Facade, ViewContextEx, PropertyChangeListener, SwitchProvider,
|
||||
QuickActionProvider {
|
||||
QuickActionProvider, DockContainer {
|
||||
|
||||
@NonNls public static final String LAYOUT = "Runner.Layout";
|
||||
@NonNls public static final String VIEW_POPUP = "Runner.View.Popup";
|
||||
@@ -70,8 +79,9 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
MyComponent myComponent = new MyComponent();
|
||||
|
||||
private final Wrapper myToolbar = new Wrapper();
|
||||
final MyDragOutDelegate myDragOutDelegate = new MyDragOutDelegate();
|
||||
|
||||
JBTabs myTabs;
|
||||
JBRunnerTabs myTabs;
|
||||
private final Comparator<TabInfo> myTabsComparator = new Comparator<TabInfo>() {
|
||||
public int compare(final TabInfo o1, final TabInfo o2) {
|
||||
//noinspection ConstantConditions
|
||||
@@ -110,6 +120,20 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
private int myAttractionCount;
|
||||
private ActionGroup myLeftToolbarActions;
|
||||
|
||||
private JBTabs myCurrentOver;
|
||||
private Image myCurrentOverImg;
|
||||
private TabInfo myCurrentOverInfo;
|
||||
private RunnerContentUi myOriginal;
|
||||
private CopyOnWriteArraySet<Listener> myDockingListeners = new CopyOnWriteArraySet<Listener>();
|
||||
private Set<RunnerContentUi> myChildren = new TreeSet<RunnerContentUi>(new Comparator<RunnerContentUi>() {
|
||||
@Override
|
||||
public int compare(RunnerContentUi o1, RunnerContentUi o2) {
|
||||
return o1.myWindow - o2.myWindow;
|
||||
}
|
||||
});
|
||||
private int myWindow;
|
||||
private boolean myDisposing;
|
||||
|
||||
public RunnerContentUi(Project project,
|
||||
RunnerLayoutUi ui,
|
||||
ActionManager actionManager,
|
||||
@@ -124,6 +148,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
myFocusManager = focusManager;
|
||||
}
|
||||
|
||||
public RunnerContentUi(RunnerContentUi ui, RunnerContentUi original, int window) {
|
||||
this(ui.myProject, ui.myRunnerUi, ui.myActionManager, ui.myFocusManager, ui.myLayoutSettings, ui.mySessionName);
|
||||
myOriginal = original;
|
||||
original.myChildren.add(this);
|
||||
myWindow = window == 0 ? original.findFreeWindow() : window;
|
||||
}
|
||||
|
||||
public void setTopActions(@NotNull final ActionGroup topActions, @NotNull String place) {
|
||||
myTopActions = topActions;
|
||||
@@ -150,32 +180,27 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
public void initUi() {
|
||||
if (myTabs != null) return;
|
||||
|
||||
myTabs = new JBTabsImpl(myProject, myActionManager, myFocusManager, this)
|
||||
.setDataProvider(new DataProvider() {
|
||||
public Object getData(@NonNls final String dataId) {
|
||||
if (ViewContext.CONTENT_KEY.is(dataId)) {
|
||||
TabInfo info = myTabs.getTargetInfo();
|
||||
if (info != null) {
|
||||
return getGridFor(info).getData(dataId);
|
||||
}
|
||||
myTabs = (JBRunnerTabs)new JBRunnerTabs(myProject, myActionManager, myFocusManager, this).setDataProvider(new DataProvider() {
|
||||
public Object getData(@NonNls final String dataId) {
|
||||
if (ViewContext.CONTENT_KEY.is(dataId)) {
|
||||
TabInfo info = myTabs.getTargetInfo();
|
||||
if (info != null) {
|
||||
return getGridFor(info).getData(dataId);
|
||||
}
|
||||
else if (ViewContext.CONTEXT_KEY.is(dataId)) {
|
||||
return RunnerContentUi.this;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).setProvideSwitchTargets(false).setInnerInsets(new Insets(1, 0, 0, 0)).setToDrawBorderIfTabsHidden(false)
|
||||
.setUiDecorator(new UiDecorator() {
|
||||
@NotNull
|
||||
public UiDecoration getDecoration() {
|
||||
return new UiDecoration(null, new Insets(1, 8, 1, 8));
|
||||
else if (ViewContext.CONTEXT_KEY.is(dataId)) {
|
||||
return RunnerContentUi.this;
|
||||
}
|
||||
}).getJBTabs();
|
||||
return null;
|
||||
}
|
||||
}).setTabLabelActionsAutoHide(false).setProvideSwitchTargets(false).setInnerInsets(new Insets(0, 0, 0, 0))
|
||||
.setToDrawBorderIfTabsHidden(false).setTabDraggingEnabled(isMoveToGridActionEnabled()).setUiDecorator(null).getJBTabs();
|
||||
rebuildTabPopup();
|
||||
|
||||
|
||||
myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setTabSidePaintBorder(2).setPaintFocus(false)
|
||||
myTabs.getPresentation().setPaintBorder(0, 0, 0, 0).setPaintFocus(false)
|
||||
.setRequestFocusOnLastFocusedComponent(true);
|
||||
myTabs.getComponent().setBackground(myToolbar.getBackground());
|
||||
myTabs.getComponent().setBorder(new EmptyBorder(0, 2, 0, 0));
|
||||
|
||||
final NonOpaquePanel wrappper = new NonOpaquePanel(new BorderLayout(0, 0));
|
||||
wrappper.add(myToolbar, BorderLayout.WEST);
|
||||
@@ -194,6 +219,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tabsMoved() {
|
||||
saveUiState();
|
||||
}
|
||||
|
||||
public void selectionChanged(final TabInfo oldSelection, final TabInfo newSelection) {
|
||||
if (!myTabs.getComponent().isShowing()) return;
|
||||
|
||||
@@ -207,6 +237,14 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (myOriginal != null) {
|
||||
final ContentManager manager = ContentFactory.SERVICE.getInstance().createContentManager(this, false, myProject);
|
||||
Disposer.register((Disposable)myRunnerUi, manager);
|
||||
manager.getComponent();
|
||||
} else {
|
||||
DockManager.getInstance(myProject).register(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void rebuildTabPopup() {
|
||||
@@ -249,10 +287,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
return group;
|
||||
}
|
||||
|
||||
public void doWhenInitialized(final Runnable runnable) {
|
||||
myInitialized.doWhenDone(runnable);
|
||||
@Override
|
||||
public boolean isOriginal() {
|
||||
return myOriginal == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindow() {
|
||||
return myWindow;
|
||||
}
|
||||
|
||||
public void propertyChange(final PropertyChangeEvent evt) {
|
||||
Content content = (Content)evt.getSource();
|
||||
@@ -302,11 +345,193 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionCallback detachTo(int window, GridCell cell) {
|
||||
if (myOriginal != null) {
|
||||
return myOriginal.detachTo(window, cell);
|
||||
}
|
||||
RunnerContentUi target = null;
|
||||
if (window > 0) {
|
||||
for (RunnerContentUi child : myChildren) {
|
||||
if (child.myWindow == window) {
|
||||
target = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
final GridCellImpl gridCell = (GridCellImpl)cell;
|
||||
final Content[] contents = gridCell.getContents();
|
||||
storeDefaultIndices(contents);
|
||||
for (Content content : contents) {
|
||||
content.putUserData(RunnerLayout.DROP_INDEX, getStateFor(content).getTab().getIndex());
|
||||
}
|
||||
Dimension size = gridCell.getSize();
|
||||
if (size == null) {
|
||||
size = new Dimension(200, 200);
|
||||
}
|
||||
final DockableGrid content = new DockableGrid(null, null, size, Arrays.asList(contents), window);
|
||||
if (target != null) {
|
||||
target.add(content, null);
|
||||
} else {
|
||||
final Point location = gridCell.getLocation();
|
||||
location.translate(size.width / 2, size.height / 2);
|
||||
getDockManager().createNewDockContainerFor(content, new RelativePoint(location));
|
||||
}
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
|
||||
private void storeDefaultIndices(Content[] contents) {
|
||||
for (Content content : contents) {
|
||||
content.putUserData(RunnerLayout.DEFAULT_INDEX, getStateFor(content).getTab().getDefaultIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelativeRectangle getAcceptArea() {
|
||||
return new RelativeRectangle(myTabs.getComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccept(DockableContent content, RelativePoint point) {
|
||||
if (!(content instanceof DockableGrid)) {
|
||||
return false;
|
||||
}
|
||||
final RunnerContentUi ui = ((DockableGrid)content).getOriginalRunnerUi();
|
||||
return ui.getProject() == myProject && ui.mySessionName.equals(mySessionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
initUi();
|
||||
return myComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getContainerComponent() {
|
||||
initUi();
|
||||
return myManager.getComponent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(DockableContent dockable, RelativePoint dropTarget) {
|
||||
saveUiState();
|
||||
|
||||
final DockableGrid dockableGrid = (DockableGrid)dockable;
|
||||
final List<Content> contents = dockableGrid.getContents();
|
||||
final boolean wasRestoring = myOriginal != null && myOriginal.isStateBeingRestored();
|
||||
setStateIsBeingRestored(true, this);
|
||||
try {
|
||||
final Point point = dropTarget != null ? dropTarget.getPoint(myComponent) : null;
|
||||
boolean hadGrid = !myTabs.shouldAddToGlobal(point);
|
||||
|
||||
for (Content content : contents) {
|
||||
dockableGrid.getRunnerUi().myManager.removeContent(content, false);
|
||||
myManager.removeContent(content, false);
|
||||
if (hadGrid && contents.size() == 1 && !wasRestoring) {
|
||||
getStateFor(content).assignTab(getTabFor(getSelectedGrid()));
|
||||
getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
|
||||
} else if (contents.size() == 1 && !wasRestoring) {
|
||||
getStateFor(content).assignTab(myLayoutSettings.createNewTab());
|
||||
getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
|
||||
}
|
||||
getStateFor(content).setWindow(myWindow);
|
||||
myManager.addContent(content);
|
||||
}
|
||||
} finally {
|
||||
setStateIsBeingRestored(false, this);
|
||||
}
|
||||
|
||||
saveUiState();
|
||||
|
||||
updateTabsUI(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeAll() {
|
||||
final Content[] contents = myManager.getContents();
|
||||
for (Content content : contents) {
|
||||
getStateFor(content).setWindow(0);
|
||||
}
|
||||
myManager.removeAllContents(false);
|
||||
for (Content content : contents) {
|
||||
myOriginal.myManager.addContent(content);
|
||||
myOriginal.findCellFor(content).minimize(content);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(final Listener listener, Disposable parent) {
|
||||
myDockingListeners.add(listener);
|
||||
Disposer.register(parent, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
myDockingListeners.remove(listener);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return myTabs.isEmptyVisible() || myDisposing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image startDropOver(DockableContent content, RelativePoint point) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image processDropOver(DockableContent content, RelativePoint point) {
|
||||
JBTabs current = getTabsAt(content, point);
|
||||
|
||||
if (myCurrentOver != null && myCurrentOver != current) {
|
||||
resetDropOver(content);
|
||||
}
|
||||
|
||||
if (myCurrentOver == null && current != null) {
|
||||
myCurrentOver = current;
|
||||
Presentation presentation = content.getPresentation();
|
||||
myCurrentOverInfo = new TabInfo(new JLabel("")).setText(presentation.getText()).setIcon(presentation.getIcon());
|
||||
myCurrentOverImg = myCurrentOver.startDropOver(myCurrentOverInfo, point);
|
||||
}
|
||||
|
||||
if (myCurrentOver != null) {
|
||||
myCurrentOver.processDropOver(myCurrentOverInfo, point);
|
||||
}
|
||||
|
||||
return myCurrentOverImg;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JBTabs getTabsAt(DockableContent content, RelativePoint point) {
|
||||
if (content instanceof DockableGrid) {
|
||||
final Point p = point.getPoint(getComponent());
|
||||
Component c = SwingUtilities.getDeepestComponentAt(getComponent(), p.x, p.y);
|
||||
while (c != null) {
|
||||
if (c instanceof JBTabs) {
|
||||
return (JBTabs)c;
|
||||
}
|
||||
c = c.getParent();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetDropOver(DockableContent content) {
|
||||
if (myCurrentOver != null) {
|
||||
myCurrentOver.resetDropOver(myCurrentOverInfo);
|
||||
myCurrentOver = null;
|
||||
myCurrentOverInfo = null;
|
||||
myCurrentOverImg = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisposeWhenEmpty() {
|
||||
return myOriginal != null;
|
||||
}
|
||||
|
||||
public boolean isCycleRoot() {
|
||||
return false;
|
||||
}
|
||||
@@ -337,6 +562,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
|
||||
|
||||
event.getContent().addPropertyChangeListener(RunnerContentUi.this);
|
||||
fireContentOpened(event.getContent());
|
||||
}
|
||||
|
||||
public void contentRemoved(final ContentManagerEvent event) {
|
||||
@@ -349,6 +575,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
removeGridIfNeeded(grid);
|
||||
}
|
||||
updateTabsUI(false);
|
||||
fireContentClosed(event.getContent());
|
||||
}
|
||||
|
||||
public void contentRemoveQuery(final ContentManagerEvent event) {
|
||||
@@ -387,6 +614,16 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
grid = new GridImpl(this, mySessionName);
|
||||
grid.setBorder(new EmptyBorder(1, 0, 0, 0));
|
||||
|
||||
if (myCurrentOver != null || myOriginal != null) {
|
||||
Integer forcedDropIndex = content.getUserData(RunnerLayout.DROP_INDEX);
|
||||
final int index = myTabs.getDropInfoIndex() + (myOriginal != null ? myOriginal.getTabOffsetFor(this) : 0);
|
||||
final TabImpl tab = myLayoutSettings.getOrCreateTab(-1);
|
||||
final Integer defaultIndex = content.getUserData(RunnerLayout.DEFAULT_INDEX);
|
||||
tab.setDefaultIndex(defaultIndex != null ? defaultIndex : -1);
|
||||
tab.setIndex(forcedDropIndex != null ? forcedDropIndex : index);
|
||||
getStateFor(content).assignTab(tab);
|
||||
}
|
||||
|
||||
TabInfo tab = new TabInfo(grid).setObject(getStateFor(content).getTab()).setText("Tab");
|
||||
|
||||
|
||||
@@ -418,6 +655,15 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
return grid;
|
||||
}
|
||||
|
||||
private int getTabOffsetFor(RunnerContentUi ui) {
|
||||
int offset = myTabs.getTabCount();
|
||||
for (RunnerContentUi child : myChildren) {
|
||||
if (child == ui) break;
|
||||
offset += child.myTabs.getTabCount();
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public GridCell findCellFor(final Content content) {
|
||||
GridImpl cell = getGridFor(content, false);
|
||||
@@ -498,9 +744,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
for (TabInfo each : tabs) {
|
||||
hasToolbarContent |= updateTabUI(each);
|
||||
}
|
||||
|
||||
myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1);
|
||||
|
||||
myTabs.getPresentation().setHideTabs(!hasToolbarContent && tabs.size() <= 1 && myOriginal == null);
|
||||
myTabs.updateTabActions(validateNow);
|
||||
|
||||
if (validateNow) {
|
||||
@@ -508,7 +752,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean updateTabUI(TabInfo tab) {
|
||||
private boolean updateTabUI(TabInfo tab) {
|
||||
TabImpl t = getTabFor(tab);
|
||||
if (t == null) {
|
||||
return false;
|
||||
@@ -534,9 +778,11 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
|
||||
if (icon == null && contents.size() == 1) {
|
||||
tab.setHidden(grid.isMinimized(contents.get(0)));
|
||||
icon = contents.get(0).getIcon();
|
||||
}
|
||||
|
||||
tab.setDragOutDelegate(myTabs.getTabs().size() > 1 || !isOriginal() ? myDragOutDelegate : null);
|
||||
|
||||
Tab gridTab = grid.getTab();
|
||||
tab.setText(title).setIcon(gridTab != null && gridTab.isDefault() ? null : icon);
|
||||
@@ -569,10 +815,38 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
public void saveUiState() {
|
||||
if (isStateBeingRestored()) return;
|
||||
|
||||
if (myOriginal != null) {
|
||||
myOriginal.saveUiState();
|
||||
return;
|
||||
}
|
||||
int offset = updateTabsIndices(myTabs, 0);
|
||||
for (RunnerContentUi child : myChildren) {
|
||||
offset = updateTabsIndices(child.myTabs, offset);
|
||||
}
|
||||
|
||||
doSaveUiState();
|
||||
}
|
||||
|
||||
private static int updateTabsIndices(final JBRunnerTabs tabs, int offset) {
|
||||
for (TabInfo each : tabs.getTabs()) {
|
||||
final int index = tabs.getIndexOf(each);
|
||||
final TabImpl tab = getTabFor(each);
|
||||
if (tab != null) tab.setIndex(index + offset);
|
||||
}
|
||||
return offset + tabs.getTabCount();
|
||||
}
|
||||
|
||||
private void doSaveUiState() {
|
||||
if (isStateBeingRestored()) return;
|
||||
|
||||
for (TabInfo each : myTabs.getTabs()) {
|
||||
GridImpl eachGrid = getGridFor(each);
|
||||
eachGrid.saveUiState();
|
||||
}
|
||||
|
||||
for (RunnerContentUi child : myChildren) {
|
||||
child.doSaveUiState();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -581,6 +855,17 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
return getTabFor(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showNotify() {
|
||||
final Window window = SwingUtilities.getWindowAncestor(myComponent);
|
||||
if (window instanceof IdeFrame.Child) {
|
||||
((IdeFrame.Child)window).setFrameTitle(mySessionName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideNotify() {}
|
||||
|
||||
@Nullable
|
||||
private static TabImpl getTabFor(@Nullable final TabInfo tab) {
|
||||
if (tab == null) {
|
||||
@@ -640,6 +925,10 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
if (myComponent.getRootPane() != null) {
|
||||
saveUiState();
|
||||
}
|
||||
if (myOriginal != null) {
|
||||
myDisposing = true;
|
||||
fireContentClosed(null);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canChangeSelectionTo(Content content, boolean implicit) {
|
||||
@@ -674,14 +963,25 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
|
||||
if (myOriginal != null) {
|
||||
myOriginal.myChildren.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreLayout() {
|
||||
Content[] all = myManager.getContents();
|
||||
final RunnerContentUi[] children = myChildren.toArray(new RunnerContentUi[myChildren.size()]);
|
||||
final List<Content> contents = new ArrayList<Content>();
|
||||
Collections.addAll(contents, myManager.getContents());
|
||||
for (RunnerContentUi child : children) {
|
||||
Collections.addAll(contents, child.myManager.getContents());
|
||||
}
|
||||
Content[] all = contents.toArray(new Content[contents.size()]);
|
||||
|
||||
setStateIsBeingRestored(true, this);
|
||||
try {
|
||||
for (RunnerContentUi child : children) {
|
||||
child.myManager.removeAllContents(false);
|
||||
}
|
||||
myManager.removeAllContents(false);
|
||||
myMinimizedViewActions.removeAll();
|
||||
}
|
||||
@@ -730,7 +1030,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
|
||||
public boolean isMinimizeActionEnabled() {
|
||||
return myMinimizeActionEnabled;
|
||||
return myMinimizeActionEnabled && myOriginal == null;
|
||||
}
|
||||
|
||||
public boolean isMoveToGridActionEnabled() {
|
||||
@@ -820,12 +1120,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
|
||||
if (!myUiLastStateWasRestored) {
|
||||
if (!myUiLastStateWasRestored && myOriginal == null) {
|
||||
myUiLastStateWasRestored = true;
|
||||
|
||||
//noinspection SSBasedInspection
|
||||
// [kirillk] this is done later since restoreUiState doesn't work properly in the addNotify call chain
|
||||
//todo to investigate and to fix (may cause extra flickering)
|
||||
//noinspection SSBasedInspection
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
restoreLastUiState().doWhenDone(new Runnable() {
|
||||
@@ -946,90 +1246,6 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
updateTabsUI(false);
|
||||
}
|
||||
|
||||
private static boolean willBeEmptyOnRemove(GridImpl grid, List<Content> toRemove) {
|
||||
List<Content> attachedToGrid = grid.getAttachedContents();
|
||||
for (Content each : attachedToGrid) {
|
||||
if (!toRemove.contains(each)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public CellTransform.Restore detach(final Content[] content) {
|
||||
List<Content> contents = Arrays.asList(content);
|
||||
|
||||
for (Content each : content) {
|
||||
GridImpl eachGrid = getGridFor(each, false);
|
||||
if (willBeEmptyOnRemove(eachGrid, contents)) {
|
||||
TabInfo info = myTabs.findInfo(eachGrid);
|
||||
if (info != null) {
|
||||
info.setHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateTabsUI(true);
|
||||
|
||||
return new CellTransform.Restore() {
|
||||
public ActionCallback restoreInGrid() {
|
||||
showHiddenTabs();
|
||||
updateTabsUI(true);
|
||||
return new ActionCallback.Done();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void showHiddenTabs() {
|
||||
List<TabInfo> tabs = myTabs.getTabs();
|
||||
for (TabInfo eachInfos : tabs) {
|
||||
GridImpl eachGrid = (GridImpl)eachInfos.getComponent();
|
||||
if (!eachGrid.getAttachedContents().isEmpty()) {
|
||||
eachInfos.setHidden(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void moveToTab(final Content content) {
|
||||
saveUiState();
|
||||
|
||||
setStateIsBeingRestored(true, this);
|
||||
try {
|
||||
myManager.removeContent(content, false);
|
||||
getStateFor(content).assignTab(myLayoutSettings.createNewTab());
|
||||
getStateFor(content).setPlaceInGrid(PlaceInGrid.center);
|
||||
myManager.addContent(content);
|
||||
}
|
||||
finally {
|
||||
setStateIsBeingRestored(false, this);
|
||||
}
|
||||
|
||||
saveUiState();
|
||||
}
|
||||
|
||||
public void moveToGrid(final Content content) {
|
||||
saveUiState();
|
||||
|
||||
setStateIsBeingRestored(true, this);
|
||||
|
||||
try {
|
||||
myManager.removeContent(content, false);
|
||||
getStateFor(content).assignTab(myLayoutSettings.getDefaultTab());
|
||||
getStateFor(content).setPlaceInGrid(myLayoutSettings.getDefaultGridPlace(content));
|
||||
myManager.addContent(content);
|
||||
}
|
||||
finally {
|
||||
setStateIsBeingRestored(false, this);
|
||||
}
|
||||
|
||||
select(content, true).doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
saveUiState();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public Project getProject() {
|
||||
return myProject;
|
||||
}
|
||||
@@ -1055,7 +1271,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
}
|
||||
|
||||
public boolean isHorizontalToolbar() {
|
||||
return myLayoutSettings.isToolbarHorizontal();
|
||||
return false;
|
||||
}
|
||||
|
||||
public ActionCallback select(final Content content, final boolean requestFocus) {
|
||||
@@ -1068,18 +1284,12 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
|
||||
|
||||
final ActionCallback result = new ActionCallback();
|
||||
if (grid.isDetached(content)) {
|
||||
if (requestFocus) {
|
||||
myTabs.select(info, false).doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
grid.select(content, requestFocus).notifyWhenDone(result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myTabs.select(info, false).doWhenDone(new Runnable() {
|
||||
public void run() {
|
||||
grid.select(content, requestFocus).notifyWhenDone(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1233,4 +1443,142 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private int findFreeWindow() {
|
||||
int i;
|
||||
for (i = 1; i < Integer.MAX_VALUE; i++) {
|
||||
if (!isUsed(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private boolean isUsed(int i) {
|
||||
for (RunnerContentUi child : myChildren) {
|
||||
if (child.getWindow() == i) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private DockManagerImpl getDockManager() {
|
||||
return (DockManagerImpl)DockManager.getInstance(myProject);
|
||||
}
|
||||
|
||||
class MyDragOutDelegate implements TabInfo.DragOutDelegate {
|
||||
private DragSession mySession;
|
||||
|
||||
@Override
|
||||
public void dragOutStarted(MouseEvent mouseEvent, TabInfo info) {
|
||||
final JComponent component = info.getComponent();
|
||||
final Content[] data = CONTENT_KEY.getData((DataProvider)component);
|
||||
final List<Content> contents = Arrays.asList(data);
|
||||
|
||||
storeDefaultIndices(data);
|
||||
|
||||
final Dimension size = info.getComponent().getSize();
|
||||
final Image image = myTabs.getComponentImage(info);
|
||||
if (component instanceof Grid) {
|
||||
info.setHidden(true);
|
||||
}
|
||||
|
||||
Presentation presentation = new Presentation(info.getText());
|
||||
presentation.setIcon(info.getIcon());
|
||||
mySession = getDockManager().createDragSession(mouseEvent, new DockableGrid(image, presentation,
|
||||
size,
|
||||
contents, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDragOut(MouseEvent event, TabInfo source) {
|
||||
mySession.process(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dragOutFinished(MouseEvent event, TabInfo source) {
|
||||
final Component component = event.getComponent();
|
||||
final IdeFrame window = UIUtil.getParentOfType(IdeFrame.class, component);
|
||||
if (window != null) {
|
||||
|
||||
}
|
||||
mySession.process(event);
|
||||
mySession = null;
|
||||
}
|
||||
}
|
||||
|
||||
class DockableGrid implements DockableContent<List<Content>> {
|
||||
final Image myImg;
|
||||
private Presentation myPresentation;
|
||||
private final Dimension myPreferredSize;
|
||||
private final List<Content> myContents;
|
||||
private final int myWindow;
|
||||
|
||||
public DockableGrid(Image img, Presentation presentation, final Dimension size, List<Content> contents, int window) {
|
||||
myImg = img;
|
||||
myPresentation = presentation;
|
||||
myPreferredSize = size;
|
||||
myContents = contents;
|
||||
myWindow = window;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Content> getKey() {
|
||||
return myContents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getPreviewImage() {
|
||||
return myImg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return myPreferredSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDockContainerType() {
|
||||
return DockableGridContainerFactory.TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Presentation getPresentation() {
|
||||
return myPresentation;
|
||||
}
|
||||
|
||||
public RunnerContentUi getRunnerUi() {
|
||||
return RunnerContentUi.this;
|
||||
}
|
||||
|
||||
public RunnerContentUi getOriginalRunnerUi() {
|
||||
return myOriginal != null ? myOriginal : RunnerContentUi.this;
|
||||
}
|
||||
|
||||
public List<Content> getContents() {
|
||||
return myContents;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
||||
public int getWindow() {
|
||||
return myWindow;
|
||||
}
|
||||
}
|
||||
|
||||
void fireContentOpened(Content content) {
|
||||
for (Listener each : myDockingListeners) {
|
||||
each.contentAdded(content);
|
||||
}
|
||||
}
|
||||
|
||||
void fireContentClosed(Content content) {
|
||||
for (Listener each : myDockingListeners) {
|
||||
each.contentRemoved(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.execution.ui.layout.LayoutAttractionPolicy;
|
||||
import com.intellij.execution.ui.layout.PlaceInGrid;
|
||||
import com.intellij.execution.ui.layout.Tab;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.content.Content;
|
||||
@@ -33,7 +34,8 @@ import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
public class RunnerLayout {
|
||||
|
||||
public static final Key<Integer> DEFAULT_INDEX = Key.create("RunnerLayoutDefaultIndex");
|
||||
public static final Key<Integer> DROP_INDEX = Key.create("RunnerLayoutDropIndex");
|
||||
private final String myID;
|
||||
|
||||
protected Map<String, ViewImpl> myViews = new HashMap<String, ViewImpl>();
|
||||
@@ -64,10 +66,6 @@ public class RunnerLayout {
|
||||
return tab;
|
||||
}
|
||||
|
||||
public TabImpl getDefaultTab() {
|
||||
return getOrCreateTab(0);
|
||||
}
|
||||
|
||||
private TabImpl createNewTab(final int index) {
|
||||
final TabImpl tab;
|
||||
|
||||
@@ -153,7 +151,9 @@ public class RunnerLayout {
|
||||
}
|
||||
|
||||
for (TabImpl eachTab : myTabs) {
|
||||
eachTab.write(parentNode);
|
||||
if (isUsed(eachTab)) {
|
||||
eachTab.write(parentNode);
|
||||
}
|
||||
}
|
||||
|
||||
parentNode.addContent(XmlSerializer.serialize(myGeneral));
|
||||
@@ -166,13 +166,13 @@ public class RunnerLayout {
|
||||
myViews.clear();
|
||||
|
||||
for (TabImpl each : myTabs) {
|
||||
final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getIndex());
|
||||
final TabImpl.Default defaultTab = getOrCreateDefaultTab(each.getDefaultIndex());
|
||||
each.copyFrom(defaultTab);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isToolbarHorizontal() {
|
||||
return myGeneral.horizontalToolbar;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setToolbarHorizontal(boolean horizontal) {
|
||||
|
||||
@@ -40,6 +40,10 @@ public class TabImpl extends AbstractTab implements Tab {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
public int getDefaultIndex() {
|
||||
return myDefaultIndex >= 0 ? myDefaultIndex : myIndex;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return myDisplayName;
|
||||
}
|
||||
@@ -52,6 +56,10 @@ public class TabImpl extends AbstractTab implements Tab {
|
||||
myIndex = index;
|
||||
}
|
||||
|
||||
public void setDefaultIndex(final int index) {
|
||||
myDefaultIndex = index;
|
||||
}
|
||||
|
||||
public void setDisplayName(final String displayName) {
|
||||
myDisplayName = displayName;
|
||||
}
|
||||
@@ -161,6 +169,7 @@ public class TabImpl extends AbstractTab implements Tab {
|
||||
|
||||
public Default(final int index, final String displayName, final Icon icon) {
|
||||
myIndex = index;
|
||||
myDefaultIndex = index;
|
||||
myDisplayName = displayName;
|
||||
myIcon = icon;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
package com.intellij.execution.ui.layout.impl;
|
||||
|
||||
import com.intellij.execution.ui.layout.GridCell;
|
||||
import com.intellij.execution.ui.layout.ViewContext;
|
||||
import com.intellij.openapi.actionSystem.ActionGroup;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
|
||||
public interface ViewContextEx extends ViewContext {
|
||||
RunnerLayout getLayoutSettings();
|
||||
|
||||
ActionGroup getCellPopupGroup(String place);
|
||||
|
||||
void doWhenInitialized(Runnable runnable);
|
||||
boolean isOriginal();
|
||||
|
||||
int getWindow();
|
||||
|
||||
ActionCallback detachTo(int window, GridCell cell);
|
||||
}
|
||||
@@ -31,16 +31,19 @@ public class ViewImpl implements View {
|
||||
|
||||
private Tab myTab;
|
||||
private int myTabIndex;
|
||||
|
||||
private int myWindow;
|
||||
|
||||
private PlaceInGrid myPlaceInGrid;
|
||||
|
||||
private boolean myMinimizedInGrid;
|
||||
|
||||
public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid) {
|
||||
public ViewImpl(String id, TabImpl tab, final PlaceInGrid placeInGrid, boolean minimizedInGrid, int window) {
|
||||
myID = id;
|
||||
myTab = tab;
|
||||
myPlaceInGrid = placeInGrid;
|
||||
myMinimizedInGrid = minimizedInGrid;
|
||||
myWindow = window;
|
||||
}
|
||||
|
||||
public ViewImpl(RunnerLayout settings, Element element) {
|
||||
@@ -94,6 +97,16 @@ public class ViewImpl implements View {
|
||||
myTabIndex = tabIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindow() {
|
||||
return myWindow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWindow(int windowNumber) {
|
||||
myWindow = windowNumber;
|
||||
}
|
||||
|
||||
public static class Default {
|
||||
|
||||
private final String myID;
|
||||
@@ -110,7 +123,7 @@ public class ViewImpl implements View {
|
||||
|
||||
public ViewImpl createView(RunnerLayout settings) {
|
||||
final TabImpl tab = myTabID == Integer.MAX_VALUE ? settings.createNewTab() : settings.getOrCreateTab(myTabID);
|
||||
return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid);
|
||||
return new ViewImpl(myID, tab, myPlaceInGrid, myMinimizedInGrid, 0);
|
||||
}
|
||||
|
||||
public PlaceInGrid getPlaceInGrid() {
|
||||
|
||||
@@ -32,6 +32,8 @@ import com.intellij.ui.ColoredListCellRenderer;
|
||||
import com.intellij.ui.SimpleTextAttributes;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.hash.*;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -39,6 +41,7 @@ import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -207,7 +210,7 @@ public class GotoRelatedFileAction extends AnAction {
|
||||
}
|
||||
}
|
||||
|
||||
List<GotoRelatedItem> items = new ArrayList<GotoRelatedItem>();
|
||||
Set<GotoRelatedItem> items = new HashSet<GotoRelatedItem> ();
|
||||
|
||||
for (GotoRelatedProvider provider : Extensions.getExtensions(GotoRelatedProvider.EP_NAME)) {
|
||||
items.addAll(provider.getItems(contextElement));
|
||||
@@ -215,7 +218,7 @@ public class GotoRelatedFileAction extends AnAction {
|
||||
items.addAll(provider.getItems(dataContext));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
return new ArrayList<GotoRelatedItem>(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+9
-1
@@ -48,6 +48,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.text.MessageFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -319,10 +320,17 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo
|
||||
@NonNls Properties props = new Properties();
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
Date date = new Date(calendar.getTimeInMillis());
|
||||
SimpleDateFormat sdfMonthNameShort = new SimpleDateFormat("MMM");
|
||||
SimpleDateFormat sdfMonthNameFull = new SimpleDateFormat("MMMM");
|
||||
SimpleDateFormat sdfYearFull = new SimpleDateFormat("yyyy");
|
||||
|
||||
props.setProperty("DATE", DateFormatUtil.formatDate(calendar.getTime()));
|
||||
props.setProperty("TIME", DateFormatUtil.formatTime(calendar.getTime()));
|
||||
props.setProperty("YEAR", Integer.toString(calendar.get(Calendar.YEAR)));
|
||||
props.setProperty("YEAR", sdfYearFull.format(date));
|
||||
props.setProperty("MONTH", getCalendarValue(calendar, Calendar.MONTH));
|
||||
props.setProperty("MONTH_NAME_SHORT", sdfMonthNameShort.format(date));
|
||||
props.setProperty("MONTH_NAME_FULL", sdfMonthNameFull.format(date));
|
||||
props.setProperty("DAY", getCalendarValue(calendar, Calendar.DAY_OF_MONTH));
|
||||
props.setProperty("HOUR", getCalendarValue(calendar, Calendar.HOUR_OF_DAY));
|
||||
props.setProperty("MINUTE", getCalendarValue(calendar, Calendar.MINUTE));
|
||||
|
||||
@@ -539,6 +539,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder {
|
||||
return null;
|
||||
}
|
||||
Object[] children = getTreeStructure().getChildElements(parent);
|
||||
Arrays.sort(children, getUi().getNodeDescriptorComparator());
|
||||
int idx = -1;
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
if (obj.equals(children[i])) {
|
||||
@@ -584,6 +585,7 @@ public abstract class TodoTreeBuilder extends AbstractTreeBuilder {
|
||||
return null;
|
||||
}
|
||||
Object[] children = getTreeStructure().getChildElements(parent);
|
||||
Arrays.sort(children, getUi().getNodeDescriptorComparator());
|
||||
int idx = -1;
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
if (obj.equals(children[i])) {
|
||||
|
||||
@@ -228,18 +228,20 @@ public class FileStructurePopup implements Disposable {
|
||||
for (ObjectWithWeight p : paths) {
|
||||
final Object last = ((TreePath)p.node).getLastPathComponent();
|
||||
final List<PsiElement> elements = new ArrayList<PsiElement>();
|
||||
FilteringTreeStructure.FilteringNode node =
|
||||
(FilteringTreeStructure.FilteringNode)((DefaultMutableTreeNode)last).getUserObject();
|
||||
while (node != null) {
|
||||
elements.add(getPsi(node));
|
||||
node = node.getParentNode();
|
||||
}
|
||||
final int size = ContainerUtil.intersection(parents, elements).size();
|
||||
if (size > max) {
|
||||
max = size;
|
||||
cur = p.node;
|
||||
} else if (size == max && size == parents.size()) {
|
||||
cur = p.node;
|
||||
final Object object = ((DefaultMutableTreeNode)last).getUserObject();
|
||||
if (object instanceof FilteringTreeStructure.FilteringNode) {
|
||||
FilteringTreeStructure.FilteringNode node = (FilteringTreeStructure.FilteringNode)object;
|
||||
while (node != null) {
|
||||
elements.add(getPsi(node));
|
||||
node = node.getParentNode();
|
||||
}
|
||||
final int size = ContainerUtil.intersection(parents, elements).size();
|
||||
if (size > max) {
|
||||
max = size;
|
||||
cur = p.node;
|
||||
} else if (size == max && size == parents.size()) {
|
||||
cur = p.node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
*/
|
||||
package com.intellij.psi.stubs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import com.intellij.util.io.UnsyncByteArrayInputStream;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
@@ -45,7 +46,7 @@ public class SerializedStubTree {
|
||||
}
|
||||
|
||||
public StubElement getStub() {
|
||||
return SerializationManager.getInstance().deserialize(new ByteArrayInputStream(myBytes));
|
||||
return SerializationManager.getInstance().deserialize(new UnsyncByteArrayInputStream(myBytes));
|
||||
}
|
||||
|
||||
public boolean equals(final Object that) {
|
||||
|
||||
@@ -3570,6 +3570,10 @@ public class AbstractTreeUi {
|
||||
}
|
||||
}
|
||||
|
||||
public Comparator getNodeDescriptorComparator() {
|
||||
return myNodeDescriptorComparator;
|
||||
}
|
||||
|
||||
private void disposeNode(DefaultMutableTreeNode node) {
|
||||
TreeNode parent = node.getParent();
|
||||
if (parent instanceof DefaultMutableTreeNode) {
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.intellij.notification;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
import com.intellij.openapi.ui.popup.JBPopupAdapter;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -97,6 +99,11 @@ public class Notification {
|
||||
|
||||
public void expire() {
|
||||
NotificationsManager.getNotificationsManager().expire(this);
|
||||
hideBalloon();
|
||||
myExpired = true;
|
||||
}
|
||||
|
||||
public void hideBalloon() {
|
||||
if (myBalloonRef != null) {
|
||||
final Balloon balloon = myBalloonRef.get();
|
||||
if (balloon != null) {
|
||||
@@ -104,15 +111,20 @@ public class Notification {
|
||||
}
|
||||
myBalloonRef = null;
|
||||
}
|
||||
myExpired = true;
|
||||
}
|
||||
|
||||
public void setBalloon(@Nullable final Balloon balloon) {
|
||||
if (balloon != null) {
|
||||
myBalloonRef = new WeakReference<Balloon>(balloon);
|
||||
} else {
|
||||
myBalloonRef = null;
|
||||
}
|
||||
public void setBalloon(@NotNull final Balloon balloon) {
|
||||
hideBalloon();
|
||||
myBalloonRef = new WeakReference<Balloon>(balloon);
|
||||
balloon.addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
WeakReference<Balloon> ref = myBalloonRef;
|
||||
if (ref != null && ref.get() == balloon) {
|
||||
myBalloonRef = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -272,6 +272,17 @@ public class TableScrollingUtil {
|
||||
moveEnd(list);
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), list);
|
||||
|
||||
new AnAction() {
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
moveHome(list);
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0)), list);
|
||||
new AnAction() {
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
moveEnd(list);
|
||||
}
|
||||
}.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0)), list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface DockContainer extends Disposable, Activatable {
|
||||
RelativeRectangle getAcceptArea();
|
||||
boolean canAccept(DockableContent content, RelativePoint point);
|
||||
|
||||
JComponent getComponent();
|
||||
JComponent getContainerComponent();
|
||||
|
||||
void add(DockableContent content, RelativePoint dropTarget);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.jdom.Element;
|
||||
|
||||
public interface DockContainerFactory extends Disposable {
|
||||
|
||||
DockContainer createContainer();
|
||||
DockContainer createContainer(DockableContent content);
|
||||
|
||||
interface Persistent extends DockContainerFactory {
|
||||
|
||||
|
||||
@@ -22,12 +22,18 @@ public interface TabsListener {
|
||||
|
||||
void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection);
|
||||
|
||||
void tabsMoved();
|
||||
|
||||
class Adapter implements TabsListener {
|
||||
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
|
||||
}
|
||||
|
||||
public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tabsMoved() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
class ActionPanel extends NonOpaquePanel {
|
||||
public class ActionPanel extends NonOpaquePanel {
|
||||
|
||||
private final ActionGroup myGroup;
|
||||
private final List<ActionButton> myButtons = new ArrayList<ActionButton>();
|
||||
|
||||
@@ -253,6 +253,9 @@ class DragHelper extends MouseDragHelper {
|
||||
myDragRec = null;
|
||||
|
||||
myTabs.resetTabsCache();
|
||||
if (!willDragOutStart) {
|
||||
myTabs.fireTabsMoved();
|
||||
}
|
||||
myTabs.relayout(true, false);
|
||||
|
||||
myTabs.revalidate();
|
||||
|
||||
@@ -163,7 +163,7 @@ public class JBTabsImpl extends JComponent
|
||||
|
||||
private boolean myOwnSwitchProvider = true;
|
||||
private SwitchProvider mySwitchDelegate;
|
||||
private TabInfo myDropInfo;
|
||||
protected TabInfo myDropInfo;
|
||||
private int myDropInfoIndex;
|
||||
|
||||
private TabInfo myOldSelection;
|
||||
@@ -629,7 +629,7 @@ public class JBTabsImpl extends JComponent
|
||||
}
|
||||
|
||||
info.getChangeSupport().addPropertyChangeListener(this);
|
||||
final TabLabel label = new TabLabel(this, info);
|
||||
final TabLabel label = createTabLabel(info);
|
||||
myInfo2Label.put(info, label);
|
||||
|
||||
if (!isDropTarget) {
|
||||
@@ -674,6 +674,9 @@ public class JBTabsImpl extends JComponent
|
||||
return info;
|
||||
}
|
||||
|
||||
protected TabLabel createTabLabel(TabInfo info) {
|
||||
return new TabLabel(this, info);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TabInfo addTab(TabInfo info) {
|
||||
@@ -832,6 +835,14 @@ public class JBTabsImpl extends JComponent
|
||||
}
|
||||
}
|
||||
|
||||
void fireTabsMoved() {
|
||||
for (TabsListener eachListener : myTabListeners) {
|
||||
if (eachListener != null) {
|
||||
eachListener.tabsMoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ActionCallback requestFocus(final JComponent toFocus) {
|
||||
if (toFocus == null) return new ActionCallback.Done();
|
||||
|
||||
@@ -1745,17 +1756,18 @@ public class JBTabsImpl extends JComponent
|
||||
return myInfo2Label.get(getSelectedInfo());
|
||||
}
|
||||
|
||||
static class ShapeInfo {
|
||||
ShapeTransform path;
|
||||
ShapeTransform fillPath;
|
||||
ShapeTransform labelPath;
|
||||
int labelBottomY;
|
||||
int labelTopY;
|
||||
int labelLeftX;
|
||||
int labelRightX;
|
||||
Insets insets;
|
||||
Color from;
|
||||
Color to;
|
||||
protected static class ShapeInfo {
|
||||
public ShapeInfo() {}
|
||||
public ShapeTransform path;
|
||||
public ShapeTransform fillPath;
|
||||
public ShapeTransform labelPath;
|
||||
public int labelBottomY;
|
||||
public int labelTopY;
|
||||
public int labelLeftX;
|
||||
public int labelRightX;
|
||||
public Insets insets;
|
||||
public Color from;
|
||||
public Color to;
|
||||
}
|
||||
|
||||
|
||||
@@ -2977,7 +2989,7 @@ public class JBTabsImpl extends JComponent
|
||||
}
|
||||
}
|
||||
|
||||
public static Rectangle layout(JComponent c, Rectangle bounds) {
|
||||
public Rectangle layout(JComponent c, Rectangle bounds) {
|
||||
final Rectangle now = c.getBounds();
|
||||
if (!bounds.equals(now)) {
|
||||
c.setBounds(bounds);
|
||||
@@ -2987,7 +2999,7 @@ public class JBTabsImpl extends JComponent
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public static Rectangle layout(JComponent c, int x, int y, int width, int height) {
|
||||
public Rectangle layout(JComponent c, int x, int y, int width, int height) {
|
||||
return layout(c, new Rectangle(x, y, width, height));
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class TabLabel extends JPanel {
|
||||
private final SimpleColoredComponent myLabel = new SimpleColoredComponent() {
|
||||
protected final SimpleColoredComponent myLabel = new SimpleColoredComponent() {
|
||||
@Override
|
||||
protected boolean shouldDrawMacShadow() {
|
||||
return SystemInfo.isMac;
|
||||
@@ -54,7 +54,7 @@ public class TabLabel extends JPanel {
|
||||
private Icon myOverlayedIcon;
|
||||
|
||||
private final TabInfo myInfo;
|
||||
private ActionPanel myActionPanel;
|
||||
protected ActionPanel myActionPanel;
|
||||
private boolean myCentered;
|
||||
|
||||
private final Wrapper myLabelPlaceholder = new Wrapper();
|
||||
@@ -224,7 +224,7 @@ public class TabLabel extends JPanel {
|
||||
});
|
||||
}
|
||||
|
||||
private int getNonSelectedOffset() {
|
||||
protected int getNonSelectedOffset() {
|
||||
if (myTabs.isEditorTabs()) {
|
||||
int offset = (TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2);
|
||||
if (myTabs.isSingleRow()) {
|
||||
@@ -237,7 +237,7 @@ public class TabLabel extends JPanel {
|
||||
return 2;
|
||||
}
|
||||
|
||||
private int getSelectedOffset() {
|
||||
protected int getSelectedOffset() {
|
||||
return myTabs.isEditorTabs() ? -(TabsUtil.ACTIVE_TAB_UNDERLINE_HEIGHT / 2) + 1 : 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,11 @@ public abstract class UndoRedoAction extends DumbAwareAction {
|
||||
}
|
||||
|
||||
UndoManager undoManager = getUndoManager(editor, dataContext);
|
||||
presentation.setEnabled(undoManager != null && isAvailable(editor, undoManager));
|
||||
if (undoManager == null) {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
presentation.setEnabled(isAvailable(editor, undoManager));
|
||||
|
||||
Pair<String, String> pair = getActionNameAndDescription(editor, undoManager);
|
||||
|
||||
|
||||
@@ -162,13 +162,13 @@ public class SocketLock {
|
||||
try {
|
||||
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
|
||||
out.writeUTF(ACTIVATE_COMMAND + StringUtil.join(args, "\0"));
|
||||
out.flush();
|
||||
String response = in.readUTF();
|
||||
if (response.equals("ok")) {
|
||||
return ActivateStatus.ACTIVATED;
|
||||
}
|
||||
}
|
||||
catch(IOException e) {
|
||||
|
||||
}
|
||||
return ActivateStatus.CANNOT_ACTIVATE;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,17 @@ public class StartupUtil {
|
||||
}
|
||||
|
||||
if (activateStatus != SocketLock.ActivateStatus.NO_INSTANCE) {
|
||||
showError("Error", "Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.");
|
||||
if (isHeadless()) { //team server inspections
|
||||
System.out.println("Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() + " can be run at a time.");
|
||||
return false;
|
||||
}
|
||||
if (activateStatus == SocketLock.ActivateStatus.CANNOT_ACTIVATE) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
"Only one instance of " + ApplicationNamesInfo.getInstance().getFullProductName() +
|
||||
" can be run at a time.",
|
||||
"Error",
|
||||
JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,7 @@ public class EventLog implements Notifications {
|
||||
mainText += content;
|
||||
}
|
||||
|
||||
mainText = StringUtil.replace(mainText, " ", " ");
|
||||
int nlIndex = eolIndex(mainText);
|
||||
if (nlIndex >= 0) {
|
||||
mainText = mainText.substring(0, nlIndex);
|
||||
@@ -329,6 +330,7 @@ public class EventLog implements Notifications {
|
||||
group.add(new DumbAwareAction("Mark all as read", "Mark all unread notifications as read", IconLoader.getIcon("/general/reset.png")) {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
if (project.isDisposed()) return;
|
||||
e.getPresentation().setEnabled(!getProjectComponent(project).myProjectModel.getNotifications().isEmpty());
|
||||
}
|
||||
|
||||
|
||||
-7
@@ -314,13 +314,6 @@ public class NotificationsManagerImpl extends NotificationsManager implements No
|
||||
.setHideOnKeyOutside(hideOnClickOutside).setHideOnFrameResize(false);
|
||||
|
||||
final Balloon balloon = builder.createBalloon();
|
||||
balloon.addListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
notification.setBalloon(null);
|
||||
}
|
||||
});
|
||||
|
||||
notification.setBalloon(balloon);
|
||||
return balloon;
|
||||
}
|
||||
|
||||
+7
-1
@@ -57,6 +57,11 @@ public class CommandProcessorImpl extends CommandProcessorEx {
|
||||
myUndoConfirmationPolicy = undoConfirmationPolicy;
|
||||
myDocument = document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "'" + myName + "', group: '" + myGroupId + "'";
|
||||
}
|
||||
}
|
||||
|
||||
private CommandDescriptor myCurrentCommand = null;
|
||||
@@ -219,7 +224,8 @@ public class CommandProcessorImpl extends CommandProcessorEx {
|
||||
}
|
||||
|
||||
public void leaveModal() {
|
||||
CommandLog.LOG.assertTrue(myCurrentCommand == null);
|
||||
CommandLog.LOG.assertTrue(myCurrentCommand == null, "Command must not run: " + String.valueOf(myCurrentCommand));
|
||||
|
||||
myCurrentCommand = myInterruptedCommands.pop();
|
||||
if (myCurrentCommand != null) {
|
||||
fireCommandStarted();
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.ui.docking.DockContainer;
|
||||
import com.intellij.ui.docking.DockContainerFactory;
|
||||
import com.intellij.ui.docking.DockManager;
|
||||
import com.intellij.ui.docking.DockableContent;
|
||||
import org.jdom.Element;
|
||||
|
||||
public class DockableEditorContainerFactory implements DockContainerFactory.Persistent {
|
||||
@@ -39,7 +40,7 @@ public class DockableEditorContainerFactory implements DockContainerFactory.Pers
|
||||
}
|
||||
|
||||
@Override
|
||||
public DockContainer createContainer() {
|
||||
public DockContainer createContainer(DockableContent content) {
|
||||
return createContainer(false);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -187,7 +187,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent() {
|
||||
public JComponent getContainerComponent() {
|
||||
return mySplitters;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class DockableEditorTabbedContainer implements DockContainer.Persistent {
|
||||
}
|
||||
|
||||
public void close(VirtualFile file) {
|
||||
mySplitters.getCurrentWindow().closeFile(file);
|
||||
mySplitters.closeFile(file, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -586,6 +586,31 @@ public class EditorsSplitters extends JPanel {
|
||||
return null;
|
||||
}
|
||||
|
||||
void closeFile(VirtualFile file, boolean moveFocus) {
|
||||
final List<EditorWindow> windows = findWindows(file);
|
||||
if (!windows.isEmpty()) {
|
||||
final VirtualFile nextFile = findNextFile(file);
|
||||
for (final EditorWindow window : windows) {
|
||||
LOG.assertTrue(window.getSelectedEditor() != null);
|
||||
window.closeFile(file, false, moveFocus);
|
||||
if (window.getTabCount() == 0 && nextFile != null) {
|
||||
EditorWithProviderComposite newComposite = myManager.newEditorComposite(nextFile);
|
||||
window.setEditor(newComposite, moveFocus); // newComposite can be null
|
||||
}
|
||||
}
|
||||
// cleanup windows with no tabs
|
||||
for (final EditorWindow window : windows) {
|
||||
if (window.isDisposed()) {
|
||||
// call to window.unsplit() which might make its sibling disposed
|
||||
continue;
|
||||
}
|
||||
if (window.getTabCount() == 0) {
|
||||
window.unsplit(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class MyFocusTraversalPolicy extends IdeFocusTraversalPolicy {
|
||||
public final Component getDefaultComponentImpl(final Container focusCycleRoot) {
|
||||
if (myCurrentWindow != null) {
|
||||
|
||||
+3
-24
@@ -556,33 +556,12 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
|
||||
assertDispatchThread();
|
||||
runChange(new FileEditorManagerChange() {
|
||||
public void run(EditorsSplitters splitters) {
|
||||
final List<EditorWindow> windows = splitters.findWindows(file);
|
||||
if (!windows.isEmpty()) {
|
||||
final VirtualFile nextFile = splitters.findNextFile(file);
|
||||
for (final EditorWindow window : windows) {
|
||||
LOG.assertTrue(window.getSelectedEditor() != null);
|
||||
window.closeFile(file, false, moveFocus);
|
||||
if (window.getTabCount() == 0 && nextFile != null) {
|
||||
EditorWithProviderComposite newComposite = newEditorComposite(nextFile);
|
||||
window.setEditor(newComposite, moveFocus); // newComposite can be null
|
||||
}
|
||||
}
|
||||
// cleanup windows with no tabs
|
||||
for (final EditorWindow window : windows) {
|
||||
if (window.isDisposed()) {
|
||||
// call to window.unsplit() which might make its sibling disposed
|
||||
continue;
|
||||
}
|
||||
if (window.getTabCount() == 0) {
|
||||
window.unsplit(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
splitters.closeFile(file, moveFocus);
|
||||
}
|
||||
}, closeAllCopies ? null : getActiveSplitters(true).getResult());
|
||||
}
|
||||
|
||||
//-------------------------------------- Open File ----------------------------------------
|
||||
//-------------------------------------- Open File ----------------------------------------
|
||||
|
||||
@NotNull
|
||||
public Pair<FileEditor[], FileEditorProvider[]> openFileWithProviders(@NotNull final VirtualFile file,
|
||||
@@ -865,7 +844,7 @@ public class FileEditorManagerImpl extends FileEditorManagerEx implements Projec
|
||||
|
||||
|
||||
@Nullable
|
||||
private EditorWithProviderComposite newEditorComposite(final VirtualFile file) {
|
||||
EditorWithProviderComposite newEditorComposite(final VirtualFile file) {
|
||||
if (file == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+2
-2
@@ -220,11 +220,11 @@ public class GlassPaneDialogWrapperPeer extends DialogWrapperPeer implements Foc
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return myDialog.isVisible();
|
||||
return myDialog != null && myDialog.isVisible();
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return myDialog.isShowing();
|
||||
return myDialog != null && myDialog.isShowing();
|
||||
}
|
||||
|
||||
public void setSize(final int width, final int height) {
|
||||
|
||||
+5
-3
@@ -188,6 +188,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
return ioFile;
|
||||
}
|
||||
|
||||
// todo[r.sh] use NIO2 API after migration to JDK 7
|
||||
// returns -1 if could not get attributes
|
||||
@MagicConstant(flags = {BA_EXISTS, BA_REGULAR, BA_DIRECTORY, BA_HIDDEN})
|
||||
private static int getBooleanAttributes(@NotNull File f) {
|
||||
@@ -196,8 +197,7 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
Object flags = JAVA_IO_FILESYSTEM_GET_BOOLEAN_ATTRIBUTES_METHOD.invoke(JAVA_IO_FILESYSTEM, f);
|
||||
return ((Integer)flags).intValue();
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
catch (Exception ignored) { }
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -535,7 +535,9 @@ public abstract class LocalFileSystemBase extends LocalFileSystem {
|
||||
public byte[] contentsToByteArray(@NotNull final VirtualFile file) throws IOException {
|
||||
final FileInputStream stream = new FileInputStream(convertToIOFileAndCheck(file));
|
||||
try {
|
||||
return FileUtil.loadBytes(stream, (int)file.getLength());
|
||||
final int length = (int)file.getLength();
|
||||
assert length >= 0 : file;
|
||||
return FileUtil.loadBytes(stream, length);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
|
||||
+4
-2
@@ -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.
|
||||
@@ -508,7 +508,9 @@ public class PersistentFS extends ManagingFS implements ApplicationComponent {
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return FileUtil.loadBytes(contentStream, (int)file.getLength());
|
||||
final int length = (int)file.getLength();
|
||||
assert length >= 0 : file;
|
||||
return FileUtil.loadBytes(contentStream, length);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw FSRecords.handleError(e);
|
||||
|
||||
@@ -122,7 +122,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
|
||||
|
||||
@Override
|
||||
public IdeFrame getIdeFrame(DockContainer container) {
|
||||
Component parent = UIUtil.findUltimateParent(container.getComponent());
|
||||
Component parent = UIUtil.findUltimateParent(container.getContainerComponent());
|
||||
if (parent instanceof IdeFrame) {
|
||||
return (IdeFrame)parent;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
|
||||
if (c == null) return null;
|
||||
|
||||
for (DockContainer eachContainer : myContainers) {
|
||||
if (SwingUtilities.isDescendingFrom(c, eachContainer.getComponent())) {
|
||||
if (SwingUtilities.isDescendingFrom(c, eachContainer.getContainerComponent())) {
|
||||
return eachContainer;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
|
||||
if (parent == null) return null;
|
||||
|
||||
for (DockContainer eachContainer : myContainers) {
|
||||
if (parent == UIUtil.findUltimateParent(eachContainer.getComponent())) {
|
||||
if (parent == UIUtil.findUltimateParent(eachContainer.getContainerComponent())) {
|
||||
return eachContainer;
|
||||
}
|
||||
}
|
||||
@@ -354,8 +354,8 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
|
||||
return myFactories.get(type);
|
||||
}
|
||||
|
||||
private void createNewDockContainerFor(DockableContent content, RelativePoint point) {
|
||||
DockContainer container = getFactory(content.getDockContainerType()).createContainer();
|
||||
public void createNewDockContainerFor(DockableContent content, RelativePoint point) {
|
||||
DockContainer container = getFactory(content.getDockContainerType()).createContainer(content);
|
||||
register(container);
|
||||
|
||||
final DockWindow window = createWindowFor(null, container);
|
||||
@@ -424,7 +424,7 @@ public class DockManagerImpl extends DockManager implements PersistentStateCompo
|
||||
center.add(myNorthPanel, BorderLayout.NORTH);
|
||||
|
||||
myDockContentUiContainer = new NonOpaquePanel(new BorderLayout());
|
||||
myDockContentUiContainer.add(myContainer.getComponent(), BorderLayout.CENTER);
|
||||
myDockContentUiContainer.add(myContainer.getContainerComponent(), BorderLayout.CENTER);
|
||||
center.add(myDockContentUiContainer, BorderLayout.CENTER);
|
||||
|
||||
myUiContainer.add(center, BorderLayout.CENTER);
|
||||
|
||||
@@ -227,7 +227,7 @@ group.reopen.mac.text=Open _Recent
|
||||
group.$LRU.description=List of recently opened projects
|
||||
action.CloseProject.text=Close Pro_ject
|
||||
action.CloseProject.description=Close current project
|
||||
action.ShowSettings.text=Se_ttings
|
||||
action.ShowSettings.text=Se_ttings...
|
||||
action.ShowSettings.description=Configure application settings
|
||||
action.ShowProjectStructureSettings.text=Pro_ject Structure...
|
||||
action.ShowProjectStructureSettings.description=Configure project structure
|
||||
@@ -1147,7 +1147,7 @@ group.EditSelectGroup.text=Editor Select Actions
|
||||
group.EditCreateDeleteGroup.text=Editor Create/Delete Actions
|
||||
group.CutCopyPasteGroup.text=Cut/Copy/Paste Actions
|
||||
group.EditSelectWordGroup.text=Select Word Actions
|
||||
group.EditBookmarksGroup.text=Bookmarks
|
||||
group.EditBookmarksGroup.text=Boo_kmarks
|
||||
group.OpenProjectGroup.text=Open Project Actions
|
||||
group.EditSmartGroup.text=Edit Code Actions
|
||||
group.ProjectViewGroup.text=Project View Actions
|
||||
|
||||
@@ -133,6 +133,8 @@ tests.passed.with.warnings.message=Tests passed (with warnings)
|
||||
junit.run.hide.passed.action.name=Hide Passed
|
||||
junit.run.hide.passed.action.description=Hide passed tests
|
||||
junit.runing.info.track.test.action.name=Track Running Test
|
||||
junit.runing.info.sort.alphabetically.action.name=Sort Alphabetically
|
||||
junit.runing.info.sort.alphabetically.action.description=Sort tests or suites alphabetically
|
||||
junit.runing.info.track.test.action.description=Select currently running test in tree
|
||||
junit.runing.info.collapse.test.action.name=Collapse all test suites
|
||||
junit.runing.info.expand.test.action.name=Expand all test suites
|
||||
|
||||
@@ -728,18 +728,14 @@
|
||||
</group>
|
||||
|
||||
<group id="RunnerLayoutActions">
|
||||
<group id="Runner.Layout" icon="/debugger/restoreLayout.png" popup="true">
|
||||
<action id="Runner.RestoreLayout" class="com.intellij.execution.ui.layout.actions.RestoreLayoutAction"/>
|
||||
<action id="Runner.ToggleToolbarLayout" class="com.intellij.execution.ui.layout.actions.ToggleToolbarLayoutAction"/>
|
||||
<group id="Runner.Layout" icon="/debugger/restoreLayout.png">
|
||||
<action id="Runner.RestoreLayout" class="com.intellij.execution.ui.layout.actions.RestoreLayoutAction"
|
||||
icon="/debugger/restoreLayout.png"/>
|
||||
<!--action id="Runner.ToggleToolbarLayout" class="com.intellij.execution.ui.layout.actions.ToggleToolbarLayoutAction"/-->
|
||||
</group>
|
||||
|
||||
|
||||
<group id="Runner.View.Popup">
|
||||
<action id="Runner.MoveViewToGrid" class="com.intellij.execution.ui.layout.actions.MoveToGridAction" icon="/debugger/toGrid.png"/>
|
||||
<action id="Runner.MoveViewToTab" class="com.intellij.execution.ui.layout.actions.MoveToTabAction" icon="/debugger/toTab.png"/>
|
||||
<action id="Runner.DetachCell" class="com.intellij.execution.ui.layout.actions.DetachCellAction" icon="/debugger/detach.png"/>
|
||||
<action id="Runner.AttachCell" class="com.intellij.execution.ui.layout.actions.AttachCellAction" icon="/debugger/attach.png"/>
|
||||
<separator/>
|
||||
<action id="Runner.MinimizeView" class="com.intellij.execution.ui.layout.actions.MinimizeViewAction" icon="/actions/minimize.png"/>
|
||||
<separator/>
|
||||
<action id="Runner.CloseView" class="com.intellij.execution.ui.layout.actions.CloseViewAction" icon="/actions/cross.png"/>
|
||||
@@ -753,10 +749,6 @@
|
||||
|
||||
|
||||
<group id="Runner.View.Toolbar">
|
||||
<reference ref="Runner.MoveViewToGrid"/>
|
||||
<reference ref="Runner.MoveViewToTab"/>
|
||||
<reference ref="Runner.DetachCell"/>
|
||||
<reference ref="Runner.AttachCell"/>
|
||||
<reference ref="Runner.MinimizeView"/>
|
||||
<reference ref="Runner.CloseView"/>
|
||||
</group>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.notification;
|
||||
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
class EventLogTest extends UsefulTestCase {
|
||||
|
||||
public void testNbsp() {
|
||||
def entry = EventLog.formatForLog(new Notification("xxx", "Title", "Hello world", NotificationType.ERROR))
|
||||
assert entry.message == 'Title: Hello world'
|
||||
}
|
||||
|
||||
}
|
||||
+580
@@ -0,0 +1,580 @@
|
||||
package com.intellij.openapi.fileEditor;
|
||||
|
||||
import com.intellij.codeStyle.CodeStyleFacade;
|
||||
import com.intellij.codeStyle.DefaultCodeStyleFacade;
|
||||
import com.intellij.mock.MockCommandProcessor;
|
||||
import com.intellij.mock.MockEditorFactory;
|
||||
import com.intellij.mock.MockVirtualFile;
|
||||
import com.intellij.mock.MockVirtualFileManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
|
||||
import com.intellij.openapi.fileTypes.*;
|
||||
import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl;
|
||||
import com.intellij.openapi.fileTypes.impl.InternalFileTypeFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectLocator;
|
||||
import com.intellij.openapi.project.impl.DefaultProjectLocator;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.testFramework.MockSchemesManagerFactory;
|
||||
import com.intellij.testFramework.PlatformLiteFixture;
|
||||
import com.intellij.util.LocalTimeCounter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.CharArrayWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class FileDocumentManagerImplTest extends PlatformLiteFixture {
|
||||
private MyFileDocumentManagerImpl myDocumentManager;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
initApplication();
|
||||
registerExtension(FileTypeFactory.FILE_TYPE_FACTORY_EP, new InternalFileTypeFactory());
|
||||
registerExtensionPoint(FileDocumentSynchronizationVetoer.EP_NAME, FileDocumentSynchronizationVetoer.class);
|
||||
getApplication().registerService(CommandProcessor.class, new MyMockCommandProcessor());
|
||||
getApplication().registerService(CodeStyleFacade.class, new DefaultCodeStyleFacade());
|
||||
getApplication().registerService(ProjectLocator.class, new DefaultProjectLocator());
|
||||
|
||||
MockEditorFactory editorFactory = new MockEditorFactory();
|
||||
getApplication().registerService(EditorFactory.class, editorFactory);
|
||||
final LanguageFileType[] fileType = {null};
|
||||
getApplication().addComponent(FileTypeManager.class, new FileTypeManagerImpl(null, new MockSchemesManagerFactory()){
|
||||
@NotNull
|
||||
@Override
|
||||
public FileType getFileTypeByFileName(@NotNull String fileName) {
|
||||
return fileType[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileType getFileTypeByFile(@NotNull VirtualFile file) {
|
||||
return fileType[0];
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FileType getFileTypeByExtension(@NotNull String extension) {
|
||||
return fileType[0];
|
||||
}
|
||||
});
|
||||
|
||||
fileType[0] = StdFileTypes.JAVA;
|
||||
|
||||
getApplication().getComponent(FileTypeManager.class);
|
||||
myDocumentManager = new MyFileDocumentManagerImpl();
|
||||
getApplication().registerService(FileDocumentManager.class, myDocumentManager);
|
||||
}
|
||||
|
||||
public void testGetCachedDocument_Cached() throws Exception {
|
||||
final Document cachedDocument = myDocumentManager.getCachedDocument(new MockVirtualFile("test.txt"));
|
||||
assertNull(cachedDocument);
|
||||
}
|
||||
|
||||
public void testGetCachedDocument_NotCached() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final Document document = myDocumentManager.getDocument(file);
|
||||
|
||||
assertSame(myDocumentManager.getCachedDocument(file), document);
|
||||
}
|
||||
|
||||
public void testGetDocument_CreateNew() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final Document document = myDocumentManager.getDocument(file);
|
||||
assertNotNull(document);
|
||||
assertEquals("test", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
assertEquals(file.isWritable(), document.isWritable());
|
||||
}
|
||||
|
||||
public void testGetDocument_CreateNew_ReadOnly() throws Exception {
|
||||
final MockVirtualFile file = newTextFile();
|
||||
file.setWritable(false);
|
||||
final Document document = myDocumentManager.getDocument(file);
|
||||
assertNotNull(document);
|
||||
assertEquals("test", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
assertEquals(file.isWritable(), document.isWritable());
|
||||
}
|
||||
|
||||
public void testGetDocument_ReturnCachedValueTwice() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final Document document = myDocumentManager.getDocument(file);
|
||||
assertNotNull(document);
|
||||
assertEquals("test", document.getText());
|
||||
|
||||
final Document document2 = myDocumentManager.getDocument(file);
|
||||
assertSame(document2, document);
|
||||
}
|
||||
|
||||
public void testGetDocument_CreatesNewAfterGced() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
int idCode = System.identityHashCode(document);
|
||||
//noinspection UnusedAssignment
|
||||
document = null;
|
||||
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
document = myDocumentManager.getDocument(file);
|
||||
assertTrue(idCode != System.identityHashCode(document));
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_NoDocuments() throws Exception {
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(0, unsavedDocuments.length);
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_CreatedDocument() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
myDocumentManager.getDocument(file);
|
||||
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(0, unsavedDocuments.length);
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_ModifiedDocument() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(1, unsavedDocuments.length);
|
||||
assertSame(document, unsavedDocuments[0]);
|
||||
assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray()));
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_afterSaveAllDocuments() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
myDocumentManager.saveAllDocuments();
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(0, unsavedDocuments.length);
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_afterSaveDocuments() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
myDocumentManager.saveDocument(document);
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(0, unsavedDocuments.length);
|
||||
}
|
||||
|
||||
private static MockVirtualFile newTextFile() {
|
||||
return new MockVirtualFile("test.txt", "test");
|
||||
}
|
||||
|
||||
public void testGetUnsavedDocuments_afterSaveDocumentWithProblems() throws Exception {
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test") {
|
||||
@Override
|
||||
@NotNull
|
||||
public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
|
||||
throw new IOException("");
|
||||
}
|
||||
};
|
||||
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
myDocumentManager.saveDocument(document);
|
||||
|
||||
assertNotNull(myDocumentManager.myExceptionOnSave);
|
||||
|
||||
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
|
||||
assertEquals(1, unsavedDocuments.length);
|
||||
assertSame(document, unsavedDocuments[0]);
|
||||
assertTrue(Arrays.equals("test".getBytes(), file.contentsToByteArray()));
|
||||
}
|
||||
|
||||
public void testUnsavedDocument_DontGc() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
int idCode = System.identityHashCode(document);
|
||||
//noinspection UnusedAssignment
|
||||
document = null;
|
||||
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
document = myDocumentManager.getDocument(file);
|
||||
assertEquals(idCode, System.identityHashCode(document));
|
||||
}
|
||||
|
||||
public void testUnsavedDocument_GcAfterSave() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
int idCode = System.identityHashCode(document);
|
||||
//noinspection UnusedAssignment
|
||||
document = null;
|
||||
|
||||
myDocumentManager.saveAllDocuments();
|
||||
|
||||
System.gc();
|
||||
System.gc();
|
||||
|
||||
document = myDocumentManager.getDocument(file);
|
||||
assertTrue(idCode != System.identityHashCode(document));
|
||||
}
|
||||
|
||||
public void testSaveDocument_DocumentWasntChanged() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final long stamp = file.getModificationStamp();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
myDocumentManager.saveDocument(document);
|
||||
assertEquals(stamp, file.getModificationStamp());
|
||||
}
|
||||
|
||||
public void testSaveDocument_DocumentWasChanged() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final long stamp = file.getModificationStamp();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
myDocumentManager.saveDocument(document);
|
||||
assertTrue(stamp != file.getModificationStamp());
|
||||
assertEquals(document.getModificationStamp(), file.getModificationStamp());
|
||||
assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray()));
|
||||
}
|
||||
|
||||
public void testSaveAllDocuments_DocumentWasChanged() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
final long stamp = file.getModificationStamp();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
|
||||
myDocumentManager.saveAllDocuments();
|
||||
assertTrue(stamp != file.getModificationStamp());
|
||||
assertTrue(Arrays.equals("xxxtest".getBytes(), file.contentsToByteArray()));
|
||||
}
|
||||
|
||||
public void testGetFile() throws Exception {
|
||||
final VirtualFile file = newTextFile();
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
assertSame(file, myDocumentManager.getFile(document));
|
||||
}
|
||||
|
||||
public void testConvertSeparators() throws Exception {
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
assertEquals("test\ntest", document.getText());
|
||||
}
|
||||
|
||||
public void testRememberSeparators() throws Exception {
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
myDocumentManager.saveAllDocuments();
|
||||
assertTrue(Arrays.equals("xxxtest\rtest".getBytes(), file.contentsToByteArray()));
|
||||
}
|
||||
|
||||
public void testContentChanged_noDocument() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
file.setListener(myDocumentManager);
|
||||
file.setContent(null, "xxx", true);
|
||||
assertNull(myDocumentManager.getCachedDocument(file));
|
||||
}
|
||||
|
||||
public void testContentChanged_documentPresent() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
file.setListener(myDocumentManager);
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
file.setContent(null, "xxx", true);
|
||||
assertEquals("xxx", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
}
|
||||
|
||||
public void testContentChanged_ignoreEventsFromSelf() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
file.setListener(myDocumentManager);
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
file.setContent(myDocumentManager, "xxx", true);
|
||||
assertEquals("test\ntest", document.getText());
|
||||
}
|
||||
|
||||
public void testContentChanged_ignoreEventsFromSelfOnSave() throws Exception {
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest") {
|
||||
public Writer getWriter(final Object requestor, final long newModificationStamp) {
|
||||
final VirtualFile self = this;
|
||||
return new CharArrayWriter() {
|
||||
@Override
|
||||
public void close() {
|
||||
super.close();
|
||||
long oldStamp = getModificationStamp();
|
||||
setModificationStamp(newModificationStamp);
|
||||
setText(toString());
|
||||
myDocumentManager.contentsChanged(new VirtualFileEvent(requestor, self, null, oldStamp, getModificationStamp()));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "xxx");
|
||||
final long stamp = document.getModificationStamp();
|
||||
|
||||
myDocumentManager.saveAllDocuments();
|
||||
assertEquals(stamp, document.getModificationStamp());
|
||||
}
|
||||
|
||||
public void testContentChanged_reloadChangedDocument() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
|
||||
file.setListener(myDocumentManager);
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "zzz");
|
||||
|
||||
myDocumentManager.myReloadFromDisk = Boolean.TRUE;
|
||||
try {
|
||||
file.setContent(null, "xxx", true);
|
||||
|
||||
assertEquals("xxx", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
|
||||
}
|
||||
finally {
|
||||
myDocumentManager.myReloadFromDisk = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testContentChanged_dontreloadChangedDocument() throws Exception {
|
||||
final MockVirtualFile file = newTextFile();
|
||||
file.setListener(myDocumentManager);
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "zzz");
|
||||
|
||||
myDocumentManager.myReloadFromDisk = Boolean.FALSE;
|
||||
try {
|
||||
long oldDocumentStamp = document.getModificationStamp();
|
||||
|
||||
file.setContent(null, "xxx", true);
|
||||
|
||||
assertEquals("zzztest", document.getText());
|
||||
assertEquals(oldDocumentStamp, document.getModificationStamp());
|
||||
}
|
||||
finally {
|
||||
myDocumentManager.myReloadFromDisk = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaveDocument_dontSaveIfModStampEqualsToFile() throws Exception {
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test") {
|
||||
@NotNull
|
||||
@Override
|
||||
public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
|
||||
fail();
|
||||
throw new IOException();
|
||||
}
|
||||
};
|
||||
DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "zzz");
|
||||
document.setModificationStamp(file.getModificationStamp());
|
||||
|
||||
myDocumentManager.saveDocument(document);
|
||||
}
|
||||
|
||||
// this test requires changes in idea code to support MockFile as local file system file (FileDocumentManager.needsRefresh).
|
||||
// TODO: think how to test this functionality without hacking production code
|
||||
public void atestContentChanged_reloadChangedDocumentOnSave() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest") {
|
||||
@Override
|
||||
public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
|
||||
long oldStamp = getModificationStamp();
|
||||
setModificationStamp(LocalTimeCounter.currentTime());
|
||||
myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp()));
|
||||
}
|
||||
};
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "zzz");
|
||||
file.setContent(null, "xxx", false);
|
||||
|
||||
myDocumentManager.myReloadFromDisk = Boolean.TRUE;
|
||||
try {
|
||||
file.setActualTimeStamp(file.getTimeStamp() + 1);
|
||||
myDocumentManager.saveAllDocuments();
|
||||
long fileStamp = file.getModificationStamp();
|
||||
|
||||
assertEquals("xxx", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
assertEquals(file.getModificationStamp(), fileStamp);
|
||||
assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
|
||||
}
|
||||
finally {
|
||||
myDocumentManager.myReloadFromDisk = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testContentChanged_dontreloadChangedDocumentOnSave() throws Exception {
|
||||
final MockVirtualFile file = new MockVirtualFile("test.txt", "test") {
|
||||
@Override
|
||||
public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
|
||||
long oldStamp = getModificationStamp();
|
||||
setModificationStamp(LocalTimeCounter.currentTime());
|
||||
myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, oldStamp, getModificationStamp()));
|
||||
}
|
||||
};
|
||||
|
||||
myDocumentManager.myReloadFromDisk = Boolean.FALSE;
|
||||
try {
|
||||
Document document = myDocumentManager.getDocument(file);
|
||||
document.insertString(0, "zzz");
|
||||
long documentStamp = document.getModificationStamp();
|
||||
|
||||
file.setContent(null, "xxx", false);
|
||||
|
||||
file.setActualTimeStamp(file.getTimeStamp() + 1);
|
||||
myDocumentManager.saveAllDocuments();
|
||||
|
||||
assertEquals("zzztest", document.getText());
|
||||
assertEquals(file.getModificationStamp(), document.getModificationStamp());
|
||||
assertTrue(Arrays.equals("zzztest".getBytes(), file.contentsToByteArray()));
|
||||
assertEquals(documentStamp, document.getModificationStamp());
|
||||
}
|
||||
finally {
|
||||
myDocumentManager.myReloadFromDisk = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void testReplaceDocumentTestWithTheSameTest() throws Exception {
|
||||
final boolean[] canCallSave = {true};
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test") {
|
||||
@NotNull
|
||||
@Override
|
||||
public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
|
||||
if (!canCallSave[0]) fail();
|
||||
return super.getOutputStream(requestor, newModificationStamp, newTimeStamp);
|
||||
}
|
||||
};
|
||||
DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
|
||||
|
||||
String newText = "test text";
|
||||
document.replaceString(0, document.getTextLength(), newText);
|
||||
assertTrue(myDocumentManager.isDocumentUnsaved(document));
|
||||
myDocumentManager.saveDocument(document);
|
||||
|
||||
canCallSave[0] = false;
|
||||
|
||||
final long modificationStamp = document.getModificationStamp();
|
||||
|
||||
document.replaceString(0, document.getTextLength(), newText);
|
||||
|
||||
if (myDocumentManager.isDocumentUnsaved(document)) {
|
||||
assertTrue(document.getModificationStamp() > modificationStamp);
|
||||
}
|
||||
else {
|
||||
assertEquals(modificationStamp, document.getModificationStamp());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testExternalReplaceWithTheSameText() throws Exception{
|
||||
final long[] modificationStamp = new long[1];
|
||||
|
||||
modificationStamp[0] = 1;
|
||||
|
||||
final VirtualFile file = new MockVirtualFile("test.txt", "test") {
|
||||
@NotNull
|
||||
@Override
|
||||
public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
|
||||
fail();
|
||||
throw new IOException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getModificationStamp() {
|
||||
return modificationStamp[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
|
||||
myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, 1, 2));
|
||||
|
||||
}
|
||||
};
|
||||
DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
|
||||
|
||||
|
||||
modificationStamp[0] = 2;
|
||||
|
||||
file.refresh(false, false);
|
||||
|
||||
assertEquals(2, document.getModificationStamp());
|
||||
}
|
||||
|
||||
public static class MyFileDocumentManagerImpl extends FileDocumentManagerImpl {
|
||||
|
||||
public static final FileDocumentManagerListener[] LISTENERS = new FileDocumentManagerListener[0];
|
||||
|
||||
public IOException myExceptionOnSave;
|
||||
public Boolean myReloadFromDisk = null;
|
||||
|
||||
public MyFileDocumentManagerImpl() {
|
||||
super(new MockVirtualFileManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void reportErrorOnSave(IOException e) {
|
||||
myExceptionOnSave = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean askReloadFromDisk(VirtualFile file, Document document) {
|
||||
if (myReloadFromDisk == null){
|
||||
fail();
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
return myReloadFromDisk.booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected FileDocumentManagerListener[] getListeners() {
|
||||
return LISTENERS;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyMockCommandProcessor extends MockCommandProcessor {
|
||||
@Override
|
||||
public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(Project project,
|
||||
@NotNull Runnable runnable,
|
||||
String name,
|
||||
Object groupId,
|
||||
@NotNull UndoConfirmationPolicy confirmationPolicy,
|
||||
Document document) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(Project project,
|
||||
@NotNull Runnable runnable,
|
||||
String name,
|
||||
Object groupId,
|
||||
@NotNull UndoConfirmationPolicy confirmationPolicy) {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) {
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user