Merge remote-tracking branch 'origin/master'

This commit is contained in:
Roman Shevchenko
2014-12-04 11:44:58 +01:00
157 changed files with 2151 additions and 1191 deletions
@@ -1304,11 +1304,14 @@ public class BuildManager implements ApplicationComponent{
// this will ensure that we'll be able to obtain VirtualFile for existing roots
CompilerUtil.refreshOutputDirectories(rootFiles, false);
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final LocalFileSystem lfs = LocalFileSystem.getInstance();
final Set<VirtualFile> filesToRefresh = new HashSet<VirtualFile>();
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
if (project.isDisposed()) {
return;
}
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
for (File root : rootFiles) {
final VirtualFile rootFile = lfs.findFileByIoFile(root);
if (rootFile != null && fileIndex.isInSourceContent(rootFile)) {
@@ -27,19 +27,12 @@ import com.intellij.debugger.engine.evaluation.expression.Modifier;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.JdkVersionUtil;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
import com.intellij.util.PathsList;
import com.sun.jdi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.org.objectweb.asm.ClassReader;
@@ -55,9 +48,9 @@ import java.util.*;
/**
* @author egor
*/
public class CompilingEvaluator implements ExpressionEvaluator {
@NotNull private final PsiElement myPsiContext;
@NotNull private final ExtractLightMethodObjectHandler.ExtractedData myData;
public abstract class CompilingEvaluator implements ExpressionEvaluator {
@NotNull protected final PsiElement myPsiContext;
@NotNull protected final ExtractLightMethodObjectHandler.ExtractedData myData;
public CompilingEvaluator(@NotNull PsiElement context, @NotNull ExtractLightMethodObjectHandler.ExtractedData data) {
myPsiContext = context;
@@ -203,25 +196,8 @@ public class CompilingEvaluator implements ExpressionEvaluator {
//private static final String GEN_CLASS_FULL_NAME = GEN_CLASS_PACKAGE + '.' + GEN_CLASS_NAME;
//private static final String GEN_METHOD_NAME = "invoke";
private String getClassCode() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return myData.getGeneratedInnerClass().getContainingFile().getText();
}
});
}
private String getMainClassName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return FileUtil.getNameWithoutExtension(myData.getGeneratedInnerClass().getContainingFile().getName());
}
});
}
private String getGenClassQName() {
protected String getGenClassQName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
@@ -250,57 +226,13 @@ public class CompilingEvaluator implements ExpressionEvaluator {
///////////////// Compiler stuff
@NotNull
private Collection<OutputFileObject> compile(String target) throws EvaluateException {
if (!SystemInfo.isJavaVersionAtLeast(target)) {
throw new EvaluateException("Unable to compile for target level " + target + ". Need to run IDEA on java version at least " + target + ", currently running on " + SystemInfo.JAVA_RUNTIME_VERSION);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler);
DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>();
Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleUtilCore.findModuleForPsiElement(myPsiContext);
}
});
List<String> options = new ArrayList<String>();
if (module != null) {
options.add("-cp");
PathsList cp = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly().withoutSdk().getPathsList();
options.add(cp.getPathsString());
}
if (!StringUtil.isEmpty(target)) {
options.add("-source");
options.add(target);
options.add("-target");
options.add(target);
}
try {
if (!compiler.getTask(null,
manager,
diagnostic,
options,
null,
Collections.singletonList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
).call()) {
StringBuilder res = new StringBuilder("Compilation failed:\n");
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
res.append(d);
}
throw new EvaluateException(res.toString());
}
}
catch (Exception e) {
throw new EvaluateException(e.getMessage());
}
return manager.classes;
}
protected abstract Collection<OutputFileObject> compile(String target) throws EvaluateException;
private static URI getUri(String name, JavaFileObject.Kind kind) {
return URI.create("memo:///" + name.replace('.', '/') + kind.extension);
}
private static class SourceFileObject extends SimpleJavaFileObject {
protected static class SourceFileObject extends SimpleJavaFileObject {
private final String myContent;
SourceFileObject(String name, Kind kind, String content) {
@@ -314,7 +246,7 @@ public class CompilingEvaluator implements ExpressionEvaluator {
}
}
private static class OutputFileObject extends SimpleJavaFileObject {
protected static class OutputFileObject extends SimpleJavaFileObject {
private final ByteArrayOutputStream myStream = new ByteArrayOutputStream();
private final String myOrigName;
@@ -333,8 +265,8 @@ public class CompilingEvaluator implements ExpressionEvaluator {
}
}
private static class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
private final Collection<OutputFileObject> classes = new ArrayList<OutputFileObject>();
protected static class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> {
protected final Collection<OutputFileObject> classes = new ArrayList<OutputFileObject>();
MemoryFileManager(JavaCompiler compiler) {
super(compiler.getStandardFileManager(null, null, null));
@@ -0,0 +1,109 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.debugger.ui.impl.watch;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
import com.intellij.util.PathsList;
import org.jetbrains.annotations.NotNull;
import javax.tools.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CompilingEvaluatorImpl extends CompilingEvaluator {
public CompilingEvaluatorImpl(@NotNull PsiElement context, @NotNull ExtractLightMethodObjectHandler.ExtractedData data) {
super(context, data);
}
@Override
@NotNull
protected Collection<OutputFileObject> compile(String target) throws EvaluateException {
if (!SystemInfo.isJavaVersionAtLeast(target)) {
throw new EvaluateException("Unable to compile for target level " + target + ". Need to run IDEA on java version at least " + target + ", currently running on " + SystemInfo.JAVA_RUNTIME_VERSION);
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler);
DiagnosticCollector<JavaFileObject> diagnostic = new DiagnosticCollector<JavaFileObject>();
Module module = ApplicationManager.getApplication().runReadAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleUtilCore.findModuleForPsiElement(myPsiContext);
}
});
List<String> options = new ArrayList<String>();
if (module != null) {
options.add("-cp");
PathsList cp = ModuleRootManager.getInstance(module).orderEntries().compileOnly().recursively().exportedOnly().withoutSdk().getPathsList();
options.add(cp.getPathsString());
}
if (!StringUtil.isEmpty(target)) {
options.add("-source");
options.add(target);
options.add("-target");
options.add(target);
}
try {
if (!compiler.getTask(null,
manager,
diagnostic,
options,
null,
Collections.singletonList(new SourceFileObject(getMainClassName(), JavaFileObject.Kind.SOURCE, getClassCode()))
).call()) {
StringBuilder res = new StringBuilder("Compilation failed:\n");
for (Diagnostic<? extends JavaFileObject> d : diagnostic.getDiagnostics()) {
res.append(d);
}
throw new EvaluateException(res.toString());
}
}
catch (Exception e) {
throw new EvaluateException(e.getMessage());
}
return manager.classes;
}
protected String getClassCode() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return myData.getGeneratedInnerClass().getContainingFile().getText();
}
});
}
protected String getMainClassName() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return FileUtil.getNameWithoutExtension(myData.getGeneratedInnerClass().getContainingFile().getName());
}
});
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -101,7 +101,7 @@ public abstract class EvaluationDescriptor extends ValueDescriptorImpl{
ExtractLightMethodObjectHandler.ExtractedData data = ExtractLightMethodObjectHandler.extractLightMethodObject(myProject,
psiFile, fragment, CompilingEvaluator.getGeneratedClassName());
if (data != null) {
return new CompilingEvaluator(psiContext, data);
return new CompilingEvaluatorImpl(psiContext, data);
}
}
catch (PrepareFailedException e) {
@@ -22,7 +22,7 @@ import com.intellij.psi.*;
* Nikolay.Tropin
* 2014-11-25
*/
interface SimpleGetterProvider {
public interface SimpleGetterProvider {
ExtensionPointName<SimpleGetterProvider> EP_NAME = ExtensionPointName.create("com.intellij.debugger.simpleGetterProvider");
boolean isSimpleGetter(PsiMethod method);
@@ -136,7 +136,7 @@ public class JavaParametersUtil {
}
final boolean isJdk = JavaSdk.checkForJdk(new File(jreHome));
if (isJdk) {
throw new CantRunException("Jre expected but jdk found");
throw new CantRunException("Alternative JRE path needs to point to a JRE, not to a complete JDK installation");
}
final Sdk jdk = JavaSdk.getInstance().createJdk("", jreHome);
if (jdk == null) throw CantRunException.noJdkConfigured();
@@ -109,6 +109,13 @@ public abstract class FrameworkSupportModelBase extends UserDataHolderBase imple
node.setChecked(enable);
// ensure configurable to be created and registered to disposer
node.getConfigurable();
if (myFrameworkVersions.get(providerId) == null) {
for (FrameworkVersion version : node.getUserObject().getFrameworkType().getVersions()) {
if (version.getAvailabilityCondition().isAvailableFor(this)) {
setSelectedVersion(providerId, version);
}
}
}
}
}
@@ -48,22 +48,22 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
}
}
if (!ignoreInference(listOwner, annotationFQN)) {
PsiAnnotation fromBytecode = ProjectBytecodeAnalysis.getInstance(myProject).findInferredAnnotation(listOwner, annotationFQN);
if (fromBytecode != null) {
return fromBytecode;
}
if (ignoreInference(listOwner, annotationFQN)) {
return null;
}
PsiAnnotation fromBytecode = ProjectBytecodeAnalysis.getInstance(myProject).findInferredAnnotation(listOwner, annotationFQN);
if (fromBytecode != null) {
return fromBytecode;
}
if (canInferFromSource(listOwner)) {
//noinspection ConstantConditions
PsiMethod method = (PsiMethod)listOwner;
if (listOwner instanceof PsiMethod) {
if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN)) {
return getInferredContractAnnotation(method);
return getInferredContractAnnotation((PsiMethod)listOwner);
}
if ((AnnotationUtil.NOT_NULL.equals(annotationFQN) || AnnotationUtil.NULLABLE.equals(annotationFQN))) {
PsiAnnotation anno = getInferredNullityAnnotation(method);
PsiAnnotation anno = getInferredNullityAnnotation((PsiMethod)listOwner);
return anno == null ? null : annotationFQN.equals(anno.getQualifiedName()) ? anno : null;
}
}
@@ -79,6 +79,9 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
@Override
public boolean ignoreInference(@NotNull PsiModifierListOwner owner, @Nullable String annotationFQN) {
if (owner instanceof PsiMethod && PsiUtil.canBeOverriden((PsiMethod)owner)) {
return true;
}
if (ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotationFQN) && hasHardcodedContracts(owner)) {
return true;
}
@@ -138,10 +141,6 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
return ProjectBytecodeAnalysis.getInstance(myProject).createContractAnnotation(attrs);
}
private static boolean canInferFromSource(PsiModifierListOwner listOwner) {
return listOwner instanceof PsiMethod && !PsiUtil.canBeOverriden((PsiMethod)listOwner);
}
@NotNull
@Override
public PsiAnnotation[] findInferredAnnotations(@NotNull PsiModifierListOwner listOwner) {
@@ -150,17 +149,24 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
PsiAnnotation[] fromBytecode = ProjectBytecodeAnalysis.getInstance(myProject).findInferredAnnotations(listOwner);
for (PsiAnnotation annotation : fromBytecode) {
if (!ignoreInference(listOwner, annotation.getQualifiedName())) {
if (!ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotation.getQualifiedName()) || canInferFromSource(listOwner)) {
result.add(annotation);
}
result.add(annotation);
}
}
if (canInferFromSource(listOwner)) {
if (listOwner instanceof PsiMethod) {
PsiAnnotation hardcoded = getHardcodedContractAnnotation((PsiMethod)listOwner);
ContainerUtil.addIfNotNull(result, hardcoded != null ? hardcoded : getInferredContractAnnotation((PsiMethod)listOwner));
ContainerUtil.addIfNotNull(result, getInferredNullityAnnotation((PsiMethod)listOwner));
if (hardcoded != null) {
result.add(hardcoded);
} else if (!ignoreInference(listOwner, ORG_JETBRAINS_ANNOTATIONS_CONTRACT)) {
ContainerUtil.addIfNotNull(result, getInferredContractAnnotation((PsiMethod)listOwner));
}
if (!ignoreInference(listOwner, AnnotationUtil.NOT_NULL) || !ignoreInference(listOwner, AnnotationUtil.NULLABLE)) {
PsiAnnotation annotation = getInferredNullityAnnotation((PsiMethod)listOwner);
if (annotation != null && !ignoreInference(listOwner, annotation.getQualifiedName())) {
result.add(annotation);
}
}
}
return result.isEmpty() ? PsiAnnotation.EMPTY_ARRAY : result.toArray(new PsiAnnotation[result.size()]);
@@ -89,8 +89,12 @@ class ContractInferenceInterpreter {
PsiTypeElement typeElement = myMethod.getReturnTypeElement();
final PsiType returnType = typeElement == null ? null : typeElement.getType();
final boolean notNull = !(returnType instanceof PsiPrimitiveType) &&
boolean referenceTypeReturned = !(returnType instanceof PsiPrimitiveType);
final boolean notNull = referenceTypeReturned &&
NullableNotNullManager.getInstance(myMethod.getProject()).isNotNull(myMethod, false);
if (referenceTypeReturned) {
contracts = boxReturnValues(contracts);
}
return ContainerUtil.filter(contracts, new Condition<MethodContract>() {
@Override
public boolean value(MethodContract contract) {
@@ -101,7 +105,20 @@ class ContractInferenceInterpreter {
}
});
}
@NotNull
private static List<MethodContract> boxReturnValues(List<MethodContract> contracts) {
return ContainerUtil.mapNotNull(contracts, new Function<MethodContract, MethodContract>() {
@Override
public MethodContract fun(MethodContract contract) {
if (contract.returnValue == FALSE_VALUE || contract.returnValue == TRUE_VALUE) {
return new MethodContract(contract.arguments, NOT_NULL_VALUE);
}
return contract;
}
});
}
private List<MethodContract> doInferContracts() {
PsiCodeBlock body = myMethod.getBody();
PsiStatement[] statements = body == null ? PsiStatement.EMPTY_ARRAY : body.getStatements();
@@ -294,7 +311,7 @@ class ContractInferenceInterpreter {
parameter = resolveParameter(op2);
constraint = getLiteralConstraint(op1);
}
if (parameter >= 0 && constraint != null) {
if (parameter >= 0 && constraint != null && constraint != NOT_NULL_VALUE) {
List<MethodContract> result = ContainerUtil.newArrayList();
for (ValueConstraint[] state : states) {
ContainerUtil.addIfNotNull(result, contractWithConstraint(state, parameter, constraint, equality ? TRUE_VALUE : FALSE_VALUE));
@@ -410,7 +427,7 @@ class ContractInferenceInterpreter {
if (expr.textMatches(PsiKeyword.TRUE)) return TRUE_VALUE;
if (expr.textMatches(PsiKeyword.FALSE)) return FALSE_VALUE;
if (expr.textMatches(PsiKeyword.NULL)) return NULL_VALUE;
if (((PsiLiteralExpression)expr).getValue() instanceof String) return NOT_NULL_VALUE;
return NOT_NULL_VALUE;
}
return null;
}
@@ -1490,10 +1490,6 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
final PsiAnnotation contractAnno = findContractAnnotation(method);
final int paramCount = method.getParameterList().getParametersCount();
if (contractAnno != null) {
if (AnnotationUtil.isInferredAnnotation(contractAnno) && PsiUtil.canBeOverriden(method)) {
return Collections.emptyList();
}
return CachedValuesManager.getCachedValue(contractAnno, new CachedValueProvider<List<MethodContract>>() {
@Nullable
@Override
@@ -536,6 +536,10 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
}
private static boolean isCompileConstantInIfCondition(PsiElement element) {
if (element instanceof PsiPrefixExpression && ((PsiPrefixExpression)element).getOperationTokenType() == JavaTokenType.EXCL) {
return isCompileConstantInIfCondition(((PsiPrefixExpression)element).getOperand());
}
if (!(element instanceof PsiReferenceExpression)) return false;
PsiElement resolved = ((PsiReferenceExpression)element).resolve();
if (!(resolved instanceof PsiField)) return false;
@@ -253,10 +253,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
if (value instanceof DfaVariableValue) {
setVariableState(var, getVariableState((DfaVariableValue)value));
}
else if (value instanceof DfaBoxedValue) {
setVariableState(var, getVariableState(var).withNullable(false));
applyCondition(compareToNull(var, true));
}
}
if (getVariableState(var).isNotNull()) {
@@ -477,6 +473,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
@Override
public boolean isNotNull(DfaValue dfaVar) {
if (dfaVar instanceof DfaConstValue) return ((DfaConstValue)dfaVar).getValue() != null;
if (dfaVar instanceof DfaBoxedValue) return true;
if (dfaVar instanceof DfaTypeValue) return ((DfaTypeValue)dfaVar).isNotNull();
if (dfaVar instanceof DfaVariableValue) {
if (getVariableState((DfaVariableValue)dfaVar).isNotNull()) return true;
@@ -26,7 +26,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -68,25 +68,34 @@ public class NullityInference {
final AtomicBoolean hasNotNulls = new AtomicBoolean();
final AtomicBoolean hasNulls = new AtomicBoolean();
final AtomicBoolean hasUnknowns = new AtomicBoolean();
final List<PsiMethodCallExpression> calls = ContainerUtil.newArrayList();
final Set<PsiMethod> delegates = ContainerUtil.newLinkedHashSet();
body.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReturnStatement(PsiReturnStatement statement) {
PsiExpression value = statement.getReturnValue();
if (value == null) {
hasErrors.set(true);
} else {
if (value instanceof PsiLiteralExpression) {
if (value.textMatches(PsiKeyword.NULL)) {
hasNulls.set(true);
} else {
hasNotNulls.set(true);
}
} else if (value instanceof PsiMethodCallExpression) {
calls.add((PsiMethodCallExpression)value);
} else {
hasUnknowns.set(true);
} else if (value instanceof PsiLiteralExpression) {
if (value.textMatches(PsiKeyword.NULL)) {
hasNulls.set(true);
}
else {
hasNotNulls.set(true);
}
}
else if (value.getType() instanceof PsiPrimitiveType) {
hasNotNulls.set(true);
}
else if (value instanceof PsiMethodCallExpression) {
PsiMethod target = ((PsiMethodCallExpression)value).resolveMethod();
if (target == null) {
hasUnknowns.set(true);
} else {
delegates.add(target);
}
}
else {
hasUnknowns.set(true);
}
super.visitReturnStatement(statement);
}
@@ -102,13 +111,12 @@ public class NullityInference {
return Nullness.NULLABLE;
}
if (calls.size() > 1) {
if (hasErrors.get() || delegates.size() > 1) {
return Nullness.UNKNOWN;
}
if (calls.size() == 1) {
PsiMethod target = calls.get(0).resolveMethod();
if (target != null && NullableNotNullManager.isNotNull(target)) {
if (delegates.size() == 1) {
if (NullableNotNullManager.isNotNull(delegates.iterator().next())) {
return Nullness.NOT_NULL;
}
return Nullness.UNKNOWN;
@@ -33,6 +33,7 @@ import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.util.VariableData;
import com.intellij.refactoring.util.duplicates.DuplicatesFinder;
import com.intellij.util.ArrayUtil;
import com.intellij.util.text.UniqueNameGenerator;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -47,6 +48,9 @@ public class InputVariables {
private ParametersFolder myFolding;
private boolean myFoldingAvailable;
private Set<PsiField> myUsedInstanceFields = null;
private boolean myPassFields = false;
public InputVariables(final List<? extends PsiVariable> inputVariables,
Project project,
LocalSearchScope scope,
@@ -74,16 +78,25 @@ public class InputVariables {
return myFolding.isFoldable();
}
public void setUsedInstanceFields(Set<PsiField> usedInstanceFields) {
myUsedInstanceFields = usedInstanceFields;
}
public void setPassFields(boolean passFields) {
if (myUsedInstanceFields == null || myUsedInstanceFields.isEmpty()) {
return;
}
myPassFields = passFields;
myInputVariables.clear();
myInputVariables.addAll(wrapInputVariables(myInitialParameters));
}
public ArrayList<VariableData> wrapInputVariables(final List<? extends PsiVariable> inputVariables) {
UniqueNameGenerator nameGenerator = new UniqueNameGenerator();
final ArrayList<VariableData> inputData = new ArrayList<VariableData>(inputVariables.size());
for (PsiVariable var : inputVariables) {
String name = var.getName();
if (!(var instanceof PsiParameter)) {
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject);
VariableKind kind = codeStyleManager.getVariableKind(var);
name = codeStyleManager.variableNameToPropertyName(name, kind);
name = codeStyleManager.propertyNameToVariableName(name, VariableKind.PARAMETER);
}
String name = nameGenerator.generateUniqueName(getParameterName(var));
PsiType type = var.getType();
if (type instanceof PsiEllipsisType) {
type = ((PsiEllipsisType)type).toArrayType();
@@ -138,9 +151,28 @@ public class InputVariables {
}
if (myPassFields && myUsedInstanceFields != null) {
for (PsiField var : myUsedInstanceFields) {
final VariableData data = new VariableData(var, var.getType());
data.name = nameGenerator.generateUniqueName(getParameterName(var));
data.passAsParameter = true;
inputData.add(data);
}
}
return inputData;
}
private String getParameterName(PsiVariable var) {
String name = var.getName();
if (!(var instanceof PsiParameter)) {
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(myProject);
VariableKind kind = codeStyleManager.getVariableKind(var);
name = codeStyleManager.variableNameToPropertyName(name, kind);
name = codeStyleManager.propertyNameToVariableName(name, VariableKind.PARAMETER);
}
return name;
}
@Nullable
private PsiType checkTopLevelInstanceOf(final PsiType currentType) {
final PsiElement[] scope = myScope.getScope();
@@ -310,4 +342,8 @@ public class InputVariables {
public boolean isFoldingSelectedByDefault() {
return myFolding.isFoldingSelectedByDefault();
}
public boolean hasInstanceFields() {
return myUsedInstanceFields != null && !myUsedInstanceFields.isEmpty();
}
}
@@ -880,11 +880,17 @@ public class ExpectedTypesProvider {
if (statement.getException() == myExpr) {
PsiManager manager = statement.getManager();
PsiType throwableType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Throwable", myExpr.getResolveScope());
PsiMember container = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiClass.class);
PsiElement container = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class, PsiClass.class);
PsiType[] throwsTypes = PsiType.EMPTY_ARRAY;
if (container instanceof PsiMethod) {
throwsTypes = ((PsiMethod)container).getThrowsList().getReferencedTypes();
}
else if (container instanceof PsiLambdaExpression) {
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(container);
if (method != null) {
throwsTypes = method.getThrowsList().getReferencedTypes();
}
}
if (throwsTypes.length == 0) {
final PsiClassType exceptionType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Exception", myExpr.getResolveScope());
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -67,7 +67,7 @@ public class RecursiveCallLineMarkerProvider implements LineMarkerProvider {
return false;
}
final PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class);
final PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiLambdaExpression.class, PsiClass.class);
if (method == null || !method.getName().equals(methodCall.getMethodExpression().getReferenceName())) {
return false;
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
@@ -56,9 +57,10 @@ import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.*;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.EditorTextFieldJBTableRowRenderer;
import com.intellij.util.ui.table.JBTableRow;
import com.intellij.util.ui.table.JBTableRowEditor;
import com.intellij.util.ui.table.JBTableRowRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,6 +74,7 @@ import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import static com.intellij.refactoring.changeSignature.ChangeSignatureHandler.REFACTORING_NAME;
@@ -220,32 +223,175 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
}
@Override
protected boolean isEmptyRow(ParameterTableModelItemBase<ParameterInfoImpl> row) {
if (!StringUtil.isEmpty(row.parameter.getName())) return false;
if (!StringUtil.isEmpty(row.parameter.getTypeText())) return false;
return true;
}
protected ParametersListTable createParametersListTable() {
return new ParametersListTable() {
private final EditorTextFieldJBTableRowRenderer myRowRenderer = new EditorTextFieldJBTableRowRenderer(getProject(), myDisposable) {
@Override
protected String getText(JTable table, int row) {
ParameterTableModelItemBase<ParameterInfoImpl> item = getRowItem(row);
final String typeText = item.typeCodeFragment.getText();
final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1);
String text = typeText + separator + item.parameter.getName();
final String defaultValue = item.defaultValueCodeFragment.getText();
String tail = "";
if (StringUtil.isNotEmpty(defaultValue)) {
tail += " default value = " + defaultValue;
}
if (item.parameter.isUseAnySingleVariable()) {
if (StringUtil.isNotEmpty(defaultValue)) {
tail += ";";
}
tail += " Use any var.";
}
if (!StringUtil.isEmpty(tail)) {
text += " //" + tail;
}
return " " + text;
}
@Override
protected JComponent getRowPresentation(ParameterTableModelItemBase<ParameterInfoImpl> item, boolean selected, final boolean focused) {
final String typeText = item.typeCodeFragment.getText();
final String separator = StringUtil.repeatSymbol(' ', getTypesMaxLength() - typeText.length() + 1);
String text = typeText + separator + item.parameter.getName();
final String defaultValue = item.defaultValueCodeFragment.getText();
String tail = "";
if (StringUtil.isNotEmpty(defaultValue)) {
tail += " default value = " + defaultValue;
}
if (item.parameter.isUseAnySingleVariable()) {
if (StringUtil.isNotEmpty(defaultValue)) {
tail += ";";
@Nullable
@Override
protected FileType getFileType() {
return JavaChangeSignatureDialog.this.getFileType();
}
};
@Override
protected JBTableRowRenderer getRowRenderer(int row) {
return myRowRenderer;
}
tail += " Use any var.";
}
if (!StringUtil.isEmpty(tail)) {
text += " //" + tail;
}
return JBListTable.createEditorTextFieldPresentation(getProject(), getFileType(), " " + text, selected, focused);
@NotNull
@Override
protected JBTableRowEditor getRowEditor(final ParameterTableModelItemBase<ParameterInfoImpl> item) {
return new JBTableRowEditor() {
private EditorTextField myTypeEditor;
private EditorTextField myNameEditor;
private EditorTextField myDefaultValueEditor;
private JCheckBox myAnyVar;
@Override
public void prepareEditor(JTable table, int row) {
setLayout(new BorderLayout());
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
myTypeEditor = new EditorTextField(document, getProject(), getFileType());
myTypeEditor.addDocumentListener(mySignatureUpdater);
myTypeEditor.setPreferredWidth(getTable().getWidth() / 2);
myTypeEditor.addDocumentListener(new RowEditorChangeListener(0));
add(createLabeledPanel("Type:", myTypeEditor), BorderLayout.WEST);
myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());
myNameEditor.addDocumentListener(mySignatureUpdater);
myNameEditor.addDocumentListener(new RowEditorChangeListener(1));
add(createLabeledPanel("Name:", myNameEditor), BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@Override
protected void addCompletionVariants(@NotNull String text,
int offset,
@NotNull String prefix,
@NotNull CompletionResultSet result) {
final PsiCodeFragment fragment = item.typeCodeFragment;
if (fragment instanceof PsiTypeCodeFragment) {
final PsiType type;
try {
type = ((PsiTypeCodeFragment)fragment).getType();
}
catch (Exception e) {
return;
}
final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject)
.suggestVariableName(VariableKind.PARAMETER, null, null, type);
for (String completionVariant : info.names) {
final LookupElementBuilder element = LookupElementBuilder.create(completionVariant);
result.addElement(element.withLookupString(completionVariant.toLowerCase(Locale.ENGLISH)));
}
}
}
}.apply(myNameEditor, item.parameter.getName());
if (!item.isEllipsisType() && item.parameter.getOldIndex() == -1) {
final JPanel additionalPanel = new JPanel(new BorderLayout());
final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType());
((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item));
myDefaultValueEditor.setPreferredWidth(getTable().getWidth() / 2);
myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2));
additionalPanel.add(createLabeledPanel("Default value:", myDefaultValueEditor), BorderLayout.WEST);
if (!isGenerateDelegate()) {
myAnyVar = new JCheckBox("&Use Any Var");
UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myAnyVar);
DialogUtil.registerMnemonic(myAnyVar, '&');
myAnyVar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
item.parameter.setUseAnySingleVariable(myAnyVar.isSelected());
}
});
final JPanel anyVarPanel = new JPanel(new BorderLayout());
anyVarPanel.add(myAnyVar, BorderLayout.SOUTH);
UIUtil.addInsets(anyVarPanel, new Insets(0,0,8,0));
additionalPanel.add(anyVarPanel, BorderLayout.CENTER);
//additionalPanel.setPreferredSize(new Dimension(t.getWidth() / 3, -1));
}
add(additionalPanel, BorderLayout.SOUTH);
}
}
@Override
public JBTableRow getValue() {
return new JBTableRow() {
@Override
public Object getValueAt(int column) {
switch (column) {
case 0: return item.typeCodeFragment;
case 1: return myNameEditor.getText().trim();
case 2: return item.defaultValueCodeFragment;
case 3: return myAnyVar != null && myAnyVar.isSelected();
}
return null;
}
};
}
@Override
public JComponent getPreferredFocusedComponent() {
final MouseEvent me = getMouseEvent();
if (me == null) {
return myTypeEditor.getFocusTarget();
}
final double x = me.getPoint().getX();
return x <= getTypesColumnWidth()
? myTypeEditor.getFocusTarget()
: myDefaultValueEditor == null || x <= getNamesColumnWidth()
? myNameEditor.getFocusTarget()
: myDefaultValueEditor.getFocusTarget();
}
@Override
public JComponent[] getFocusableComponents() {
final List<JComponent> focusable = new ArrayList<JComponent>();
focusable.add(myTypeEditor.getFocusTarget());
focusable.add(myNameEditor.getFocusTarget());
if (myDefaultValueEditor != null) {
focusable.add(myDefaultValueEditor.getFocusTarget());
}
if (myAnyVar != null) {
focusable.add(myAnyVar);
}
return focusable.toArray(new JComponent[focusable.size()]);
}
};
}
@Override
protected boolean isRowEmpty(int row) {
ParameterInfoImpl parameter = getRowItem(row).parameter;
return StringUtil.isEmpty(parameter.getName()) && StringUtil.isEmpty(parameter.getTypeText());
}
};
}
private int getTypesMaxLength() {
@@ -281,130 +427,6 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
return getColumnWidth(1);
}
@Override
protected JBTableRowEditor getTableEditor(final JTable t, final ParameterTableModelItemBase<ParameterInfoImpl> item) {
return new JBTableRowEditor() {
private EditorTextField myTypeEditor;
private EditorTextField myNameEditor;
private EditorTextField myDefaultValueEditor;
private JCheckBox myAnyVar;
@Override
public void prepareEditor(JTable table, int row) {
setLayout(new BorderLayout());
final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
myTypeEditor = new EditorTextField(document, getProject(), getFileType());
myTypeEditor.addDocumentListener(mySignatureUpdater);
myTypeEditor.setPreferredWidth(t.getWidth() / 2);
myTypeEditor.addDocumentListener(new RowEditorChangeListener(0));
add(createLabeledPanel("Type:", myTypeEditor), BorderLayout.WEST);
myNameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());
myNameEditor.addDocumentListener(mySignatureUpdater);
myNameEditor.addDocumentListener(new RowEditorChangeListener(1));
add(createLabeledPanel("Name:", myNameEditor), BorderLayout.CENTER);
new TextFieldCompletionProvider() {
@Override
protected void addCompletionVariants(@NotNull String text,
int offset,
@NotNull String prefix,
@NotNull CompletionResultSet result) {
final PsiCodeFragment fragment = item.typeCodeFragment;
if (fragment instanceof PsiTypeCodeFragment) {
final PsiType type;
try {
type = ((PsiTypeCodeFragment)fragment).getType();
}
catch (Exception e) {
return;
}
final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject)
.suggestVariableName(VariableKind.PARAMETER, null, null, type);
for (String completionVariant : info.names) {
final LookupElementBuilder element = LookupElementBuilder.create(completionVariant);
result.addElement(element.withLookupString(completionVariant.toLowerCase()));
}
}
}
}.apply(myNameEditor, item.parameter.getName());
if (!item.isEllipsisType() && item.parameter.getOldIndex() == -1) {
final JPanel additionalPanel = new JPanel(new BorderLayout());
final Document doc = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
myDefaultValueEditor = new EditorTextField(doc, getProject(), getFileType());
((PsiExpressionCodeFragment)item.defaultValueCodeFragment).setExpectedType(getRowType(item));
myDefaultValueEditor.setPreferredWidth(t.getWidth() / 2);
myDefaultValueEditor.addDocumentListener(new RowEditorChangeListener(2));
additionalPanel.add(createLabeledPanel("Default value:", myDefaultValueEditor), BorderLayout.WEST);
if (!isGenerateDelegate()) {
myAnyVar = new JCheckBox("&Use Any Var");
UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myAnyVar);
DialogUtil.registerMnemonic(myAnyVar, '&');
myAnyVar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
item.parameter.setUseAnySingleVariable(myAnyVar.isSelected());
}
});
final JPanel anyVarPanel = new JPanel(new BorderLayout());
anyVarPanel.add(myAnyVar, BorderLayout.SOUTH);
UIUtil.addInsets(anyVarPanel, new Insets(0,0,8,0));
additionalPanel.add(anyVarPanel, BorderLayout.CENTER);
//additionalPanel.setPreferredSize(new Dimension(t.getWidth() / 3, -1));
}
add(additionalPanel, BorderLayout.SOUTH);
}
}
@Override
public JBTableRow getValue() {
return new JBTableRow() {
@Override
public Object getValueAt(int column) {
switch (column) {
case 0: return item.typeCodeFragment;
case 1: return myNameEditor.getText().trim();
case 2: return item.defaultValueCodeFragment;
case 3: return myAnyVar != null && myAnyVar.isSelected();
}
return null;
}
};
}
@Override
public JComponent getPreferredFocusedComponent() {
final MouseEvent me = getMouseEvent();
if (me == null) {
return myTypeEditor.getFocusTarget();
}
final double x = me.getPoint().getX();
return x <= getTypesColumnWidth()
? myTypeEditor.getFocusTarget()
: myDefaultValueEditor == null || x <= getNamesColumnWidth()
? myNameEditor.getFocusTarget()
: myDefaultValueEditor.getFocusTarget();
}
@Override
public JComponent[] getFocusableComponents() {
final List<JComponent> focusable = new ArrayList<JComponent>();
focusable.add(myTypeEditor.getFocusTarget());
focusable.add(myNameEditor.getFocusTarget());
if (myDefaultValueEditor != null) {
focusable.add(myDefaultValueEditor.getFocusTarget());
}
if (myAnyVar != null) {
focusable.add(myAnyVar);
}
return focusable.toArray(new JComponent[focusable.size()]);
}
};
}
@Nullable
private static PsiType getRowType(ParameterTableModelItemBase<ParameterInfoImpl> item) {
try {
@@ -28,6 +28,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.IntArrayList;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -106,8 +107,8 @@ public class ControlFlowWrapper {
}
if (myExitPoints.size() != 1) {
areExitStatementsTheSame();
myGenerateConditionalExit = true;
areExitStatementsTheSame();
}
return myExitStatements;
}
@@ -142,10 +143,12 @@ public class ControlFlowWrapper {
public static class ExitStatementsNotSameException extends Exception {}
@NotNull
public PsiVariable[] getOutputVariables() {
return getOutputVariables(myGenerateConditionalExit);
}
@NotNull
public PsiVariable[] getOutputVariables(boolean collectVariablesAtExitPoints) {
PsiVariable[] myOutputVariables = ControlFlowUtil.getOutputVariables(myControlFlow, myFlowStart, myFlowEnd, myExitPoints.toArray());
if (collectVariablesAtExitPoints) {
@@ -31,6 +31,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.*;
import com.intellij.refactoring.util.ConflictsUtil;
@@ -40,6 +41,7 @@ import com.intellij.ui.EditorTextField;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.ui.SeparatorFactory;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.MultiMap;
@@ -239,11 +241,28 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
return main;
}
protected boolean isVoidReturn() {
return false;
}
@Nullable
private JPanel createReturnTypePanel() {
mySelector = new TypeSelectorManagerImpl(myProject, myReturnType, findOccurrences(), areTypesDirected()).getTypeSelector();
if (TypeConversionUtil.isPrimitiveWrapper(myReturnType) && myNullness == Nullness.NULLABLE) {
return null;
}
final TypeSelectorManagerImpl manager = new TypeSelectorManagerImpl(myProject, myReturnType, findOccurrences(), areTypesDirected()) {
@Override
public PsiType[] getTypesForAll(boolean direct) {
final PsiType[] types = super.getTypesForAll(direct);
return !isVoidReturn() ? types : ArrayUtil.prepend(PsiType.VOID, types);
}
};
mySelector = manager.getTypeSelector();
final JComponent component = mySelector.getComponent();
if (component instanceof JComboBox) {
if (isVoidReturn()) {
mySelector.selectType(PsiType.VOID);
}
final JPanel returnTypePanel = new JPanel(new BorderLayout(2, 0));
final JLabel label = new JLabel(RefactoringBundle.message("changeSignature.return.type.prompt"));
returnTypePanel.add(label, BorderLayout.NORTH);
@@ -280,8 +299,17 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
if (myStaticFlag || myCanBeStatic) {
myMakeStatic.setEnabled(!myStaticFlag);
myMakeStatic.setSelected(myStaticFlag);
if (myVariableData.hasInstanceFields()) {
myMakeStatic.setText(RefactoringBundle.message("declare.static.pass.fields.checkbox"));
}
myMakeStatic.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
if (myVariableData.hasInstanceFields()) {
myVariableData.setPassFields(myMakeStatic.isSelected());
myInputVariables = myVariableData.getInputVariables().toArray(new VariableData[myVariableData.getInputVariables().size()]);
updateVarargsEnabled();
createParametersPanel();
}
updateSignature();
}
});
@@ -523,7 +551,7 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
buffer.append(myTargetClass.getName());
}
else {
buffer.append(PsiFormatUtil.formatType(mySelector.getSelectedType(), 0, PsiSubstitutor.EMPTY));
buffer.append(PsiFormatUtil.formatType(mySelector != null ? mySelector.getSelectedType() : myReturnType, 0, PsiSubstitutor.EMPTY));
buffer.append(" ");
buffer.append(myNameField.getText());
}
@@ -593,6 +621,6 @@ public class ExtractMethodDialog extends DialogWrapper implements AbstractExtrac
}
public PsiType getReturnType() {
return mySelector.getSelectedType();
return mySelector != null ? mySelector.getSelectedType() : myReturnType;
}
}
@@ -53,6 +53,8 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl;
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PsiElementProcessor;
@@ -68,10 +70,8 @@ import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.refactoring.util.*;
import com.intellij.refactoring.util.classMembers.ElementNeedsThis;
import com.intellij.refactoring.util.duplicates.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -114,6 +114,7 @@ public class ExtractMethodProcessor implements MatchProvider {
protected InputVariables myInputVariables; // input variables
protected PsiVariable[] myOutputVariables; // output variables
protected PsiVariable myOutputVariable; // the only output variable
private PsiVariable myArtificialOutputVariable;
private Collection<PsiStatement> myExitStatements;
private boolean myHasReturnStatement; // there is a return statement
@@ -125,7 +126,6 @@ public class ExtractMethodProcessor implements MatchProvider {
protected boolean myCanBeStatic;
protected boolean myCanBeChainedConstructor;
protected boolean myIsChainedConstructor;
private DuplicatesFinder myDuplicatesFinder;
private List<Match> myDuplicates;
@PsiModifier.ModifierConstant private String myMethodVisibility = PsiModifier.PRIVATE;
protected boolean myGenerateConditionalExit;
@@ -242,8 +242,11 @@ public class ExtractMethodProcessor implements MatchProvider {
}
catch (ControlFlowWrapper.ExitStatementsNotSameException e) {
myExitStatements = myControlFlowWrapper.getExitStatements();
showMultipleExitPointsMessage();
return false;
myNotNullConditionalCheck = areAllExitPointsAreNotNull(getExpectedReturnType());
if (!myNotNullConditionalCheck) {
showMultipleExitPointsMessage();
return false;
}
}
myOutputVariables = myControlFlowWrapper.getOutputVariables();
@@ -266,11 +269,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
myHasExpressionOutput = expressionType != PsiType.VOID;
final PsiType returnStatementType = myCodeFragmentMember instanceof PsiMethod
? ((PsiMethod)myCodeFragmentMember).getReturnType()
: myCodeFragmentMember instanceof PsiLambdaExpression
? LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)myCodeFragmentMember)
: null;
final PsiType returnStatementType = getExpectedReturnType();
myHasReturnStatementOutput = myHasReturnStatement && returnStatementType != null && returnStatementType != PsiType.VOID;
if (myGenerateConditionalExit && myOutputVariables.length == 1) {
@@ -285,15 +284,7 @@ public class ExtractMethodProcessor implements MatchProvider {
myNullConditionalCheck &= isNullInferred(myOutputVariables[0].getName(), false);
}
if (insertNotNullCheckIfPossible() && myControlFlowWrapper.getOutputVariables(false).length == 0) {
myNotNullConditionalCheck = returnStatementType != null && returnStatementType != PsiType.VOID;
for (PsiStatement statement : myExitStatements) {
if (statement instanceof PsiReturnStatement) {
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
myNotNullConditionalCheck &= returnValue != null && !isNullInferred(returnValue.getText(), true);
}
}
}
myNotNullConditionalCheck = areAllExitPointsAreNotNull(returnStatementType);
}
if (!myHasReturnStatementOutput && checkOutputVariablesCount() && !myNullConditionalCheck && !myNotNullConditionalCheck) {
@@ -343,6 +334,45 @@ public class ExtractMethodProcessor implements MatchProvider {
return true;
}
private PsiType getExpectedReturnType() {
return myCodeFragmentMember instanceof PsiMethod
? ((PsiMethod)myCodeFragmentMember).getReturnType()
: myCodeFragmentMember instanceof PsiLambdaExpression
? LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)myCodeFragmentMember)
: null;
}
@Nullable
private PsiVariable getArtificialOutputVariable() {
if (myOutputVariables.length == 0) {
final VariablesProcessor processor = new VariablesProcessor(true) {
@Override
protected boolean check(PsiVariable var, ResolveState state) {
return isDeclaredInside(var);
}
};
PsiScopesUtil.treeWalkUp(processor, myElements[myElements.length - 1], myCodeFragmentMember);
if (processor.size() == 1) {
return processor.getResult(0);
}
}
return null;
}
private boolean areAllExitPointsAreNotNull(PsiType returnStatementType) {
if (insertNotNullCheckIfPossible() && myControlFlowWrapper.getOutputVariables(false).length == 0) {
boolean isNotNull = returnStatementType != null && returnStatementType != PsiType.VOID;
for (PsiStatement statement : myExitStatements) {
if (statement instanceof PsiReturnStatement) {
final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue();
isNotNull &= returnValue != null && !isNullInferred(returnValue.getText(), true);
}
}
return isNotNull;
}
return false;
}
protected boolean insertNotNullCheckIfPossible() {
return true;
}
@@ -498,7 +528,9 @@ public class ExtractMethodProcessor implements MatchProvider {
final List<VariableData> variables = myInputVariables.getInputVariables();
myVariableDatum = variables.toArray(new VariableData[variables.size()]);
myNullness = initNullness();
return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, myReturnType, getTypeParameterList(),
myArtificialOutputVariable = PsiType.VOID.equals(myReturnType) ? getArtificialOutputVariable() : null;
final PsiType returnType = myArtificialOutputVariable != null ? myArtificialOutputVariable.getType() : myReturnType;
return new ExtractMethodDialog(myProject, myTargetClass, myInputVariables, returnType, getTypeParameterList(),
getThrownExceptions(), isStatic(), isCanBeStatic(), myCanBeChainedConstructor,
suggestInitialMethodName(),
myRefactoringName, myHelpId, myNullness, myElements) {
@@ -516,6 +548,10 @@ public class ExtractMethodProcessor implements MatchProvider {
return ExtractMethodProcessor.this.isOutputVariable(var);
}
protected boolean isVoidReturn() {
return myArtificialOutputVariable != null;
}
@Override
protected void checkMethodConflicts(MultiMap<PsiElement, String> conflicts) {
super.checkMethodConflicts(conflicts);
@@ -554,7 +590,19 @@ public class ExtractMethodProcessor implements MatchProvider {
: PsiTreeUtil.findCommonParent(myElements);
return CodeInsightUtil.findReferenceExpressions(scope, myOutputVariable);
}
return PsiExpression.EMPTY_ARRAY;
final List<PsiStatement> filter = ContainerUtil.filter(myExitStatements, new Condition<PsiStatement>() {
@Override
public boolean value(PsiStatement statement) {
return statement instanceof PsiReturnStatement;
}
});
final List<PsiExpression> map = ContainerUtil.map(filter, new Function<PsiStatement, PsiExpression>() {
@Override
public PsiExpression fun(PsiStatement statement) {
return ((PsiReturnStatement) statement).getReturnValue();
}
});
return map.toArray(new PsiExpression[map.size()]);
}
private Nullness initNullness() {
@@ -639,7 +687,17 @@ public class ExtractMethodProcessor implements MatchProvider {
}
@TestOnly
public void testPrepare(PsiType returnType) {
public void testPrepare(PsiType returnType, boolean makeStatic) throws PrepareFailedException{
if (makeStatic) {
if (!isCanBeStatic()) {
throw new PrepareFailedException("Failed to make static", myElements[0]);
}
myInputVariables.setPassFields(true);
myStatic = true;
}
if (PsiType.VOID.equals(myReturnType)) {
myArtificialOutputVariable = getArtificialOutputVariable();
}
testPrepare();
if (returnType != null) {
myReturnType = returnType;
@@ -709,7 +767,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
}
private void initDuplicates() {
private DuplicatesFinder initDuplicates() {
List<PsiElement> elements = new ArrayList<PsiElement>();
for (PsiElement element : myElements) {
if (!(element instanceof PsiWhiteSpace || element instanceof PsiComment)) {
@@ -718,18 +776,21 @@ public class ExtractMethodProcessor implements MatchProvider {
}
if (myExpression != null) {
myDuplicatesFinder = new DuplicatesFinder(PsiUtilCore.toPsiElementArray(elements), myInputVariables.copy(),
DuplicatesFinder finder = new DuplicatesFinder(PsiUtilCore.toPsiElementArray(elements), myInputVariables.copy(),
new ArrayList<PsiVariable>());
myDuplicates = myDuplicatesFinder.findDuplicates(myTargetClass);
myDuplicates = finder.findDuplicates(myTargetClass);
return finder;
}
else if (elements.size() > 0){
myDuplicatesFinder = new DuplicatesFinder(PsiUtilCore.toPsiElementArray(elements), myInputVariables.copy(),
DuplicatesFinder myDuplicatesFinder = new DuplicatesFinder(PsiUtilCore.toPsiElementArray(elements), myInputVariables.copy(),
myOutputVariable != null ? new VariableReturnValue(myOutputVariable) : null,
Arrays.asList(myOutputVariables));
myDuplicates = myDuplicatesFinder.findDuplicates(myTargetClass);
return myDuplicatesFinder;
} else {
myDuplicates = new ArrayList<Match>();
}
return null;
}
public void doExtract() throws IncorrectOperationException {
@@ -787,7 +848,7 @@ public class ExtractMethodProcessor implements MatchProvider {
CodeStyleManager.getInstance(myProject).reformat(ifStatement);
}
else if (myNotNullConditionalCheck) {
String varName = myOutputVariable.getName();
String varName = myOutputVariable != null ? myOutputVariable.getName() : "x";
varName = declareVariableAtMethodCallLocation(varName, myReturnType instanceof PsiPrimitiveType ? ((PsiPrimitiveType)myReturnType).getBoxedType(myCodeFragmentMember) : myReturnType);
addToMethodCallLocation(myElementFactory.createStatementFromText("if (" + varName + " != null) return " + varName + ";", null));
}
@@ -818,9 +879,14 @@ public class ExtractMethodProcessor implements MatchProvider {
myMethodCall = (PsiMethodCallExpression)((PsiReturnStatement)statement).getReturnValue().replace(myMethodCall);
}
else {
PsiStatement statement = myElementFactory.createStatementFromText("x();", null);
statement = (PsiStatement)addToMethodCallLocation(statement);
myMethodCall = (PsiMethodCallExpression)((PsiExpressionStatement)statement).getExpression().replace(myMethodCall);
if (myArtificialOutputVariable != null && myReturnType != PsiType.VOID) {
declareVariableAtMethodCallLocation(myArtificialOutputVariable.getName());
}
else {
PsiStatement statement = myElementFactory.createStatementFromText("x();", null);
statement = (PsiStatement)addToMethodCallLocation(statement);
myMethodCall = (PsiMethodCallExpression)((PsiExpressionStatement)statement).getExpression().replace(myMethodCall);
}
}
if (myHasReturnStatement && !myHasReturnStatementOutput && !hasNormalExit()) {
PsiStatement statement = myElementFactory.createStatementFromText("return;", null);
@@ -980,6 +1046,9 @@ public class ExtractMethodProcessor implements MatchProvider {
}
}
}
else if (myArtificialOutputVariable != null && !PsiType.VOID.equals(myReturnType)) {
body.add(myElementFactory.createStatementFromText("return " + myArtificialOutputVariable.getName() + ";", null));
}
return exitStatementCopy;
}
@@ -1012,7 +1081,9 @@ public class ExtractMethodProcessor implements MatchProvider {
statement = (PsiDeclarationStatement)addToMethodCallLocation(statement);
PsiVariable var = (PsiVariable)statement.getDeclaredElements()[0];
myMethodCall = (PsiMethodCallExpression)var.getInitializer();
var.getModifierList().replace(myOutputVariable.getModifierList());
if (myOutputVariable != null) {
var.getModifierList().replace(myOutputVariable.getModifierList());
}
return name;
}
@@ -1462,8 +1533,21 @@ public class ExtractMethodProcessor implements MatchProvider {
private boolean applyChosenClassAndExtract(List<PsiVariable> inputVariables, @Nullable Pass<ExtractMethodProcessor> extractPass)
throws PrepareFailedException {
myStatic = shouldBeStatic();
final Set<PsiField> fields = new LinkedHashSet<PsiField>();
if (!PsiUtil.isLocalOrAnonymousClass(myTargetClass) && (myTargetClass.getContainingClass() == null || myTargetClass.hasModifierProperty(PsiModifier.STATIC))) {
ElementNeedsThis needsThis = new ElementNeedsThis(myTargetClass);
ElementNeedsThis needsThis = new ElementNeedsThis(myTargetClass) {
@Override
protected void visitClassMemberReferenceElement(PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) {
if (classMember instanceof PsiField && !classMember.hasModifierProperty(PsiModifier.STATIC)) {
final PsiExpression expression = PsiTreeUtil.getParentOfType(classMemberReference, PsiExpression.class, false);
if (expression == null || !PsiUtil.isAccessedForWriting(expression)) {
fields.add((PsiField)classMember);
return;
}
}
super.visitClassMemberReferenceElement(classMember, classMemberReference);
}
};
for (int i = 0; i < myElements.length && !needsThis.usesMembers(); i++) {
PsiElement element = myElements[i];
element.accept(needsThis);
@@ -1475,6 +1559,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
myInputVariables = new InputVariables(inputVariables, myProject, new LocalSearchScope(myElements), true);
myInputVariables.setUsedInstanceFields(fields);
if (!checkExitPoints()){
return false;
@@ -1561,12 +1646,12 @@ public class ExtractMethodProcessor implements MatchProvider {
}
public boolean hasDuplicates(Set<VirtualFile> files) {
initDuplicates();
final DuplicatesFinder finder = initDuplicates();
if (hasDuplicates()) return true;
final PsiManager psiManager = PsiManager.getInstance(myProject);
for (VirtualFile file : files) {
if (!myDuplicatesFinder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true;
if (!finder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true;
}
return false;
}
@@ -118,7 +118,10 @@ public class ReassignVariableUtil {
};
PsiElement scope = declaration;
while (scope != null) {
if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break;
if (scope instanceof PsiFile ||
scope instanceof PsiMethod ||
scope instanceof PsiLambdaExpression ||
scope instanceof PsiClassInitializer) break;
scope = scope.getParent();
}
if (scope == null) return proc;
@@ -205,7 +205,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
}
}
private PsiType[] getTypesForAll(final boolean areTypesDirected) {
protected PsiType[] getTypesForAll(final boolean areTypesDirected) {
final ArrayList<ExpectedTypeInfo[]> expectedTypesFromAll = new ArrayList<ExpectedTypeInfo[]>();
for (PsiExpression occurrence : myOccurrences) {
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider, isUsedAfter());
@@ -24,7 +24,6 @@ import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
@@ -168,30 +167,16 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
myDefaultNotNull = defaultNotNull;
}
private static boolean skipAnnotation(@NotNull PsiAnnotation annotation, @NotNull PsiModifierListOwner owner) {
return owner instanceof PsiMethod &&
PsiUtil.canBeOverriden((PsiMethod)owner) &&
AnnotationUtil.isInferredAnnotation(annotation) &&
AnnotationUtil.NOT_NULL.equals(annotation.getQualifiedName());
}
@Nullable
private PsiAnnotation findNullabilityAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean nullable) {
Set<String> qNames = ContainerUtil.newHashSet(nullable ? getNullables() : getNotNulls());
PsiAnnotation annotation = AnnotationUtil.findAnnotation(owner, qNames);
if (annotation != null && !skipAnnotation(annotation, owner)) {
PsiAnnotation annotation = checkBases && (owner instanceof PsiClass || owner instanceof PsiMethod)
? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
: AnnotationUtil.findAnnotation(owner, qNames);
if (annotation != null) {
return annotation;
}
if (checkBases && owner instanceof PsiMethod) {
for (PsiModifierListOwner superOwner : AnnotationUtil.getSuperAnnotationOwners(owner)) {
annotation = AnnotationUtil.findAnnotation(superOwner, qNames);
if (annotation != null && !skipAnnotation(annotation, superOwner)) {
return annotation;
}
}
}
PsiType type = getOwnerType(owner);
if (type == null || TypeConversionUtil.isPrimitiveAndNotNull(type)) return null;
@@ -317,7 +302,6 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
}
try {
//noinspection deprecation
DefaultJDOMExternalizer.writeExternal(this, component);
}
catch (WriteExternalException e) {
@@ -329,7 +313,6 @@ public class NullableNotNullManager implements PersistentStateComponent<Element>
@Override
public void loadState(Element state) {
try {
//noinspection deprecation
DefaultJDOMExternalizer.readExternal(this, state);
if (myNullables.isEmpty()) {
Collections.addAll(myNullables, DEFAULT_NULLABLES);
@@ -514,7 +514,8 @@ public final class PsiUtil extends PsiUtilCore {
PsiType lastParmType = getParameterType(lastParameter, languageLevel, substitutorForMethod);
if (!(lastParmType instanceof PsiArrayType)) return ApplicabilityLevel.NOT_APPLICABLE;
lastParmType = ((PsiArrayType)lastParmType).getComponentType();
if (lastParmType instanceof PsiCapturedWildcardType && !JavaVersionService.getInstance().isAtLeast(lastParameter, JavaSdkVersion.JDK_1_8)) {
if (lastParmType instanceof PsiCapturedWildcardType &&
!JavaVersionService.getInstance().isAtLeast(((PsiCapturedWildcardType)lastParmType).getContext(), JavaSdkVersion.JDK_1_8)) {
lastParmType = ((PsiCapturedWildcardType)lastParmType).getWildcard();
}
for (int i = parms.length - 1; i < args.length; i++) {
@@ -240,7 +240,7 @@ public class PsiReferenceExpressionImpl extends PsiReferenceExpressionBase imple
private JavaResolveResult[] resolve(IElementType parentType, @NotNull PsiFile containingFile) {
if (parentType == JavaElementType.REFERENCE_EXPRESSION) {
JavaResolveResult[] result = resolveToVariable(containingFile);
if (result.length > 0) {
if (result.length == 1 && result[0].isAccessible()) {
return result;
}
@@ -0,0 +1,11 @@
class C {
private int id;
}
class A extends C {
{
<error descr="Cannot resolve symbol 'id'">id</error>.MyObject.fromInt(1);
<error descr="'id' has private access in 'C'">id</error>.MyObject o;
}
}
@@ -0,0 +1,14 @@
// "Create Local Variable 'v'" "true"
public class A {
void foo() {
L l = () -> {
MyException v;
throw v
}
}
interface L {
void g() throws MyException;
}
class MyException extends Exception {}
}
@@ -0,0 +1,13 @@
// "Create Local Variable 'v'" "true"
public class A {
void foo() {
L l = () -> {
throw v<caret>
}
}
interface L {
void g() throws MyException;
}
class MyException extends Exception {}
}
@@ -2346,11 +2346,6 @@
<item name="java.lang.System void checkKey(java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>
<item name="java.lang.System void exit(int)">
<annotation name="org.jetbrains.annotations.Contract">
<val val="&quot;_ -&gt; fail&quot;"/>
</annotation>
</item>
<item name="java.lang.System void setProperties(java.util.Properties) 0">
<annotation name="org.jetbrains.annotations.Nullable"/>
</item>
@@ -3834,18 +3834,12 @@
<item name="org.apache.commons.lang.Validate void notEmpty(java.util.Map, java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>
<!-- hardcoded start -->
<item name="org.apache.commons.lang.Validate void notNull(java.lang.Object)">
<annotation name="org.jetbrains.annotations.Contract">
<val val="value = &quot;null -&gt; fail&quot;, pure = true"/>
</annotation>
<item name="org.apache.commons.lang.Validate void notNull(java.lang.Object) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>
<item name="org.apache.commons.lang.Validate void notNull(java.lang.Object, java.lang.String)">
<annotation name="org.jetbrains.annotations.Contract">
<val val="value = &quot;null, _ -&gt; fail&quot;, pure = true"/>
</annotation>
<item name="org.apache.commons.lang.Validate void notNull(java.lang.Object, java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NotNull"/>
</item>
<!-- hardcoded end -->
<item name="org.apache.commons.lang.WordUtils WordUtils()">
<annotation name="org.jetbrains.annotations.Contract">
<val val="pure=true"/>
@@ -0,0 +1,14 @@
class Fun {
public static final boolean isDebug = true;
void foo() {
if (isDebug) {
System.out.println();
}
}
void fooNegated() {
if (!isDebug) {
System.out.println();
}
}
}
@@ -0,0 +1,6 @@
class X {
private int myI;
void foo() {
<selection>int i = myI++;</selection>
}
}
@@ -0,0 +1,12 @@
class Test {
Integer method() {
<selection>try {
if(cond1) return 0;
else if(cond2) return null;
System.out.println("Text");
} finally {
doSomething();
}</selection>
return 12;
}
}
@@ -0,0 +1,21 @@
import org.jetbrains.annotations.Nullable;
class Test {
int method() {
Integer x = newMethod();
if (x != null) return x;
return 12;
}
@Nullable
private Integer newMethod() {
try {
if(cond1) return 0;
else if(cond2) return 1;
System.out.println("Text");
} finally {
doSomething();
}
return null;
}
}
@@ -0,0 +1,5 @@
class X {
void foo() {
<selection>int x = 0;</selection>
}
}
@@ -0,0 +1,10 @@
class X {
void foo() {
int x = newMethod();
}
private int newMethod() {
int x = 0;
return x;
}
}
@@ -0,0 +1,7 @@
class X {
void foo() {
<selection>int x = 0;
int y = 42;
</selection>
}
}
@@ -0,0 +1,11 @@
class X {
void foo() {
newMethod();
}
private int newMethod() {
int x = 0;
int y = 42;
}
}
@@ -0,0 +1,6 @@
class X {
private int myI;
void foo() {
<selection>int i = myI;</selection>
}
}
@@ -0,0 +1,10 @@
class X {
private int myI;
void foo() {
newMethod(myI);
}
private static void newMethod(int myI) {
int i = myI;
}
}
@@ -0,0 +1,13 @@
class Test {
String foo(boolean b) {
<selection>
if (b) {
return "a";
}
if (!b) {
return "b";
}
</selection>
return "42";
}
}
@@ -391,6 +391,7 @@ public class LightAdvHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testIDEA18343() { doTest(false, false); }
public void testNewExpressionClass() { doTest(false, false); }
public void testInnerClassObjectLiteralFromSuperExpression() { doTest(false, false); }
public void testPrivateFieldInSuperClass() { doTest(false, false); }
public void testNoEnclosingInstanceWhenStaticNestedInheritsFromContainingClass() throws Exception {
doTest(false, false);
@@ -126,7 +126,7 @@ public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
doAutoPopupTest("instanceof", null);
}
public void testDoNotAutoCompleteCompletionElementIfTemplateUnique() {
public void testDoNotAutoCompleteCompletionElementIfTemplateUnique() {
LiveTemplateCompletionContributor.ourShowTemplatesInTests = true;
configureByFile();
myFixture.completeBasic();
@@ -239,6 +239,28 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase {
assert c == []
}
public void "test return boxed integer"() {
def c = inferContracts("""
static Object test1(Object o1) {
return o1 == null ? 1 : smth();
}
static native Object smth()
""")
assert c == ['null -> !null']
}
public void "test return boxed boolean"() {
def c = inferContracts("""
static Object test1(Object o1) {
return o1 == null ? false : smth();
}
static native Object smth()
""")
assert c == ['null -> !null']
}
public void "test boolean autoboxing in delegation"() {
def c = inferContracts("""
static Boolean test04(String s) {
@@ -391,6 +413,15 @@ class ContractInferenceFromSourceTest extends LightCodeInsightFixtureTestCase {
assert c == ['null -> null']
}
public void "test compare with string literal"() {
def c = inferContracts("""
String cast(String s) {
return s == "a" ? "b" : null;
}
""")
assert c == []
}
public void "test return after if without else"() {
def c = inferContracts("""
public static boolean isBlank(String s) {
@@ -184,6 +184,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
public void testUnknownFloatMayBeNaN() { doTest(); }
public void testFloatEquality() { doTest(); }
public void testLastConstantConditionInAnd() { doTest(); }
public void testCompileTimeConstant() { doTest(); }
public void testTransientFinalField() { doTest(); }
public void testRememberLocalTransientFieldState() { doTest(); }
@@ -42,6 +42,17 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
assert inferNullity(parse('String foo() { return bar(); }; String bar() { return "z"; }; ')) == NOT_NULL
}
void "test same delegate method invoked twice"() {
assert inferNullity(parse('''
String foo() {
if (equals(2)) return bar();
if (equals(3)) return bar();
return "abc";
}
String bar() { return "z"; }
''')) == NOT_NULL
}
void "test if branch returns null"() {
assert inferNullity(parse('String bar() { if (equals(2)) return null; return "a"; }; ')) == NULLABLE
}
@@ -50,9 +61,21 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
assert inferNullity(parse('String foo() { return bar(); }; String bar() { if (equals(2)) return null; return "a"; }; ')) == UNKNOWN
}
void "test return boxed boolean constant"() {
assert inferNullity(parse('Object foo() { return true; }')) == NOT_NULL
}
void "test return boxed boolean value"() {
assert inferNullity(parse('Object foo(Object o) { return o == null; }')) == NOT_NULL
}
void "test return boxed integer"() {
assert inferNullity(parse('Object foo() { return 1; }')) == NOT_NULL
}
protected abstract Nullness inferNullity(PsiMethod method)
private PsiMethod parse(String method) {
protected PsiMethod parse(String method) {
return myFixture.addClass("final class Foo { $method }").methods[0]
}
@@ -60,6 +83,10 @@ abstract class NullityInferenceFromSourceTestCase extends LightCodeInsightFixtur
Nullness inferNullity(PsiMethod method) {
return NullableNotNullManager.isNotNull(method) ? NOT_NULL : NullableNotNullManager.isNullable(method) ? NULLABLE : UNKNOWN
}
void "test skip when errors"() {
assert inferNullity(parse('String foo() { if(); return 2; } ')) == UNKNOWN
}
}
static class DfaInferenceTest extends NullityInferenceFromSourceTestCase {
@@ -17,7 +17,6 @@ package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ExternalAnnotationsManager;
import com.intellij.codeInsight.InferredAnnotationsManager;
import com.intellij.codeInsight.daemon.GutterMark;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.projectRoots.Sdk;
@@ -257,7 +256,7 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
@Nullable
private PsiAnnotation findInferredAnnotation(PsiModifierListOwner owner, String fqn) {
return InferredAnnotationsManager.getInstance(myModule.getProject()).findInferredAnnotation(owner, fqn);
return ProjectBytecodeAnalysis.getInstance(getProject()).findInferredAnnotation(owner, fqn);
}
@Nullable
@@ -16,7 +16,6 @@
package com.intellij.codeInspection.bytecodeAnalysis;
import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.InferredAnnotationsManager;
import com.intellij.codeInspection.bytecodeAnalysis.asm.LeakingParameters;
import com.intellij.codeInspection.bytecodeAnalysis.data.*;
import com.intellij.openapi.util.io.FileUtil;
@@ -48,7 +47,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
public static final String ORG_JETBRAINS_ANNOTATIONS_CONTRACT = Contract.class.getName();
private final String myClassesProjectRelativePath = "/classes/" + Test01.class.getPackage().getName().replace('.', '/');
private JavaPsiFacade myJavaPsiFacade;
private InferredAnnotationsManager myInferredAnnotationsManager;
private ProjectBytecodeAnalysis myBytecodeAnalysisService;
private MessageDigest myMessageDigest;
@@ -56,7 +55,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
protected void setUp() throws Exception {
super.setUp();
myJavaPsiFacade = JavaPsiFacade.getInstance(myModule.getProject());
myInferredAnnotationsManager = InferredAnnotationsManager.getInstance(myModule.getProject());
myBytecodeAnalysisService = ProjectBytecodeAnalysis.getInstance(myModule.getProject());
myMessageDigest = MessageDigest.getInstance("MD5");
setUpDataClasses();
}
@@ -131,7 +130,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
params: for (int i = 0; i < annotations.length; i++) {
Annotation[] parameterAnnotations = annotations[i];
PsiParameter psiParameter = psiMethod.getParameterList().getParameters()[i];
PsiAnnotation inferredAnnotation = myInferredAnnotationsManager.findInferredAnnotation(psiParameter, AnnotationUtil.NOT_NULL);
PsiAnnotation inferredAnnotation = myBytecodeAnalysisService.findInferredAnnotation(psiParameter, AnnotationUtil.NOT_NULL);
for (Annotation parameterAnnotation : parameterAnnotations) {
if (parameterAnnotation.annotationType() == ExpectNotNull.class) {
assertNotNull(javaMethod.toString() + " " + i, inferredAnnotation);
@@ -143,13 +142,13 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
// not-null result
ExpectNotNull expectedAnnotation = javaMethod.getAnnotation(ExpectNotNull.class);
PsiAnnotation actualAnnotation = myInferredAnnotationsManager.findInferredAnnotation(psiMethod, AnnotationUtil.NOT_NULL);
PsiAnnotation actualAnnotation = myBytecodeAnalysisService.findInferredAnnotation(psiMethod, AnnotationUtil.NOT_NULL);
assertEquals(javaMethod.toString(), expectedAnnotation == null, actualAnnotation == null);
// contracts
ExpectContract expectedContract = javaMethod.getAnnotation(ExpectContract.class);
PsiAnnotation actualContract = myInferredAnnotationsManager.findInferredAnnotation(psiMethod, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
PsiAnnotation actualContract = myBytecodeAnalysisService.findInferredAnnotation(psiMethod, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
String expectedText = expectedContract == null ? "null" : expectedContract.toString();
String inferredText = actualContract == null ? "null" : actualContract.getText();
@@ -252,7 +252,8 @@ public class IndexTest extends JavaCodeInsightFixtureTestCase {
((VirtualFileSystemEntry)vFile).setModificationStamp(0); // as unchanged file
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
assertTrue(document != null && document.getModificationStamp() == 0);
assertTrue(document != null);
assert document.getModificationStamp() == 0;
assertNotNull(findClass("Foo"));
WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@@ -58,6 +58,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
}
public void testExitPoints4() throws Exception {
doTest();
}
public void testExitPoints4Nullable() throws Exception {
doExitPointsTest(false);
}
@@ -625,6 +629,28 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doTestReturnTypeChanged(PsiType.getJavaLangObject(getPsiManager(), GlobalSearchScope.allScope(getProject())));
}
public void testMakeVoidMethodReturnVariable() throws Exception {
doTestReturnTypeChanged(PsiType.INT);
}
public void testMultipleVarsInMethodNoReturnStatementAndAssignment() throws Exception {
//return type should not be suggested but still
doTestReturnTypeChanged(PsiType.INT);
}
public void testPassFieldAsParameterAndMakeStatic() throws Exception {
doTestPassFieldsAsParams();
}
public void testCantPassFieldAsParameter() throws Exception {
try {
doTestPassFieldsAsParams();
fail("Field was modified inside. Make static should be disabled");
}
catch (PrepareFailedException ignore) {
}
}
private void doTestDisabledParam() throws PrepareFailedException {
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.ELSE_ON_NEW_LINE = true;
@@ -640,7 +666,17 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
settings.ELSE_ON_NEW_LINE = true;
settings.CATCH_ON_NEW_LINE = myCatchOnNewLine;
configureByFile(BASE_PATH + getTestName(false) + ".java");
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type);
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type, false);
assertTrue(success);
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
private void doTestPassFieldsAsParams() throws PrepareFailedException {
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.ELSE_ON_NEW_LINE = true;
settings.CATCH_ON_NEW_LINE = myCatchOnNewLine;
configureByFile(BASE_PATH + getTestName(false) + ".java");
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, true);
assertTrue(success);
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
@@ -700,7 +736,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
final boolean extractChainedConstructor,
int... disabledParams)
throws PrepareFailedException, IncorrectOperationException {
return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, disabledParams);
return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, false, disabledParams);
}
public static boolean performExtractMethod(boolean doRefactor,
@@ -710,6 +746,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
Project project,
final boolean extractChainedConstructor,
PsiType returnType,
boolean makeStatic,
int... disabledParams)
throws PrepareFailedException, IncorrectOperationException {
int startOffset = editor.getSelectionModel().getSelectionStart();
@@ -741,7 +778,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
}
if (doRefactor) {
processor.testPrepare(returnType);
processor.testPrepare(returnType, makeStatic);
processor.testNullness();
if (disabledParams != null) {
for (int param : disabledParams) {
@@ -20,6 +20,7 @@ public class ReplaceMethodDuplicatesTestSuite {
testSuite.addTestSuite(FindMethodDuplicatesMiscTest.class);
testSuite.addTestSuite(FindMethodDuplicatesTest.class);
testSuite.addTestSuite(SuggestedParamTypesTest.class);
testSuite.addTestSuite(SuggestedReturnTypesTest.class);
return testSuite;
}
}
@@ -61,6 +61,10 @@ public class SuggestedReturnTypesTest extends LightCodeInsightTestCase {
doTest("Integer", "int");
}
public void testOutputUsedInReturn() throws Exception {
doTest("String");
}
private void doTest(String... types) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
@@ -115,11 +115,11 @@ public class HighlightDisplayLevel {
@NotNull
public static Icon createIconByMask(final Color renderColor) {
return new MyColorIcon(EMPTY_ICON_DIM, renderColor);
return new TheColorIcon(EMPTY_ICON_DIM, renderColor);
}
private static class MyColorIcon extends ColorIcon implements ColoredIcon {
public MyColorIcon(int size, @NotNull Color color) {
public static class TheColorIcon extends ColorIcon implements ColoredIcon {
public TheColorIcon(int size, @NotNull Color color) {
super(size, color);
}
@@ -93,7 +93,9 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator<Highlig
myRendererColors.put(severity.getName(), renderColor);
}
myOrderMap = null;
HighlightDisplayLevel.registerSeverity(severity, getHighlightInfoTypeBySeverity(severity).getAttributesKey());
Color color = info.getAttributes().getErrorStripeColor();
new HighlightDisplayLevel(severity, new HighlightDisplayLevel.TheColorIcon(HighlightDisplayLevel.EMPTY_ICON_DIM, color));
severitiesChanged();
}
@@ -324,6 +324,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
VirtualFile file = viewProvider.getVirtualFile();
msg += "; file stamp: " + file.getModificationStamp();
msg += "; file modCount: " + file.getModificationCount();
msg += "; file length: " + file.getLength();
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
if (document != null) {
@@ -332,6 +333,8 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
msg += "; doc size: " + document.getTextLength();
msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document);
}
msg += "\nindexing info: " + StubTreeLoader.getInstance().getIndexingStampDebugInfo(file);
throw new AssertionError(msg + "\n------------\n");
}
@@ -87,4 +87,9 @@ public class CoreStubTreeLoader extends StubTreeLoader {
}
return false;
}
@Override
public String getIndexingStampDebugInfo(VirtualFile file) {
return "";
}
}
@@ -41,4 +41,6 @@ public abstract class StubTreeLoader {
public abstract long getStubTreeTimestamp(VirtualFile vFile);
public abstract boolean canHaveStub(VirtualFile file);
public abstract String getIndexingStampDebugInfo(VirtualFile file);
}
@@ -20,7 +20,6 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.PossiblyDumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NonNls;
@@ -229,7 +228,7 @@ public abstract class AnAction implements PossiblyDumbAware {
*
* @param e Carries information on the invocation place and data available
*/
public void update(@NotNull AnActionEvent e) {
public void update(AnActionEvent e) {
}
/**
@@ -268,7 +267,7 @@ public abstract class AnAction implements PossiblyDumbAware {
*
* @param e Carries information on the invocation place
*/
public abstract void actionPerformed(@NotNull AnActionEvent e);
public abstract void actionPerformed(AnActionEvent e);
protected void setShortcutSet(ShortcutSet shortcutSet) {
myShortcutSet = shortcutSet;
@@ -84,7 +84,7 @@ public class DocumentMarkupModel {
if (create && model == null) {
MarkupModelImpl newModel = new MarkupModelImpl((DocumentEx)document);
if ((model = ConcurrencyUtil.cacheOrGet(markupModelMap, project, newModel)) == newModel) {
documentMarkupModelManager.registerDocument((DocumentImpl)document);
documentMarkupModelManager.registerDocument(document);
}
else {
newModel.dispose();
@@ -18,6 +18,7 @@ package com.intellij.openapi.editor.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.WeakList;
@@ -29,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
public class DocumentMarkupModelManager extends AbstractProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentMarkupModelManager");
private final WeakList<DocumentImpl> myDocumentSet = new WeakList<DocumentImpl>();
private final WeakList<Document> myDocumentSet = new WeakList<Document>();
private volatile boolean myDisposed;
public static DocumentMarkupModelManager getInstance(Project project) {
@@ -46,7 +47,7 @@ public class DocumentMarkupModelManager extends AbstractProjectComponent {
});
}
public void registerDocument(DocumentImpl document) {
public void registerDocument(Document document) {
LOG.assertTrue(!myDisposed);
myDocumentSet.add(document);
}
@@ -58,7 +59,7 @@ public class DocumentMarkupModelManager extends AbstractProjectComponent {
private void cleanupProjectMarkups() {
if (!myDisposed) {
myDisposed = true;
for (DocumentImpl document : myDocumentSet.toStrongList()) {
for (Document document : myDocumentSet.toStrongList()) {
DocumentMarkupModel.removeMarkupModel(document, myProject);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,7 +58,7 @@ public class EditScopesDialog extends SettingsDialog {
}
@Override
protected void doOKAction() {
public void doOKAction() {
Object selectedObject = myConfigurable.getSelectedObject();
mySelectedScope = selectedObject instanceof NamedScope ? (NamedScope)selectedObject : null;
@@ -29,6 +29,7 @@ import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.profile.codeInspection.ui.table.SeverityRenderer;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -65,7 +66,7 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA
group.addSeparator();
group.add(new DumbAwareAction("Edit severities...") {
@Override
public void actionPerformed(final AnActionEvent e) {
public void actionPerformed(@NotNull final AnActionEvent e) {
final SeverityEditorDialog dlg = new SeverityEditorDialog(anchor, myChosen, mySeverityRegistrar);
if (dlg.showAndGet()) {
final HighlightInfoType type = dlg.getSelectedType();
@@ -98,7 +99,7 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA
myChosen = severity;
final Presentation templatePresentation = getTemplatePresentation();
templatePresentation.setText(SingleInspectionProfilePanel.renderSeverity(severity));
templatePresentation.setIcon(HighlightDisplayLevel.find(severity).getIcon());
templatePresentation.setIcon(SeverityRenderer.getIcon(HighlightDisplayLevel.find(severity)));
}
private class HighlightSeverityAction extends DumbAwareAction {
@@ -112,11 +113,11 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA
mySeverity = severity;
final Presentation presentation = getTemplatePresentation();
presentation.setText(SingleInspectionProfilePanel.renderSeverity(severity));
presentation.setIcon(HighlightDisplayLevel.find(severity).getIcon());
presentation.setIcon(SeverityRenderer.getIcon(HighlightDisplayLevel.find(severity)));
}
@Override
public void actionPerformed(final AnActionEvent e) {
public void actionPerformed(@NotNull final AnActionEvent e) {
final HighlightSeverity severity = getSeverity();
setChosen(severity);
onChosen(severity);
@@ -548,12 +548,12 @@ public class SingleInspectionProfilePanel extends JPanel {
actions.add(new DumbAwareAction("Reset to Empty", "Reset to empty", AllIcons.Actions.Reset_to_empty){
@Override
public void update(AnActionEvent e) {
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(mySelectedProfile != null && mySelectedProfile.isExecutable(myProjectProfileManager.getProject()));
}
@Override
public void actionPerformed(AnActionEvent e) {
public void actionPerformed(@NotNull AnActionEvent e) {
mySelectedProfile.resetToEmpty(e.getProject());
loadDescriptorsConfigs(false);
postProcessModification();
@@ -753,7 +753,7 @@ public class SingleInspectionProfilePanel extends JPanel {
final HighlightDisplayLevel level = HighlightDisplayLevel.find(severity);
group.add(new AnAction(renderSeverity(severity), renderSeverity(severity), level.getIcon()) {
@Override
public void actionPerformed(AnActionEvent e) {
public void actionPerformed(@NotNull AnActionEvent e) {
setNewHighlightingLevel(level);
}
@@ -25,6 +25,7 @@ import com.intellij.profile.codeInspection.ui.LevelChooserAction;
import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ColorIcon;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -58,6 +59,13 @@ public class SeverityRenderer extends ComboBoxTableRenderer<SeverityState> {
}), onClose);
}
public static Icon getIcon(@NotNull HighlightDisplayLevel level) {
Icon icon = level.getIcon();
return icon instanceof HighlightDisplayLevel.ColoredIcon
? new ColorIcon(icon.getIconWidth(), ((HighlightDisplayLevel.ColoredIcon)icon).getColor())
: icon;
}
@Override
protected void customizeComponent(SeverityState value, JTable table, boolean isSelected) {
super.customizeComponent(value, table, isSelected);
@@ -73,7 +81,7 @@ public class SeverityRenderer extends ComboBoxTableRenderer<SeverityState> {
@Override
protected Icon getIconFor(@NotNull final SeverityState value) {
return HighlightDisplayLevel.find(value.getSeverity()).getIcon();
return getIcon(HighlightDisplayLevel.find(value.getSeverity()));
}
@Override
@@ -167,4 +167,9 @@ public class StubTreeLoaderImpl extends StubTreeLoader {
public boolean canHaveStub(VirtualFile file) {
return StubUpdatingIndex.canHaveStub(file);
}
@Override
public String getIndexingStampDebugInfo(VirtualFile file) {
return StubUpdatingIndex.getIndexingStampInfo(file);
}
}
@@ -51,6 +51,7 @@ import com.intellij.util.PlatformIcons;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.table.JBListTable;
import com.intellij.util.ui.table.JBTableRowEditor;
import com.intellij.util.ui.table.JBTableRowRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -458,37 +459,7 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
myPropagateParamChangesButton.setShortcut(CustomShortcutSet.fromString("alt G"));
if (isListTableViewSupported() && Registry.is("change.signature.awesome.mode")) {
myParametersList = new JBListTable(myParametersTable) {
@Override
protected JComponent getRowRenderer(JTable table, int row, boolean selected, boolean focused) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
return getRowPresentation(items.get(row), selected, focused);
}
@Override
protected boolean isRowEmpty(int row) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
return isEmptyRow(items.get(row));
}
@Override
protected JBTableRowEditor getRowEditor(final int row) {
final List<ParameterTableModelItem> items = myParametersTable.getItems();
JBTableRowEditor editor = getTableEditor(myParametersList.getTable(), items.get(row));
LOG.assertTrue(editor != null);
editor.addDocumentListener(new JBTableRowEditor.RowDocumentListener() {
@Override
public void documentChanged(DocumentEvent e, int column) {
if (myParametersTableModel.getColumnClass(column).equals(String.class)) {
myParametersTableModel.setValueAtWithoutUpdate(e.getDocument().getText(), row, column);
}
updateSignature();
}
});
return editor;
}
};
myParametersList = createParametersListTable();
final JPanel buttonsPanel = ToolbarDecorator.createDecorator(myParametersList.getTable())
.addExtraAction(myPropagateParamChangesButton)
.createPanel();
@@ -512,15 +483,56 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
}
}
protected ParametersListTable createParametersListTable() {
return new ParametersListTable() {
@Override
protected JBTableRowRenderer getRowRenderer(int row) {
return new JBTableRowRenderer() {
@Override
public JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused) {
JComponent presentation = getRowPresentation(getRowItem(row), selected, focused);
LOG.assertTrue(presentation != null);
return presentation;
}
};
}
@NotNull
@Override
protected JBTableRowEditor getRowEditor(ParameterTableModelItemBase<ParamInfo> item) {
JBTableRowEditor editor = ChangeSignatureDialogBase.this.getTableEditor(getTable(), item);
LOG.assertTrue(editor != null);
return editor;
}
@Override
protected boolean isRowEmpty(int row) {
return ChangeSignatureDialogBase.this.isEmptyRow(getRowItem(row));
}
};
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
@Nullable
protected JBTableRowEditor getTableEditor(JTable table, ParameterTableModelItemBase<ParamInfo> item) {
return null;
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
protected boolean isEmptyRow(ParameterTableModelItemBase<ParamInfo> row) {
return false;
}
/**
* @deprecated override {@link #createParametersListTable} instead.
*/
@Deprecated
@Nullable
protected JComponent getRowPresentation(ParameterTableModelItemBase<ParamInfo> item, boolean selected, boolean focused) {
return null;
@@ -673,4 +685,35 @@ public abstract class ChangeSignatureDialogBase<ParamInfo extends ParameterInfo,
public void beforeDocumentChange(DocumentEvent event) {
}
}
protected abstract class ParametersListTable extends JBListTable {
public ParametersListTable() {
super(myParametersTable);
}
@Override
protected final JBTableRowEditor getRowEditor(final int row) {
JBTableRowEditor editor = getRowEditor(getRowItem(row));
editor.addDocumentListener(new JBTableRowEditor.RowDocumentListener() {
@Override
public void documentChanged(DocumentEvent e, int column) {
if (String.class.equals(myParametersTableModel.getColumnClass(column))) {
myParametersTableModel.setValueAtWithoutUpdate(e.getDocument().getText(), row, column);
}
updateSignature();
}
});
return editor;
}
@NotNull
protected abstract JBTableRowEditor getRowEditor(ParameterTableModelItemBase<ParamInfo> item);
@Override
protected abstract boolean isRowEmpty(int row);
protected ParameterTableModelItem getRowItem(int row) {
return myParametersTable.getItems().get(row);
}
}
}
@@ -23,7 +23,9 @@ public abstract class CachesInvalidator {
/**
* @return description of the caches to be cleared, shown in the warning dialog to the user
* @return description of the files to be cleared, shown in the warning dialog to the user.
* When to use: when invalidation will lead to the loss of a potentially valuable to the user information, e.g. Local History.
* Do not use: when caches are easily re-buildable and doesn't contain user's data (to avoid unnecessary confusion).
*/
@Nullable
public String getDescription() { return null; }
@@ -58,7 +58,7 @@ public abstract class CheckboxAction extends ToggleAction implements CustomCompo
ActionManager.getInstance(), 0));
}
});
updateCustomComponent(checkBox, presentation);
return checkBox;
}
@@ -70,14 +70,17 @@ public abstract class CheckboxAction extends ToggleAction implements CustomCompo
if (property instanceof JCheckBox) {
JCheckBox checkBox = (JCheckBox)property;
checkBox.setText(presentation.getText());
checkBox.setToolTipText(presentation.getDescription());
checkBox.setMnemonic(presentation.getMnemonic());
checkBox.setDisplayedMnemonicIndex(presentation.getDisplayedMnemonicIndex());
checkBox.setSelected(Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)));
checkBox.setEnabled(presentation.isEnabled());
checkBox.setVisible(presentation.isVisible());
updateCustomComponent(checkBox, presentation);
}
}
protected void updateCustomComponent(JCheckBox checkBox, Presentation presentation) {
checkBox.setText(presentation.getText());
checkBox.setToolTipText(presentation.getDescription());
checkBox.setMnemonic(presentation.getMnemonic());
checkBox.setDisplayedMnemonicIndex(presentation.getDisplayedMnemonicIndex());
checkBox.setSelected(Boolean.TRUE.equals(presentation.getClientProperty(SELECTED_PROPERTY)));
checkBox.setEnabled(presentation.isEnabled());
checkBox.setVisible(presentation.isVisible());
}
}
@@ -190,6 +190,7 @@ public abstract class FocusCommand extends ActiveRunnable implements Expirable {
});
}
if (commandCreationTime > lastProcessedCommandTime) {
if (!(myToFocus.requestFocusInWindow())) {
if (shouldLogFocuses) {
@@ -25,7 +25,7 @@ import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
public abstract class GroupedElementsRenderer {
public static final Color POPUP_SEPARATOR_FOREGROUND = new JBColor(Color.gray.brighter(), Gray._43);
public static final Color POPUP_SEPARATOR_FOREGROUND = new JBColor(Color.gray.brighter(), Gray.x51);
public static final Color POPUP_SEPARATOR_TEXT_FOREGROUND = Color.gray;
public static final Color SELECTED_FRAME_FOREGROUND = Color.black;
@@ -120,8 +120,7 @@ class TableToolbarDecorator extends ToolbarDecorator {
table.setColumnSelectionInterval(0, 0);
table.editCellAt(index, 0);
boolean temporaryHideVerticalScrollBar = table.getCellEditor() instanceof Animated;
TableUtil.updateScroller(table, temporaryHideVerticalScrollBar);
TableUtil.updateScroller(table);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
@@ -145,7 +144,7 @@ class TableToolbarDecorator extends ToolbarDecorator {
if (TableUtil.doRemoveSelectedItems(table, tableModel, null)) {
updateButtons();
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
};
@@ -29,6 +29,7 @@ import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.impl.ToolWindowImpl;
import com.intellij.ui.SizedIcon;
import com.intellij.ui.content.Content;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -102,14 +103,31 @@ public class ActivateToolWindowAction extends DumbAwareAction {
presentation.setIcon(icon == null ? null : new SizedIcon(icon, icon.getIconHeight(), icon.getIconHeight()));
}
public void actionPerformed(AnActionEvent e) {
public void actionPerformed(final AnActionEvent e) {
Project project = getEventProject(e);
if (project == null) return;
ToolWindowManager windowManager = ToolWindowManager.getInstance(project);
if (windowManager.isEditorComponentActive() || !myToolWindowId.equals(windowManager.getActiveToolWindowId())) {
windowManager.getToolWindow(myToolWindowId).activate(null);
final ToolWindow window = windowManager.getToolWindow(myToolWindowId);
InputEvent event = e.getInputEvent();
Runnable run = null;
if (event instanceof KeyEvent && event.isShiftDown()) {
final Content[] contents = window.getContentManager().getContents();
if (contents.length > 0 && window.getContentManager().getSelectedContent() != contents[0]) {
run = new Runnable() {
public void run() {
window.getContentManager().setSelectedContent(contents[0], true, true);
}
};
}
}
else {
if (windowManager.isEditorComponentActive() || !myToolWindowId.equals(windowManager.getActiveToolWindowId()) || run != null) {
if (run != null && window.isActive()) {
run.run();
} else {
window.activate(run);
}
} else {
windowManager.getToolWindow(myToolWindowId).hide(null);
}
}
@@ -18,7 +18,7 @@ package com.intellij.ide.plugins;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.options.newEditor.IdeSettingsDialog;
import com.intellij.openapi.options.newEditor.SettingsDialog;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.wm.IdeFocusManager;
@@ -281,8 +281,9 @@ public class PluginHeaderPanel {
public void run() {
final DialogWrapper settings =
DialogWrapper.findInstance(IdeFocusManager.findInstance().getFocusOwner());
if (settings instanceof IdeSettingsDialog) {
((IdeSettingsDialog)settings).doOKAction();
if (settings instanceof SettingsDialog) {
((SettingsDialog)settings).doOKAction();
ApplicationManager.getApplication().restart();
} else {
ApplicationManager.getApplication().restart();
}
@@ -65,7 +65,7 @@ TabbedPane.contentBorderInsets=3,1,1,1
TabbedPane.darkShadow=292b2d
TabbedPane.shadow=3c3f41
Separator.foreground=2d2d2d
Separator.foreground=515151
Focus.color=ff0000
@@ -25,7 +25,9 @@ import com.intellij.openapi.diff.impl.external.DiscloseMultiRequest;
import com.intellij.openapi.diff.impl.external.MultiLevelDiffTool;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.ui.content.Content;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,6 +35,7 @@ import javax.swing.*;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* Created with IntelliJ IDEA.
@@ -47,7 +50,7 @@ public class CompositeDiffPanel implements DiffViewer {
private final DiscloseMultiRequest myRequest;
private final Window myWindow;
private final Disposable myParentDisposable;
private final Map<String, DiffViewer> myMap;
private final Map<String, Pair<DiffViewer, Content>> myMap;
public CompositeDiffPanel(Project project, final DiscloseMultiRequest request, final Window window, @NotNull Disposable parentDisposable) {
myRequest = request;
@@ -57,7 +60,7 @@ public class CompositeDiffPanel implements DiffViewer {
myUi.getComponent().setBorder(null);
myUi.getOptions().setMinimizeActionEnabled(false);
//myUi.getOptions().setTopToolbar()
myMap = new HashMap<String, DiffViewer>();
myMap = new HashMap<String, Pair<DiffViewer, Content>>();
}
@Override
@@ -68,59 +71,47 @@ public class CompositeDiffPanel implements DiffViewer {
@Override
public void setDiffRequest(DiffRequest request) {
final Map<String, DiffRequest> requestMap = myRequest.discloseRequest(request);
final HashMap<String, DiffViewer> copy = new HashMap<String, DiffViewer>(myMap);
HashMap<String, Pair<DiffViewer, Content>> mapCopy = new HashMap<String, Pair<DiffViewer, Content>>(myMap);
myMap.clear();
for (Map.Entry<String, DiffRequest> entry : requestMap.entrySet()) {
final String key = entry.getKey();
final DiffRequest diffRequest = entry.getValue();
diffRequest.getGenericData().put(PlatformDataKeys.COMPOSITE_DIFF_VIEWER.getName(), this);
final DiffViewer viewer = copy.remove(key);
final Pair<DiffViewer, Content> pair = mapCopy.get(key);
DiffViewer viewer = pair != null ? pair.first : null;
if (viewer != null && viewer.acceptsType(diffRequest.getType()) && viewer.canShowRequest(diffRequest)) {
viewer.setDiffRequest(diffRequest);
myMap.put(key, pair);
mapCopy.remove(key);
} else {
if (viewer != null) {
removeTab(myUi.getContentManager().getContents(), key);
}
final DiffViewer newViewer = myRequest.viewerForRequest(myWindow, myParentDisposable, key, diffRequest);
if (newViewer == null) continue;
myMap.put(key, newViewer);
final Content content = myUi.createContent(key, newViewer.getComponent(), key, null, newViewer.getPreferredFocusedComponent());
content.setCloseable(false);
content.setPinned(true);
Disposer.register(myParentDisposable, new Disposable() {
@Override
public void dispose() {
myMap.remove(key);
myUi.removeContent(content, true);
}
});
content.setDisposer(myParentDisposable);
myUi.addContent(content);
myMap.put(key, Pair.create(newViewer, content));
if (pair != null) myUi.removeContent(pair.second, false);
}
}
final Content[] contents = myUi.getContentManager().getContents();
for (String s : copy.keySet()) {
removeTab(contents, s);
}
if (myMap.isEmpty()) {
final ErrorDiffViewer errorDiffViewer = new ErrorDiffViewer(request);
myMap.put(FICTIVE_KEY, errorDiffViewer);
final ErrorDiffViewer errorDiffViewer = new ErrorDiffViewer(myWindow, request);
final Content content = myUi.createContent(FICTIVE_KEY, errorDiffViewer.getComponent(), FICTIVE_KEY, null,
errorDiffViewer.getPreferredFocusedComponent());
content.setCloseable(false);
content.setPinned(true);
content.setDisposer(myParentDisposable);
myUi.addContent(content);
myMap.put(FICTIVE_KEY, Pair.<DiffViewer, Content>create(errorDiffViewer, content));
}
}
private void removeTab(Content[] contents, String s) {
myMap.remove(s);
for (Content content : contents) {
if (s.equals(content.getDisplayName())) {
myUi.getContentManager().removeContent(content, false);
break;
}
for (Pair<DiffViewer, Content> pair : mapCopy.values()) {
myUi.removeContent(pair.second, false);
if (pair.first instanceof Disposable) Disposer.dispose((Disposable)pair.first);
}
}
@@ -255,7 +255,10 @@ public class DiffSideView {
public JComponent getFocusableComponent() {
Editor editor = getEditor();
return editor != null ? editor.getContentComponent() : MOCK_COMPONENT;
if (editor != null) return editor.getContentComponent();
FileEditor fileEditor = myEditorSource.getFileEditor();
if (fileEditor != null) return fileEditor.getComponent();
return MOCK_COMPONENT;
}
public void becomeMaster() {
@@ -36,8 +36,64 @@ import java.awt.*;
public class ErrorDiffViewer implements DiffViewer {
@NotNull private final DiffRequest myRequest;
protected ErrorDiffViewer(@NotNull DiffRequest request) {
@NotNull private final JPanel myPanel;
@NotNull private final DiffToolbarComponent myToolbar;
protected ErrorDiffViewer(Window window, @NotNull DiffRequest request) {
myRequest = request;
myPanel = new AbstractDataProviderPanel(new BorderLayout(), false) {
@Override
public void calcData(DataKey key, DataSink sink) {
final Object data = myRequest.getGenericData().get(key.getName());
if (data != null) {
sink.put(key, data);
}
}
};
myPanel.setFocusable(true);
final ActionManager actionManager = ActionManager.getInstance();
myToolbar = new DiffToolbarComponent(myPanel);
final DiffRequest.ToolbarAddons addons = new DiffRequest.ToolbarAddons() {
@Override
public void customize(DiffToolbar toolbar) {
toolbar.addAction(actionManager.getAction("DiffPanel.Toolbar"));
toolbar.addAction(actionManager.getAction("ContextHelp"));
toolbar.addSeparator();
}
};
myToolbar.resetToolbar(addons);
final DiffToolbarImpl toolbar = myToolbar.getToolbar();
myRequest.customizeToolbar(toolbar);
/*group.addAction(actionManager.getAction("Diff.PrevChange"));
group.addAction(actionManager.getAction("Diff.NextChange"));*/
myPanel.add(myToolbar, BorderLayout.NORTH);
DiffContent content1 = myRequest.getContents()[0];
DiffContent content2 = myRequest.getContents()[1];
String message;
if (DiffUtil.oneIsUnknown(content1, content2)) {
message = DiffBundle.message("diff.can.not.show.unknown");
}
else {
message = DiffBundle.message("diff.can.not.show");
}
final JPanel messagePanel = createMessagePanel(message);
myPanel.add(messagePanel, BorderLayout.CENTER);
setWindowTitle(window, request.getWindowTitle());
}
private static void setWindowTitle(Window window, String title) {
if (title == null || title.isEmpty()) title = "Diff";
if (window instanceof JDialog) {
((JDialog)window).setTitle(title);
}
else if (window instanceof JFrame) ((JFrame)window).setTitle(title);
}
@Override
@@ -52,48 +108,7 @@ public class ErrorDiffViewer implements DiffViewer {
@Override
public JComponent getComponent() {
final JPanel result = new AbstractDataProviderPanel(new BorderLayout(), false) {
@Override
public void calcData(DataKey key, DataSink sink) {
final Object data = myRequest.getGenericData().get(key.getName());
if (data != null) {
sink.put(key, data);
}
}
};
final ActionManager actionManager = ActionManager.getInstance();
final DiffToolbarComponent toolbarComponent = new DiffToolbarComponent(result);
final DiffRequest.ToolbarAddons addons = new DiffRequest.ToolbarAddons() {
@Override
public void customize(DiffToolbar toolbar) {
toolbar.addAction(actionManager.getAction("DiffPanel.Toolbar"));
toolbar.addAction(actionManager.getAction("ContextHelp"));
toolbar.addSeparator();
}
};
toolbarComponent.resetToolbar(addons);
final DiffToolbarImpl toolbar = toolbarComponent.getToolbar();
myRequest.customizeToolbar(toolbar);
/*group.addAction(actionManager.getAction("Diff.PrevChange"));
group.addAction(actionManager.getAction("Diff.NextChange"));*/
result.add(toolbarComponent, BorderLayout.NORTH);
DiffContent content1 = myRequest.getContents()[0];
DiffContent content2 = myRequest.getContents()[1];
String message;
if (DiffUtil.oneIsUnknown(content1, content2)) {
message = DiffBundle.message("diff.can.not.show.unknown");
}
else {
message = DiffBundle.message("diff.can.not.show");
}
final JPanel messagePanel = createMessagePanel(message);
result.add(messagePanel, BorderLayout.CENTER);
return result;
return myPanel;
}
@NotNull
@@ -109,7 +124,7 @@ public class ErrorDiffViewer implements DiffViewer {
@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return null;
return myPanel;
}
@Override
@@ -432,6 +432,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
}
Color color = myEditor.getColorsScheme().getColor(EditorColors.LINE_NUMBERS_COLOR);
g.setColor(color != null ? color : JBColor.blue);
g.setFont(myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
Graphics2D g2 = (Graphics2D)g;
@@ -453,8 +454,10 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
if (logLine >= 0) {
String s = String.valueOf(logLine + 1);
int startY = (i + 1) * lineHeight;
Color fgColor = myTextFgColors.get(i);
g.setColor(fgColor != null ? fgColor : color != null ? color : JBColor.blue);
if (myEditor.isInDistractionFreeMode()) {
Color fgColor = myTextFgColors.get(i);
g.setColor(fgColor != null ? fgColor : color != null ? color : JBColor.blue);
}
g.drawString(s,
getLineNumberAreaOffset() + getLineNumberAreaWidth() -
myEditor.getFontMetrics(Font.PLAIN).stringWidth(s) -
@@ -17,10 +17,9 @@
package com.intellij.openapi.options.ex;
import com.intellij.ide.ui.search.SearchUtil;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
@@ -30,7 +29,6 @@ import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.Kernel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -60,19 +58,15 @@ public class GlassPanel extends JComponent {
public void paintSpotlight(final Graphics g, final JComponent surfaceComponent) {
Dimension size = surfaceComponent.getSize();
if (myLightComponents.size() > 0) {
int width = size.width - 1;
int height = size.height - 1;
int stroke = 2;
Rectangle2D screen = new Rectangle2D.Double(0, 0, width, height);
final Rectangle visibleRect = myPanel.getVisibleRect();
final Point leftPoint = SwingUtilities.convertPoint(myPanel, new Point(visibleRect.x, visibleRect.y), surfaceComponent);
Area innerPanel = new Area(new Rectangle2D.Double(leftPoint.x, leftPoint.y, visibleRect.width, visibleRect.height));
Area mask = new Area(screen);
ArrayList<JComponent> components = new ArrayList<JComponent>();
Area mask = new Area(new Rectangle(-stroke, -stroke, 2 * stroke + size.width, 2 * stroke + size.height));
for (JComponent lightComponent : myLightComponents) {
final Area area = getComponentArea(surfaceComponent, lightComponent, 1);
if (area == null) continue;
components.add(lightComponent);
if (lightComponent instanceof JLabel) {
final JLabel label = (JLabel)lightComponent;
@@ -80,7 +74,6 @@ public class GlassPanel extends JComponent {
if (labelFor instanceof JComponent) {
final Area labelForArea = getComponentArea(surfaceComponent, (JComponent)labelFor, 1);
if (labelForArea != null) {
components.add((JComponent)labelFor);
area.add(labelForArea);
}
}
@@ -89,35 +82,28 @@ public class GlassPanel extends JComponent {
area.intersect(innerPanel);
mask.subtract(area);
}
Graphics clip = g.create(0, 0, size.width, size.height);
try {
Graphics2D g2 = (Graphics2D)clip;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
Graphics2D g2 = (Graphics2D)g;
Color background = surfaceComponent.getBackground();
g2.setColor(ColorUtil.toAlpha(background == null ? null : background.darker(), 100));
g2.fill(mask);
Color shieldColor = new Color(0.0f, 0.0f, 0.0f, 0.20f);
Color boundsColor = Color.gray;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(shieldColor);
g2.fill(mask);
g2.setColor(ColorUtil.toAlpha(Color.orange, 25));
GraphicsConfig config = GraphicsUtil.setupAAPainting(g2);
for (int i = 2; i > 0; i--) {
g2.setStroke(new BasicStroke(i));
Area arrr = new Area();
for (JComponent component : components) {
Area area = getComponentArea(surfaceComponent, component, i-1);
if (area != null) {
arrr.add(area);
}
}
g2.draw(arrr);
g2.setStroke(new BasicStroke(stroke));
g2.setColor(ColorUtil.toAlpha(JBColor.ORANGE, 100));
g2.draw(mask);
}
finally {
clip.dispose();
}
config.restore();
}
}
@Nullable
private Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) {
private static Area getComponentArea(final JComponent surfaceComponent, final JComponent lightComponent, int offset) {
if (!lightComponent.isShowing()) return null;
final Point panelPoint = SwingUtilities.convertPoint(lightComponent, new Point(0, 0), surfaceComponent);
@@ -173,6 +159,9 @@ public class GlassPanel extends JComponent {
public void removeSpotlight(final JComponent component){
myLightComponents.remove(component);
if (myLightComponents.isEmpty()) {
setVisible(false);
}
}
public void clear() {
@@ -133,7 +133,7 @@ public class SettingsDialog extends DialogWrapper implements DataProvider {
}
@Override
protected void doOKAction() {
public void doOKAction() {
if (myEditor.apply()) {
ApplicationManager.getApplication().saveAll();
super.doOKAction();
@@ -64,7 +64,13 @@ public abstract class AbstractCommand implements PlaybackCommand {
Runnable runnable = new Runnable() {
@Override
public void run() {
_execute(context).notify(result);
try {
_execute(context).notify(result);
}
catch (Throwable e) {
context.error(e.getMessage(), getLine());
result.setRejected();
}
}
};
@@ -82,7 +88,7 @@ public abstract class AbstractCommand implements PlaybackCommand {
return result;
}
catch (Exception e) {
catch (Throwable e) {
context.error(e.getMessage(), getLine());
return new ActionCallback.Rejected();
}
@@ -1374,7 +1374,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
return false;
}
final Stripe stripe = myToolWindowsPane.getStripeFor(toolWindowId);
return stripe.getButtonFor(toolWindowId) != null;
return stripe != null && stripe.getButtonFor(toolWindowId) != null;
}
@Override
@@ -1397,6 +1397,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
final Stripe stripe = myToolWindowsPane.getStripeFor(toolWindowId);
if (stripe == null) {
return;
}
final ToolWindowImpl window = getInternalDecorator(toolWindowId).getToolWindow();
if (!window.isAvailable()) {
window.setPlaceholderMode(true);
@@ -332,6 +332,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
return myLayeredPane;
}
@Nullable
private StripeButton getButtonById(final String id) {
return myId2Button.get(id);
}
@@ -443,7 +444,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
}
}
@Nullable
Stripe getStripeFor(String id) {
ToolWindow window = myManager.getToolWindow(id);
if (window == null) {
return null;
}
final ToolWindowAnchor anchor = myManager.getToolWindow(id).getAnchor();
if (ToolWindowAnchor.TOP == anchor) {
return myTopStripe;
@@ -461,6 +468,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
throw new IllegalArgumentException("Anchor=" + anchor);
}
@Nullable
Stripe getStripeFor(final Rectangle screenRec, Stripe preferred) {
if (preferred.containsScreen(screenRec)) {
return myStripes.get(myStripes.indexOf(preferred));
@@ -816,32 +824,37 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
}
});
}
InternalDecorator oldComponent = (InternalDecorator)getComponentAt(anchor);
if (myInfo.isSplit()) {
splitter.setFirstComponent(oldComponent);
splitter.setSecondComponent(myNewComponent);
float proportion = getPreferredSplitProportion(oldComponent.getWindowInfo().getId(),
normalizeWeigh(oldComponent.getWindowInfo().getSideWeight() /
(oldComponent.getWindowInfo().getSideWeight() +
myInfo.getSideWeight())));
splitter.setProportion(proportion);
if (!anchor.isHorizontal() && !anchor.isSplitVertically()) {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight() + myInfo.getWeight());
JComponent c = getComponentAt(anchor);
if (c instanceof InternalDecorator) {
InternalDecorator oldComponent = (InternalDecorator)c;
if (myInfo.isSplit()) {
splitter.setFirstComponent(oldComponent);
splitter.setSecondComponent(myNewComponent);
float proportion = getPreferredSplitProportion(oldComponent.getWindowInfo().getId(),
normalizeWeigh(oldComponent.getWindowInfo().getSideWeight() /
(oldComponent.getWindowInfo().getSideWeight() +
myInfo.getSideWeight())));
splitter.setProportion(proportion);
if (!anchor.isHorizontal() && !anchor.isSplitVertically()) {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight() + myInfo.getWeight());
}
else {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight());
}
}
else {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight());
}
}
else {
splitter.setFirstComponent(myNewComponent);
splitter.setSecondComponent(oldComponent);
splitter.setProportion(normalizeWeigh(myInfo.getSideWeight()));
if (!anchor.isHorizontal() && !anchor.isSplitVertically()) {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight() + myInfo.getWeight());
}
else {
newWeight = normalizeWeigh(myInfo.getWeight());
splitter.setFirstComponent(myNewComponent);
splitter.setSecondComponent(oldComponent);
splitter.setProportion(normalizeWeigh(myInfo.getSideWeight()));
if (!anchor.isHorizontal() && !anchor.isSplitVertically()) {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight() + myInfo.getWeight());
}
else {
newWeight = normalizeWeigh(myInfo.getWeight());
}
}
} else {
newWeight = normalizeWeigh(myInfo.getWeight());
}
setComponent(splitter, anchor, newWeight);
@@ -1046,16 +1059,20 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
public void run() {
try {
Splitter splitter = (Splitter)getComponentAt(myInfo.getAnchor());
if (myInfo.isSplit()) {
InternalDecorator component = (InternalDecorator)splitter.getFirstComponent();
myId2SplitProportion.put(component.getWindowInfo().getId(), splitter.getProportion());
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
}
else {
InternalDecorator component = (InternalDecorator)splitter.getSecondComponent();
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
JComponent c = getComponentAt(myInfo.getAnchor());
if (c instanceof Splitter) {
Splitter splitter = (Splitter)c;
if (myInfo.isSplit()) {
InternalDecorator component = (InternalDecorator)splitter.getFirstComponent();
myId2SplitProportion.put(component.getWindowInfo().getId(), splitter.getProportion());
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
}
else {
InternalDecorator component = (InternalDecorator)splitter.getSecondComponent();
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
}
} else {
setComponent(null, myInfo.getAnchor(), 0);
}
if (!myDirtyMode) {
myLayeredPane.validate();
@@ -1161,7 +1178,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
public void run() {
try {
WindowInfoImpl info = getButtonById(myId).getWindowInfo();
StripeButton stripeButton = getButtonById(myId);
if (stripeButton == null) {
return;
}
WindowInfoImpl info = stripeButton.getWindowInfo();
ToolWindowAnchor anchor = info.getAnchor();
if (ToolWindowAnchor.TOP == anchor) {
@@ -18,9 +18,10 @@ package com.intellij.platform;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithBrowseButton;
import com.intellij.openapi.ui.ComponentWithBrowseButton.BrowseFolderActionListener;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.DocumentAdapter;
@@ -35,9 +36,9 @@ import javax.swing.text.PlainDocument;
import java.io.File;
/**
* User: catherine
* <p/>
* Logic for updating 2 fields: name for new directory and it's base location
*
* @author catherine
*/
public class LocationNameFieldsBinding {
private boolean myModifyingLocation = false;
@@ -46,60 +47,59 @@ public class LocationNameFieldsBinding {
private String myBaseDir;
private String mySuggestedProjectName;
public LocationNameFieldsBinding(@Nullable Project project, final TextFieldWithBrowseButton locationTextField,
final JTextField nameTextField, String baseDir, final String browseFolderTitle) {
public LocationNameFieldsBinding(@Nullable Project project,
final TextFieldWithBrowseButton locationField,
final JTextField nameField,
String baseDir,
String title) {
myBaseDir = baseDir;
File suggestedProjectDirectory = FileUtil.findSequentNonexistentFile(new File(baseDir), "untitled", "");
locationTextField.setText(suggestedProjectDirectory.toString());
nameTextField.setDocument(new NameFieldDocument(nameTextField, locationTextField));
locationField.setText(suggestedProjectDirectory.toString());
nameField.setDocument(new NameFieldDocument(nameField, locationField));
mySuggestedProjectName = suggestedProjectDirectory.getName();
nameTextField.setText(mySuggestedProjectName);
nameTextField.selectAll();
nameField.setText(mySuggestedProjectName);
nameField.selectAll();
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
ComponentWithBrowseButton.BrowseFolderActionListener<JTextField> listener =
new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(browseFolderTitle, "", locationTextField,
project,
descriptor,
TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
BrowseFolderActionListener<JTextField> listener =
new BrowseFolderActionListener<JTextField>(title, "", locationField, project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
@Override
protected void onFileChosen(@NotNull VirtualFile chosenFile) {
myBaseDir = chosenFile.getPath();
if (isProjectNameChanged(nameTextField.getText()) && !nameTextField.getText().equals(chosenFile.getName())) {
if (isProjectNameChanged(nameField.getText()) && !nameField.getText().equals(chosenFile.getName())) {
myExternalModify = true;
locationTextField.setText(new File(chosenFile.getPath(), nameTextField.getText()).toString());
locationField.setText(new File(chosenFile.getPath(), nameField.getText()).toString());
myExternalModify = false;
}
else {
myExternalModify = true;
locationTextField.setText(chosenFile.getPath());
nameTextField.setText(chosenFile.getName());
locationField.setText(chosenFile.getPath());
nameField.setText(chosenFile.getName());
myExternalModify = false;
}
}
};
locationTextField.addActionListener(listener);
locationTextField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
locationField.addActionListener(listener);
locationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
if (myExternalModify) {
return;
}
myModifyingLocation = true;
String path = locationTextField.getText().trim();
String path = locationField.getText().trim();
if (path.endsWith(File.separator)) {
path = path.substring(0, path.length() - File.separator.length());
}
int ind = path.lastIndexOf(File.separator);
if (ind != -1) {
String projectName = path.substring(ind + 1, path.length());
if (!nameTextField.getText().trim().isEmpty()) {
if (!nameField.getText().trim().isEmpty()) {
myBaseDir = path.substring(0, ind);
}
if (!projectName.equals(nameTextField.getText())) {
if (!projectName.equals(nameField.getText())) {
if (!myModifyingProjectName) {
nameTextField.setText(projectName);
nameField.setText(projectName);
}
}
}
@@ -112,7 +112,6 @@ public class LocationNameFieldsBinding {
return !currentName.equals(mySuggestedProjectName);
}
private class NameFieldDocument extends PlainDocument {
public NameFieldDocument(final JTextField projectNameTextField, final TextFieldWithBrowseButton locationField) {
addDocumentListener(new DocumentAdapter() {
@@ -129,14 +128,25 @@ public class LocationNameFieldsBinding {
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
boolean ok = true;
for (int idx = 0; idx < str.length() && ok; idx++) {
char ch = str.charAt(idx);
ok = ch != File.separatorChar && ch != '\\' && ch != '/' && ch != '|' && ch != ':';
StringBuilder sb = null;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
boolean replace = c == '\\' || c == '/' || SystemInfo.isWindows && (c == '|' || c == ':');
if (replace) {
if (sb == null) {
sb = new StringBuilder(str.length());
sb.append(str.substring(0, i));
}
sb.append('_');
}
else if (sb != null) {
sb.append(c);
}
}
if (ok) {
super.insertString(offs, str, a);
if (sb != null) {
str = sb.toString();
}
super.insertString(offs, str, a);
}
}
}
@@ -47,6 +47,7 @@ import java.io.File;
public class NewDirectoryProjectAction extends AnAction implements DumbAware {
private static final Logger LOG = Logger.getInstance(NewDirectoryProjectAction.class);
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
NewDirectoryProjectDialog dlg = new NewDirectoryProjectDialog(project);
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.platform.NewDirectoryProjectDialog">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myRootPane" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="575" height="400"/>
@@ -17,19 +17,6 @@
<text value="Project &amp;name:"/>
</properties>
</component>
<component id="89536" class="javax.swing.JLabel" binding="myLocationLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Location:"/>
</properties>
</component>
<vspacer id="bf7cf">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="92c6d" class="javax.swing.JTextField" binding="myProjectNameTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
@@ -38,45 +25,40 @@
</constraints>
<properties/>
</component>
<component id="89536" class="javax.swing.JLabel" binding="myLocationLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="&amp;Location:"/>
</properties>
</component>
<component id="bf36b" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myLocationField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<grid id="2663" binding="myProjectTypePanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<component id="dae2f" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="5c20f"/>
<text value="Project &amp;type:"/>
</properties>
</component>
<component id="5c20f" class="javax.swing.JComboBox" binding="myProjectTypeComboBox" default-binding="true">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="dae2f" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<labelFor value="5c20f"/>
<text value="Project &amp;type:"/>
</properties>
</component>
<component id="5c20f" class="javax.swing.JComboBox" binding="myProjectTypeComboBox" default-binding="true">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="eecc0" binding="myPlaceHolder" layout-manager="GridBagLayout">
</component>
<vspacer id="bf7cf">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children/>
</grid>
</vspacer>
</children>
</grid>
</form>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,9 +15,8 @@
*/
package com.intellij.platform;
import com.intellij.facet.ui.FacetEditorValidator;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
@@ -31,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
@@ -40,143 +38,93 @@ import java.util.List;
* @author yole
*/
public class NewDirectoryProjectDialog extends DialogWrapper {
private JTextField myProjectNameTextField;
private TextFieldWithBrowseButton myLocationField;
protected JPanel myRootPane;
protected JComboBox myProjectTypeComboBox;
private JPanel myProjectTypePanel;
private JLabel myLocationLabel;
protected JPanel getPlaceHolder() {
return myPlaceHolder;
}
private JPanel myPlaceHolder;
private static final Object EMPTY_PROJECT_GENERATOR = new Object();
private final DirectoryProjectGenerator myGeneratorBeforeSeparator;
protected NewDirectoryProjectDialog(Project project) {
private JPanel myRootPane;
private JTextField myProjectNameTextField;
private JLabel myLocationLabel;
private TextFieldWithBrowseButton myLocationField;
private JComboBox myProjectTypeComboBox;
@SuppressWarnings("unchecked")
protected NewDirectoryProjectDialog(@Nullable Project project) {
super(project, true);
setTitle("Create New Project");
setTitle(IdeBundle.message("new.dir.project.title"));
init();
myLocationLabel.setLabelFor(myLocationField.getChildComponent());
new LocationNameFieldsBinding(project, myLocationField, myProjectNameTextField, ProjectUtil.getBaseDir(), "Select Location for Project Directory");
String title = IdeBundle.message("new.dir.project.chooser.title");
new LocationNameFieldsBinding(project, myLocationField, myProjectNameTextField, ProjectUtil.getBaseDir(), title);
final DirectoryProjectGenerator[] generators = getGenerators();
if (generators.length == 0) {
myProjectTypePanel.setVisible(false);
myGeneratorBeforeSeparator = null;
}
else {
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(getEmptyProjectGenerator());
DefaultComboBoxModel model = new DefaultComboBoxModel();
model.addElement(EMPTY_PROJECT_GENERATOR);
DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
if (generators.length > 0) {
List<DirectoryProjectGenerator> primaryGenerators = ContainerUtil.newArrayList();
List<DirectoryProjectGenerator> otherGenerators = ContainerUtil.newArrayList();
for (DirectoryProjectGenerator generator : generators) {
if (generator instanceof HideableProjectGenerator) {
if (((HideableProjectGenerator)generator).isHidden()) {
continue;
}
if (generator instanceof HideableProjectGenerator && ((HideableProjectGenerator)generator).isHidden()) {
continue;
}
boolean primary = true;
if (generator instanceof WebProjectGenerator) {
primary = ((WebProjectGenerator) generator).isPrimaryGenerator();
}
if (primary) {
if (generator instanceof WebProjectGenerator && ((WebProjectGenerator)generator).isPrimaryGenerator()) {
primaryGenerators.add(generator);
} else {
}
else {
otherGenerators.add(generator);
}
}
if (!primaryGenerators.isEmpty() && !otherGenerators.isEmpty()) {
myGeneratorBeforeSeparator = primaryGenerators.get(primaryGenerators.size() - 1);
}
else {
myGeneratorBeforeSeparator = null;
}
for (DirectoryProjectGenerator generator : primaryGenerators) {
model.addElement(generator);
}
for (DirectoryProjectGenerator generator : otherGenerators) {
model.addElement(generator);
}
myProjectTypeComboBox.setModel(model);
myProjectTypeComboBox.setRenderer(createProjectTypeListCellRenderer(myProjectTypeComboBox.getRenderer()));
for (DirectoryProjectGenerator generator : primaryGenerators) model.addElement(generator);
for (DirectoryProjectGenerator generator : otherGenerators) model.addElement(generator);
}
myProjectTypeComboBox.setModel(model);
myProjectTypeComboBox.setRenderer(createProjectTypeListCellRenderer());
registerValidators(new FacetValidatorsManager() {
public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
checkValid();
}
public void validate() {
});
myProjectTypeComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(@NotNull ActionEvent e) {
checkValid();
}
});
}
@NotNull
private ListCellRenderer createProjectTypeListCellRenderer(@NotNull final ListCellRenderer originalRenderer) {
ListCellRenderer intermediate = myGeneratorBeforeSeparator == null ? originalRenderer : new ListCellRenderer() {
private final JSeparator mySeparator = new JSeparator(SwingConstants.HORIZONTAL);
private final JPanel myComponentWithSeparator = new JPanel(new BorderLayout(0, 0));
private static ListCellRendererWrapper<Object> createProjectTypeListCellRenderer() {
return new ListCellRendererWrapper<Object>() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component original = originalRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (index != -1 && value == myGeneratorBeforeSeparator
&& value instanceof DirectoryProjectGenerator && original instanceof JLabel) {
myComponentWithSeparator.removeAll();
JLabel label = (JLabel) original;
label.setText(((DirectoryProjectGenerator) value).getName());
myComponentWithSeparator.add(label, BorderLayout.CENTER);
myComponentWithSeparator.add(mySeparator, BorderLayout.SOUTH);
myComponentWithSeparator.revalidate();
myComponentWithSeparator.repaint();
return myComponentWithSeparator;
}
return original;
}
};
return new ListCellRendererWrapper() {
@Override
public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) {
if (value == null) return;
public void customize(JList list, Object value, int index, boolean selected, boolean cellHasFocus) {
if (value == EMPTY_PROJECT_GENERATOR) {
setText("Empty project");
setText(IdeBundle.message("new.dir.project.default.generator"));
}
else {
else if (value != null) {
setText(((DirectoryProjectGenerator)value).getName());
}
}
};
}
protected Object getEmptyProjectGenerator() {
return EMPTY_PROJECT_GENERATOR;
}
protected DirectoryProjectGenerator[] getGenerators() {
return Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
}
protected void checkValid() {
private void checkValid() {
String projectName = myProjectNameTextField.getText();
if (projectName.trim().isEmpty()) {
setOKActionEnabled(false);
setErrorText("Project name can't be empty");
setErrorText(IdeBundle.message("new.dir.project.error.empty"));
return;
}
if (myLocationField.getText().indexOf('$') >= 0) {
setOKActionEnabled(false);
setErrorText("Project directory name must not contain the $ character");
setErrorText(IdeBundle.message("new.dir.project.error.buck"));
return;
}
DirectoryProjectGenerator generator = getProjectGenerator();
if (generator != null) {
String baseDirPath = myLocationField.getTextField().getText();
@@ -187,58 +135,33 @@ public class NewDirectoryProjectDialog extends DialogWrapper {
return;
}
}
setOKActionEnabled(true);
setErrorText(null);
}
private void registerValidators(final FacetValidatorsManager validatorsManager) {
validateOnTextChange(validatorsManager, myLocationField.getTextField());
validateOnSelectionChange(validatorsManager, myProjectTypeComboBox);
}
private static void validateOnSelectionChange(final FacetValidatorsManager validatorsManager, final JComboBox projectNameTextField) {
projectNameTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
validatorsManager.validate();
}
});
}
private static void validateOnTextChange(final FacetValidatorsManager validatorsManager, final JTextField textField) {
textField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
validatorsManager.validate();
}
});
}
protected JComponent createCenterPanel() {
return myRootPane;
}
public String getNewProjectLocation() {
return myLocationField.getText();
}
public String getNewProjectName() {
return myProjectNameTextField.getText();
}
@Nullable
public DirectoryProjectGenerator getProjectGenerator() {
final Object selItem = myProjectTypeComboBox.getSelectedItem();
if (selItem == EMPTY_PROJECT_GENERATOR) return null;
return (DirectoryProjectGenerator)selItem;
}
@Override
public JComponent getPreferredFocusedComponent() {
return myProjectNameTextField;
}
@Override
protected JComponent createCenterPanel() {
return myRootPane;
}
@Override
protected String getHelpId() {
return "create_new_project_dialog";
}
public String getNewProjectLocation() {
return myLocationField.getText();
}
@Nullable
public DirectoryProjectGenerator getProjectGenerator() {
Object item = myProjectTypeComboBox.getSelectedItem();
return item == EMPTY_PROJECT_GENERATOR ? null : (DirectoryProjectGenerator)item;
}
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.DelegateColorScheme;
import com.intellij.openapi.editor.event.DocumentListener;
@@ -30,7 +31,9 @@ import com.intellij.openapi.editor.impl.RangeMarkerTree;
import com.intellij.openapi.editor.markup.HighlighterLayer;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.openapi.util.text.StringUtil;
@@ -56,31 +59,54 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
private static final Key<MyPanel> MY_PANEL_PROPERTY = Key.create("EditorTextFieldCellRenderer.MyEditorPanel");
public EditorTextFieldCellRenderer(Disposable parent) {
private final Project myProject;
private final boolean myInheritFontFromLaF;
protected EditorTextFieldCellRenderer(@Nullable Project project, @NotNull Disposable parent) {
this(project, true, parent);
}
protected EditorTextFieldCellRenderer(@Nullable Project project, boolean inheritFontFromLaF, @NotNull Disposable parent) {
myProject = project;
myInheritFontFromLaF = inheritFontFromLaF;
Disposer.register(parent, this);
}
protected abstract EditorColorsScheme getColorScheme();
protected abstract String getText(FontMetrics fontMetrics, JTable table, Object value, int row, int column);
protected abstract String getText(JTable table, Object value, int row, int column);
@Nullable
protected abstract TextAttributes getTextAttributes(Object value, boolean selected, int row, int col);
protected TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return null;
}
protected Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
return UIUtil.getTableBackground(selected);
}
@Nullable
protected FileType getFileType() {
return null;
}
@NotNull
protected EditorColorsScheme getColorScheme() {
return EditorColorsManager.getInstance().getGlobalScheme();
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
MyPanel panel = getEditorPanel(table);
EditorEx editor = panel.myEditor;
editor.getColorsScheme().setEditorFontSize(table.getFont().getSize());
String text = getText(((EditorImpl)editor).getFontMetrics(Font.PLAIN), table, value, row, column);
TextAttributes textAttributes = getTextAttributes(value, isSelected, row, column);
String text = getText(table, value, row, column);
TextAttributes textAttributes = getTextAttributes(table, value, selected, focused, row, column);
panel.setText(text, textAttributes);
((EditorImpl)editor).setPaintSelection(isSelected);
editor.getSelectionModel().setSelection(0, isSelected ? editor.getDocument().getTextLength() : 0);
((EditorImpl)editor).setPaintSelection(selected);
editor.getSelectionModel().setSelection(0, selected ? editor.getDocument().getTextLength() : 0);
editor.getColorsScheme().setColor(EditorColors.SELECTION_BACKGROUND_COLOR, table.getSelectionBackground());
editor.getColorsScheme().setColor(EditorColors.SELECTION_FOREGROUND_COLOR, table.getSelectionForeground());
editor.setBackgroundColor(getCellBackgroundColor(getColorScheme(), table, isSelected, row));
editor.setBackgroundColor(getCellBackground(table, value, selected, focused, row, column));
panel.setOpaque(!Comparing.equal(editor.getBackgroundColor(), table.getBackground()));
panel.setBorder(null); // prevents double border painting when ExtendedItemRendererComponentWrapper is used
@@ -88,14 +114,8 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
return panel;
}
public static Color getCellBackgroundColor(EditorColorsScheme colorsScheme, JTable table, boolean isSelected, int row) {
return isSelected ? table.getSelectionBackground() :
table.getSelectionModel().getLeadSelectionIndex() == row ? colorsScheme.getColor(EditorColors.CARET_ROW_COLOR) :
table.getBackground();
}
@NotNull
private MyPanel getEditorPanel(JTable table) {
private MyPanel getEditorPanel(final JTable table) {
MyPanel panel = UIUtil.getClientProperty(table, MY_PANEL_PROPERTY);
if (panel != null) {
DelegateColorScheme scheme = (DelegateColorScheme)panel.myEditor.getColorsScheme();
@@ -103,10 +123,10 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
return panel;
}
// reuse EditorTextField initialization logic
EditorTextField field = new EditorTextField(new MyDocument(), null, FileTypes.PLAIN_TEXT, false, false);
FileType fileType = ObjectUtils.notNull(getFileType(), FileTypes.PLAIN_TEXT);
EditorTextField field = new EditorTextField(new MyDocument(), myProject, fileType, false, false);
field.setSupplementary(true);
field.setFontInheritedFromLAF(false);
field.setFontInheritedFromLAF(myInheritFontFromLaF);
field.addNotify(); // creates editor
EditorEx editor = (EditorEx)ObjectUtils.assertNotNull(field.getEditor());
@@ -119,6 +139,12 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
panel = new MyPanel(editor);
Disposer.register(this, panel);
Disposer.register(this, new Disposable() {
@Override
public void dispose() {
UIUtil.putClientProperty(table, MY_PANEL_PROPERTY, null);
}
});
table.putClientProperty(MY_PANEL_PROPERTY, panel);
return panel;
@@ -157,6 +183,15 @@ public abstract class EditorTextFieldCellRenderer implements TableCellRenderer,
recalculatePreferredSize();
}
@Override
public void setBackground(Color bg) {
// allows for striped tables
if (myEditor != null) {
myEditor.setBackgroundColor(bg);
}
super.setBackground(bg);
}
@Override
public Dimension getPreferredSize() {
return myPreferredSize;
@@ -525,8 +525,10 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
myPopupLayeredPane.validate();
myPopupLayeredPane.repaint();
myPopupLayeredPane = null;
Disposer.dispose(myListenerDisposable);
if (myListenerDisposable != null) {
Disposer.dispose(myListenerDisposable);
}
myListenerDisposable = null;
}
else if (searchPopup != null) {
@@ -0,0 +1,64 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.util.ui.table;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
import com.intellij.ui.EditorTextFieldCellRenderer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
public abstract class EditorTextFieldJBTableRowRenderer extends EditorTextFieldCellRenderer implements JBTableRowRenderer {
protected EditorTextFieldJBTableRowRenderer(@Nullable Project project, @NotNull Disposable parent) {
super(project, parent);
}
@Override
public final JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused) {
return (JComponent)getTableCellRendererComponent(table, null, selected, focused, row, 0);
}
@Override
protected final String getText(JTable table, Object value, int row, int column) {
return getText(table, row);
}
@Override
protected final Color getCellBackground(JTable table, Object value, boolean selected, boolean focused, int row, int column) {
return getRowBackground(table, selected, focused, row);
}
@Nullable
@Override
protected final TextAttributes getTextAttributes(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return getTextAttributes(table, row);
}
protected abstract String getText(JTable table, int row);
@Nullable
protected TextAttributes getTextAttributes(JTable table, int row) {
return null;
}
protected Color getRowBackground(JTable table, boolean selected, boolean focused, int row) {
return super.getCellBackground(table, null, selected, focused, row, 0);
}
}
@@ -15,25 +15,33 @@
*/
package com.intellij.util.ui.table;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.ui.*;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.DottedBorder;
import com.intellij.ui.EditorSettingsProvider;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TIntArrayList;
import gnu.trove.TIntObjectHashMap;
import gnu.trove.TIntObjectProcedure;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.*;
import java.util.List;
import static java.awt.event.KeyEvent.*;
@@ -41,16 +49,18 @@ import static java.awt.event.KeyEvent.*;
/**
* @author Konstantin Bulenkov
*/
public abstract class JBListTable extends JPanel {
public abstract class JBListTable {
protected final JTable myInternalTable;
private final JBTable mainTable;
private final Ref<Integer> myLastEditorIndex = Ref.create(null);
private final RowResizeAnimator myRowResizeAnimator;
private final Disposable myOnRemoveDisposable;
private MouseEvent myMouseEvent;
private MyCellEditor myCellEditor;
private int myLastFocusedEditorComponentIdx = -1;
public JBListTable(@NotNull final JTable t) {
super(new BorderLayout());
myInternalTable = t;
myOnRemoveDisposable = Disposer.newDisposable();
final JBListTableModel model = new JBListTableModel(t.getModel()) {
@Override
public JBTableRow getRow(int index) {
@@ -64,7 +74,7 @@ public abstract class JBListTable extends JPanel {
@Override
public void addRow() {
myLastEditorIndex.set(null);
myLastFocusedEditorComponentIdx = -1;
super.addRow();
}
};
@@ -114,10 +124,11 @@ public abstract class JBListTable extends JPanel {
@Override
public TableCellRenderer getCellRenderer(int row, int column) {
return new DefaultTableCellRenderer() {
final JBTableRowRenderer rowRenderer = getRowRenderer(row);
return new TableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean hasFocus, int row, int col) {
return getRowRenderer(t, row, selected, hasFocus);
public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focused, int row, int col) {
return rowRenderer.getRowRendererComponent(t, row, selected, focused);
}
};
}
@@ -199,6 +210,16 @@ public abstract class JBListTable extends JPanel {
return super.processKeyBinding(ks, e, condition, pressed);
}
@Override
public void columnMarginChanged(ChangeEvent e) {
// we don't stop editing (it prevents editor removal when scrollbar is added)
TableColumn resizingColumn = tableHeader != null ? tableHeader.getResizingColumn() : null;
if (resizingColumn != null && autoResizeMode == AUTO_RESIZE_OFF) {
resizingColumn.setPreferredWidth(resizingColumn.getWidth());
}
resizeAndRepaint();
}
@Override
public TableCellEditor getCellEditor(final int row, int column) {
final JBTableRowEditor editor = getRowEditor(row);
@@ -224,14 +245,31 @@ public abstract class JBListTable extends JPanel {
boolean isSelected = isCellSelected(row, column);
return editor.getTableCellEditorComponent(this, value, isSelected, row, column);
}
@Override
public void addNotify() {
super.addNotify();
Disposer.register(myOnRemoveDisposable, myRowResizeAnimator);
}
@Override
public void removeNotify() {
super.removeNotify();
Disposer.dispose(myOnRemoveDisposable);
}
};
mainTable.setStriped(true);
myRowResizeAnimator = new RowResizeAnimator(mainTable);
}
public void stopEditing() {
TableUtil.stopEditing(mainTable);
}
public Disposable getOnRemoveDisposable() {
return myOnRemoveDisposable;
}
private static void installPaddingAndBordersForEditors(JBTableRowEditor editor) {
final List<EditorTextField> editors = UIUtil.findComponentsOfType(editor, EditorTextField.class);
for (EditorTextField textField : editors) {
@@ -244,7 +282,7 @@ public abstract class JBListTable extends JPanel {
return mainTable;
}
protected abstract JComponent getRowRenderer(JTable table, int row, boolean selected, boolean focused);
protected abstract JBTableRowRenderer getRowRenderer(int row);
protected abstract JBTableRowEditor getRowEditor(int row);
@@ -296,118 +334,49 @@ public abstract class JBListTable extends JPanel {
return panel;
}
private static class RowResizeAnimator extends Thread {
private final JTable myTable;
private final int myRow;
private final JScrollPane myScrollPane;
private int neededHeight;
private final JBTableRowEditor myEditor;
private final Ref<Integer> myIndex;
private int step = 5;
private int currentHeight;
private RowResizeAnimator(JTable table, int row, int height, JBTableRowEditor editor, @NotNull Ref<Integer> index) {
super("Row Animator");
myTable = table;
myRow = row;
neededHeight = height;
myEditor = editor;
myIndex = index;
currentHeight = myTable.getRowHeight(myRow);
myScrollPane = UIUtil.getParentOfType(JScrollPane.class, myTable);
}
@Override
public void run() {
final boolean exitEditing = currentHeight > neededHeight;
try {
sleep(50);
final JScrollBar bar = myScrollPane.getVerticalScrollBar();
if (bar == null || !bar.isVisible()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
}
});
sleep(15);
}
while (currentHeight != neededHeight) {
if (Math.abs(currentHeight - neededHeight) < step) {
currentHeight = neededHeight;
}
else {
currentHeight += currentHeight < neededHeight ? step : -step;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myTable.setRowHeight(myRow, currentHeight);
}
});
sleep(15);
}
if (myEditor != null) {
JComponent[] components = myEditor.getFocusableComponents();
JComponent focus = null;
if (myIndex.get() != null) {
int index = myIndex.get().intValue();
if (0 <= index && index < components.length) {
focus = components[index];
}
}
if (focus == null) {
focus = myEditor.getPreferredFocusedComponent();
}
if (focus != null) {
focus.requestFocus();
}
}
}
catch (InterruptedException ignore) {
} finally {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
TableUtil.scrollSelectionToVisible(myTable);
if (exitEditing && !myTable.isEditing()) {
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
}
}
});
}
}
}
private class MyCellEditor extends AbstractTableCellEditor implements Animated {
JTable curTable;
private class MyCellEditor extends AbstractTableCellEditor {
private final JBTableRowEditor myEditor;
public MyCellEditor(JBTableRowEditor editor) {
myEditor = editor;
curTable = null;
}
@Override
public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, int column) {
curTable = table;
final JPanel p = new JPanel(new BorderLayout()) {
@Override
public void addNotify() {
super.addNotify();
final int height = (int)getPreferredSize().getHeight();
int height = getPreferredSize().height;
if (height > table.getRowHeight(row)) {
new RowResizeAnimator(table, row, height, myEditor, myMouseEvent == null ? myLastEditorIndex : Ref.<Integer>create(null)).start();
myRowResizeAnimator.resize(row, height);
}
}
public void removeNotify() {
if (myCellEditor != null) myCellEditor.saveFocusIndex();
super.removeNotify();
new RowResizeAnimator(table, row, table.getRowHeight(), null, myMouseEvent == null ? myLastEditorIndex : Ref.<Integer>create(null)).start();
myRowResizeAnimator.resize(row, table.getRowHeight());
}
};
p.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(p);
focusManager.requestFocus(getComponentToFocus(), true);
}
private Component getComponentToFocus() {
if (myLastFocusedEditorComponentIdx >= 0) {
JComponent[] focusableComponents = myEditor.getFocusableComponents();
if (myLastFocusedEditorComponentIdx < focusableComponents.length) {
return focusableComponents[myLastFocusedEditorComponentIdx];
}
}
return myEditor.getPreferredFocusedComponent();
}
});
p.add(myEditor, BorderLayout.CENTER);
p.setFocusable(false);
return p;
}
@@ -422,31 +391,107 @@ public abstract class JBListTable extends JPanel {
return super.stopCellEditing();
}
private void removeEmptyRow() {
final int row = curTable.getSelectedRow();
if (row != -1 && isRowEmpty(row)) {
final JBListTableModel model = (JBListTableModel)curTable.getModel();
final int count = model.getRowCount();
model.removeRow(row);
int newRow = count == row + 1 ? row - 1 : row;
curTable.setRowSelectionInterval(newRow, newRow);
}
}
public void saveFocusIndex() {
JComponent[] components = myEditor.getFocusableComponents();
for (int i = 0; i < components.length; i++) {
if (components[i].hasFocus()) {
JBListTable.this.myLastEditorIndex.set(i);
break;
}
}
}
@Override
public void cancelCellEditing() {
saveFocusIndex();
super.cancelCellEditing();
}
private void saveFocusIndex() {
JComponent[] components = myEditor.getFocusableComponents();
for (int i = 0; i < components.length; i++) {
if (components[i].hasFocus()) {
myLastFocusedEditorComponentIdx = i;
break;
}
}
}
}
private static class RowResizeAnimator implements ActionListener, Disposable {
private static final int ANIMATION_STEP_MILLIS = 15;
private static final int RESIZE_AMOUNT_PER_STEP = 5;
private final TIntObjectHashMap<RowAnimationState> myRowAnimationStates = new TIntObjectHashMap<RowAnimationState>();
private final Timer myAnimationTimer = new Timer(ANIMATION_STEP_MILLIS, this);
private final JTable myTable;
public RowResizeAnimator(JTable table) {
myTable = table;
}
public void resize(int row, int targetHeight) {
myRowAnimationStates.put(row, new RowAnimationState(row, targetHeight));
startAnimation();
}
@Override
public void actionPerformed(final ActionEvent e) {
doAnimationStep(e.getWhen());
}
@Override
public void dispose() {
stopAnimation();
}
private void startAnimation() {
if (!myAnimationTimer.isRunning()) {
myAnimationTimer.start();
}
}
private void stopAnimation() {
myAnimationTimer.stop();
}
private void doAnimationStep(final long updateTime) {
final TIntArrayList completeRows = new TIntArrayList(myRowAnimationStates.size());
myRowAnimationStates.forEachEntry(new TIntObjectProcedure<RowAnimationState>() {
@Override
public boolean execute(int row, RowAnimationState animationState) {
if (animationState.doAnimationStep(updateTime)) {
completeRows.add(row);
}
return true;
}
});
completeRows.forEach(new TIntProcedure() {
@Override
public boolean execute(int row) {
myRowAnimationStates.remove(row);
return true;
}
});
if (myRowAnimationStates.isEmpty()) {
stopAnimation();
}
}
private class RowAnimationState {
private final int myRow;
private final int myTargetHeight;
private long myLastUpdateTime;
public RowAnimationState(int row, int targetHeight) {
myRow = row;
myTargetHeight = targetHeight;
myLastUpdateTime = System.currentTimeMillis();
}
/**
* @return whether this row animation is complete
*/
public boolean doAnimationStep(long currentTime) {
int currentRowHeight = myTable.getRowHeight(myRow);
int resizeAbs = (int) (RESIZE_AMOUNT_PER_STEP * ((currentTime - myLastUpdateTime) / (double)ANIMATION_STEP_MILLIS));
int leftToAnimate = myTargetHeight - currentRowHeight;
int newHeight = Math.abs(leftToAnimate) <= Math.abs(resizeAbs) ? myTargetHeight :
currentRowHeight + (leftToAnimate < 0 ? -resizeAbs : resizeAbs);
myTable.setRowHeight(myRow, newHeight);
myLastUpdateTime = currentTime;
return myTargetHeight == newHeight;
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,13 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui;
package com.intellij.util.ui.table;
/**
* Indicates that component, or cell editor, or cell renderer performs
* some animations and side effects may occur because of changes of the bounds
*
* @author Konstantin Bulenkov
*/
public interface Animated {
import javax.swing.*;
public interface JBTableRowRenderer {
JComponent getRowRendererComponent(JTable table, int row, boolean selected, boolean focused);
}
@@ -371,7 +371,7 @@ public class TableModelEditor<T> implements ElementProducer<T> {
}
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
).createPanel();
@@ -440,7 +440,7 @@ public class TableModelEditor<T> implements ElementProducer<T> {
public void run(AnActionButton button) {
if (TableUtil.doRemoveSelectedItems(table, model, this)) {
table.requestFocus();
TableUtil.updateScroller(table, false);
TableUtil.updateScroller(table);
}
}
@@ -207,7 +207,7 @@ failed.to.generate.wrapper.error.message=Failed to generate temporary html wrapp
application.configuration.use.classpath.and.jdk.of.module.label=Use classpath of m&odule:
application.configuration.main.class.label=Main &class:
jre.path.is.not.valid.jre.home.error.mesage=''{0}'' is not valid JRE home
jre.path.is.not.valid.jre.home.error.mesage=''{0}'' is not a valid JRE home
main.method.not.found.in.class.error.message=Main method not found in class {0}
no.user.process.input.error.message=No process input
fix.run.configuration.problem.button=Fix
@@ -1155,3 +1155,9 @@ presentation.mode.fon.size=Font size\:
update.available.group=Update Checker
loading.editors=Loading files...
new.dir.project.title=Create New Project
new.dir.project.chooser.title=Select Location for Project Directory
new.dir.project.default.generator=Empty project
new.dir.project.error.empty=Project name can't be empty
new.dir.project.error.buck=Project directory name must not contain the ''$'' character
@@ -397,6 +397,7 @@ introduce.constant.field.of.type=Constant (static final field) of &type:
extract.subclass.command=Extract Subclass
extract.superclass.elements.header=Extract superclass with members to directory
declare.static.checkbox=Declare &static
declare.static.pass.fields.checkbox=Declare &static (pass fields as params)
declare.varargs.checkbox=Declare v&arargs
declare.folded.parameters=&Fold parameters
extract.method.method.panel.border=Method
@@ -836,6 +836,7 @@
</action>
<action id="ActivateChangesToolWindow">
<keyboard-shortcut first-keystroke="alt 9"/>
<keyboard-shortcut first-keystroke="alt shift 9"/>
</action>
<action id="NewElement">
<keyboard-shortcut first-keystroke="alt INSERT"/>
@@ -214,6 +214,7 @@
</action>
<action id="ActivateChangesToolWindow">
<keyboard-shortcut first-keystroke="meta 9"/>
<keyboard-shortcut first-keystroke="meta shift 9"/>
</action>
<action id="Generate">
<keyboard-shortcut first-keystroke="meta N"/>
@@ -217,6 +217,7 @@
</action>
<action id="ActivateChangesToolWindow">
<keyboard-shortcut first-keystroke="meta 9"/>
<keyboard-shortcut first-keystroke="meta shift 9"/>
</action>
<action id="NewElement">
<keyboard-shortcut first-keystroke="control N"/>
@@ -26,6 +26,7 @@
</action>
<action id="ActivateChangesToolWindow">
<keyboard-shortcut first-keystroke="meta 9" />
<keyboard-shortcut first-keystroke="meta shift 9" />
</action>
<action id="FileStructurePopup">
<keyboard-shortcut first-keystroke="control 6"/>

Some files were not shown because too many files have changed in this diff Show More