mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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));
|
||||
|
||||
+109
@@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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();
|
||||
|
||||
+7
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-22
@@ -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()]);
|
||||
|
||||
+21
-4
@@ -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;
|
||||
}
|
||||
|
||||
-4
@@ -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
|
||||
|
||||
+4
@@ -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;
|
||||
|
||||
+1
-4
@@ -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;
|
||||
|
||||
+25
-17
@@ -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;
|
||||
|
||||
+43
-7
@@ -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());
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
+171
-149
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+121
-36
@@ -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;
|
||||
}
|
||||
|
||||
+4
-1
@@ -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++) {
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -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;
|
||||
}
|
||||
}
|
||||
+14
@@ -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 {}
|
||||
}
|
||||
+13
@@ -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 {}
|
||||
}
|
||||
-5
@@ -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=""_ -> fail""/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name="java.lang.System void setProperties(java.util.Properties) 0">
|
||||
<annotation name="org.jetbrains.annotations.Nullable"/>
|
||||
</item>
|
||||
|
||||
+4
-10
@@ -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 = "null -> fail", 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 = "null, _ -> fail", 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>
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class X {
|
||||
void foo() {
|
||||
int x = newMethod();
|
||||
}
|
||||
|
||||
private int newMethod() {
|
||||
int x = 0;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class X {
|
||||
void foo() {
|
||||
<selection>int x = 0;
|
||||
int y = 42;
|
||||
</selection>
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class X {
|
||||
void foo() {
|
||||
newMethod();
|
||||
|
||||
}
|
||||
|
||||
private int newMethod() {
|
||||
int x = 0;
|
||||
int y = 42;
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class X {
|
||||
private int myI;
|
||||
void foo() {
|
||||
<selection>int i = myI;</selection>
|
||||
}
|
||||
}
|
||||
+10
@@ -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);
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
|
||||
doAutoPopupTest("instanceof", null);
|
||||
}
|
||||
|
||||
public void testDoNotAutoCompleteCompletionElementIfTemplateUnique() {
|
||||
public void testDoNotAutoCompleteCompletionElementIfTemplateUnique() {
|
||||
LiveTemplateCompletionContributor.ourShowTemplatesInTests = true;
|
||||
configureByFile();
|
||||
myFixture.completeBasic();
|
||||
|
||||
+31
@@ -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(); }
|
||||
|
||||
+28
-1
@@ -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 {
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
+5
-6
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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();
|
||||
|
||||
+4
-3
@@ -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;
|
||||
|
||||
|
||||
+5
-4
@@ -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);
|
||||
|
||||
+3
-3
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+74
-31
@@ -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
|
||||
|
||||
+5
-2
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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();
|
||||
|
||||
+8
-2
@@ -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 &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="&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="&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 &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 &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) {
|
||||
|
||||
+64
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-9
@@ -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
Reference in New Issue
Block a user