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:
+1
-1
@@ -1181,7 +1181,7 @@ public class HighlightMethodUtil {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue;
|
||||
if (currentMethod.getTypeParameters().length > 0 && JavaGenericsUtil.isRawToGeneric(currentType, otherSuperReturnType)) continue;
|
||||
}
|
||||
return createIncompatibleReturnTypeMessage(currentMethod, otherSuperMethod, otherSuperReturnType,
|
||||
currentType, JavaErrorMessages.message("unrelated.overriding.methods.return.types"),
|
||||
|
||||
-4
@@ -684,10 +684,6 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
String message = JavaErrorMessages.message("underscore.lambda.identifier");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create();
|
||||
}
|
||||
else {
|
||||
String message = JavaErrorMessages.message("underscore.identifier");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
+12
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.compiler;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.patterns.ElementPattern;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -63,4 +65,14 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIdentifier(PsiIdentifier identifier) {
|
||||
super.visitIdentifier(identifier);
|
||||
if (PsiUtil.getLanguageLevel(identifier).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
if ("_".equals(identifier.getText())) {
|
||||
myHolder.registerProblem(identifier, JavaErrorMessages.message("underscore.identifier"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -198,6 +198,18 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
|
||||
super.visitMethodReferenceExpression(expression);
|
||||
if (IGNORE_UNCHECKED_CALL) return;
|
||||
final JavaResolveResult result = expression.advancedResolve(false);
|
||||
final String description = getUncheckedCallDescription(result);
|
||||
if (description != null) {
|
||||
final PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
registerProblem(description, referenceNameElement != null ? referenceNameElement : expression, myGenerifyFixes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(PsiCallExpression callExpression) {
|
||||
super.visitCallExpression(callExpression);
|
||||
@@ -383,8 +395,9 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
|
||||
|
||||
@Nullable
|
||||
private String getUncheckedCallDescription(JavaResolveResult resolveResult) {
|
||||
final PsiMethod method = (PsiMethod)resolveResult.getElement();
|
||||
if (method == null) return null;
|
||||
final PsiElement element = resolveResult.getElement();
|
||||
if (!(element instanceof PsiMethod)) return null;
|
||||
final PsiMethod method = (PsiMethod)element;
|
||||
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
|
||||
if (!PsiUtil.isRawSubstitutor(method, substitutor)) return null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
@@ -36,7 +36,7 @@ public class LambdaHighlightingUtil {
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(@NotNull PsiClass psiClass, String interfaceNonFunctionalMessage) {
|
||||
if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass);
|
||||
final List<HierarchicalMethodSignature> signatures = LambdaUtil.findFunctionCandidates(psiClass);
|
||||
if (signatures == null) return interfaceNonFunctionalMessage;
|
||||
if (signatures.isEmpty()) return "No target method found";
|
||||
if (signatures.size() == 1) {
|
||||
@@ -97,15 +97,23 @@ public class LambdaHighlightingUtil {
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
|
||||
if (functionalInterfaceType instanceof PsiIntersectionType) {
|
||||
int count = 0;
|
||||
for (PsiType type : ((PsiIntersectionType)functionalInterfaceType).getConjuncts()) {
|
||||
if (checkInterfaceFunctional(type) == null) return null;
|
||||
if (checkInterfaceFunctional(type) == null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
return "Multiple non-overriding abstract methods found in " + functionalInterfaceType.getPresentableText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(aClass);
|
||||
final List<HierarchicalMethodSignature> signatures = LambdaUtil.findFunctionCandidates(aClass);
|
||||
if (signatures != null && signatures.size() == 1) {
|
||||
final MethodSignature functionalMethod = signatures.get(0);
|
||||
if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
|
||||
|
||||
@@ -103,9 +103,7 @@ public class LambdaUtil {
|
||||
|
||||
public static boolean isFunctionalType(PsiType type) {
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
for (PsiType type1 : ((PsiIntersectionType)type).getConjuncts()) {
|
||||
if (isFunctionalType(type1)) return true;
|
||||
}
|
||||
return extractFunctionalConjunct((PsiIntersectionType)type) != null;
|
||||
}
|
||||
return isFunctionalClass(PsiUtil.resolveGenericsClassInType(type).getElement());
|
||||
}
|
||||
@@ -114,7 +112,7 @@ public class LambdaUtil {
|
||||
public static boolean isFunctionalClass(PsiClass aClass) {
|
||||
if (aClass != null) {
|
||||
if (aClass instanceof PsiTypeParameter) return false;
|
||||
final List<MethodSignature> signatures = findFunctionCandidates(aClass);
|
||||
final List<HierarchicalMethodSignature> signatures = findFunctionCandidates(aClass);
|
||||
return signatures != null && signatures.size() == 1;
|
||||
}
|
||||
return false;
|
||||
@@ -144,7 +142,7 @@ public class LambdaUtil {
|
||||
@Nullable
|
||||
static MethodSignature getFunction(PsiClass psiClass) {
|
||||
if (psiClass == null) return null;
|
||||
final List<MethodSignature> functions = findFunctionCandidates(psiClass);
|
||||
final List<HierarchicalMethodSignature> functions = findFunctionCandidates(psiClass);
|
||||
if (functions != null && functions.size() == 1) {
|
||||
return functions.get(0);
|
||||
}
|
||||
@@ -178,12 +176,13 @@ public class LambdaUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static List<MethodSignature> hasSubsignature(List<MethodSignature> signatures) {
|
||||
for (MethodSignature signature : signatures) {
|
||||
private static List<HierarchicalMethodSignature> hasSubsignature(List<HierarchicalMethodSignature> signatures) {
|
||||
for (HierarchicalMethodSignature signature : signatures) {
|
||||
boolean subsignature = true;
|
||||
for (MethodSignature methodSignature : signatures) {
|
||||
for (HierarchicalMethodSignature methodSignature : signatures) {
|
||||
if (!signature.equals(methodSignature)) {
|
||||
if (!MethodSignatureUtil.isSubsignature(signature, methodSignature)) {
|
||||
if (!MethodSignatureUtil.isSubsignature(signature, methodSignature) &&
|
||||
!skipMethod(signature, methodSignature)) {
|
||||
subsignature = false;
|
||||
break;
|
||||
}
|
||||
@@ -194,10 +193,20 @@ public class LambdaUtil {
|
||||
return signatures;
|
||||
}
|
||||
|
||||
private static boolean skipMethod(HierarchicalMethodSignature signature,
|
||||
HierarchicalMethodSignature methodSignature) {
|
||||
//not generic
|
||||
if (methodSignature.getTypeParameters().length == 0) {
|
||||
return false;
|
||||
}
|
||||
//foreign class
|
||||
return signature.getMethod().getContainingClass() != methodSignature.getMethod().getContainingClass();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static List<MethodSignature> findFunctionCandidates(PsiClass psiClass) {
|
||||
public static List<HierarchicalMethodSignature> findFunctionCandidates(PsiClass psiClass) {
|
||||
if (psiClass != null && psiClass.isInterface() && !psiClass.isAnnotationType()) {
|
||||
final List<MethodSignature> methods = new ArrayList<MethodSignature>();
|
||||
final List<HierarchicalMethodSignature> methods = new ArrayList<HierarchicalMethodSignature>();
|
||||
final Collection<HierarchicalMethodSignature> visibleSignatures = psiClass.getVisibleSignatures();
|
||||
for (HierarchicalMethodSignature signature : visibleSignatures) {
|
||||
final PsiMethod psiMethod = signature.getMethod();
|
||||
@@ -286,9 +295,8 @@ public class LambdaUtil {
|
||||
} else if (parent instanceof PsiTypeCastExpression) {
|
||||
final PsiType castType = ((PsiTypeCastExpression)parent).getType();
|
||||
if (castType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunctType : ((PsiIntersectionType)castType).getConjuncts()) {
|
||||
if (getFunctionalInterfaceMethod(conjunctType) != null) return conjunctType;
|
||||
}
|
||||
final PsiType conjunct = extractFunctionalConjunct((PsiIntersectionType)castType);
|
||||
if (conjunct != null) return conjunct;
|
||||
}
|
||||
return castType;
|
||||
}
|
||||
@@ -363,6 +371,19 @@ public class LambdaUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType extractFunctionalConjunct(PsiIntersectionType type) {
|
||||
PsiType conjunct = null;
|
||||
for (PsiType conjunctType : type.getConjuncts()) {
|
||||
final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(conjunctType);
|
||||
if (interfaceMethod != null) {
|
||||
if (conjunct != null && !conjunct.equals(conjunctType)) return null;
|
||||
conjunct = conjunctType;
|
||||
}
|
||||
}
|
||||
return conjunct;
|
||||
}
|
||||
|
||||
private static PsiType getFunctionalInterfaceTypeByContainingLambda(@NotNull PsiLambdaExpression parentLambda) {
|
||||
final PsiType parentInterfaceType = parentLambda.getFunctionalInterfaceType();
|
||||
return parentInterfaceType != null ? getFunctionalInterfaceReturnType(parentInterfaceType) : null;
|
||||
|
||||
+2
-2
@@ -1070,7 +1070,7 @@ public class InferenceSession {
|
||||
session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
|
||||
return true;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
|
||||
return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1115,7 +1115,7 @@ public class InferenceSession {
|
||||
session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
|
||||
return true;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
|
||||
return sReturnType != null && tReturnType != null && TypeConversionUtil.isAssignable(tReturnType, sReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -65,7 +65,10 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
|
||||
}
|
||||
}
|
||||
|
||||
collectReturnTypeVariables(session, psiExpression, substitutor.substitute(interfaceMethod.getReturnType()), result);
|
||||
final PsiType returnType = interfaceMethod.getReturnType();
|
||||
if (returnType != null) {
|
||||
collectReturnTypeVariables(session, psiExpression, substitutor.substitute(returnType), result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
+6
-2
@@ -156,7 +156,11 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil
|
||||
.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
|
||||
if (receiverSubstitutor != null) {
|
||||
if (!method.hasTypeParameters() && signature.getParameterTypes().length == 1) return receiverSubstitutor;
|
||||
if (!method.hasTypeParameters()) {
|
||||
if (signature.getParameterTypes().length == 1 || PsiUtil.isRawSubstitutor(containingClass, receiverSubstitutor)) {
|
||||
return receiverSubstitutor;
|
||||
}
|
||||
}
|
||||
psiSubstitutor = receiverSubstitutor;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +179,7 @@ class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMet
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
if (interfaceMethodReturnType != PsiType.VOID) {
|
||||
if (interfaceMethodReturnType != PsiType.VOID && interfaceMethodReturnType != null) {
|
||||
final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
|
||||
if (returnType != null) {
|
||||
session.registerConstraints(returnType, interfaceMethodReturnType);
|
||||
|
||||
+1
-3
@@ -421,9 +421,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
if (interfaceMethod != null) {
|
||||
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(left);
|
||||
|
||||
LOG.assertTrue(interfaceReturnType != null);
|
||||
|
||||
if (interfaceReturnType == PsiType.VOID) {
|
||||
if (interfaceReturnType == PsiType.VOID || interfaceReturnType == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -624,11 +624,11 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
}
|
||||
|
||||
if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) {
|
||||
return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
|
||||
return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
|
||||
}
|
||||
|
||||
if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) {
|
||||
return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
|
||||
return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
|
||||
}
|
||||
|
||||
return specifics;
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
interface A {
|
||||
Iterable<Integer> m(List ls);
|
||||
}
|
||||
|
||||
interface B {
|
||||
Iterable<String> m(List l);
|
||||
}
|
||||
|
||||
<error descr="'m(List)' in 'Test.B' clashes with 'm(List)' in 'Test.A'; methods have unrelated return types">interface AB extends A, B</error> {}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
class Test {
|
||||
void <warning descr="Use of '_' as an identifier might not be supported in releases after Java 8">_</warning>(){}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface I<T, K extends Integer> {
|
||||
void m(T t);
|
||||
void m(K k);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface IEx extends I<Integer, Integer> { }
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
<X> void m();
|
||||
}
|
||||
|
||||
interface B {
|
||||
void m();
|
||||
}
|
||||
|
||||
interface C extends A, B { }
|
||||
|
||||
{
|
||||
C c = ()-> {};
|
||||
}
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
|
||||
interface F {
|
||||
<X> void m();
|
||||
}
|
||||
|
||||
{
|
||||
F f = this::g;
|
||||
}
|
||||
|
||||
void g() {}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
interface F {
|
||||
<X> void m();
|
||||
void a();
|
||||
}
|
||||
|
||||
{
|
||||
F f = <error descr="Multiple non-overriding abstract methods found">() -> g()</error>;
|
||||
}
|
||||
|
||||
void g() {}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
int m();
|
||||
}
|
||||
|
||||
interface B {
|
||||
int m(int i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
A a = ()-> ((B)i -> i).m(3);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import java.io.Serializable;
|
||||
|
||||
class Test {
|
||||
|
||||
interface I {
|
||||
void foo();
|
||||
}
|
||||
|
||||
interface A {
|
||||
void bar(int i);
|
||||
}
|
||||
|
||||
{
|
||||
Object o1 = (Serializable & I) () -> {};
|
||||
Object o2 = (I & Serializable) () -> {};
|
||||
Object o3 = (I & Runnable) <error descr="Multiple non-overriding abstract methods found in Runnable & I">() -> {}</error>;
|
||||
Object o4 = (A & Runnable) <error descr="Multiple non-overriding abstract methods found in Runnable & A">() -> {}</error>;
|
||||
Object o5 = (Runnable & A) <error descr="Multiple non-overriding abstract methods found in Runnable & A">() -> {}</error>;
|
||||
}
|
||||
}
|
||||
|
||||
class Test1 {
|
||||
|
||||
interface A {
|
||||
<X> void foo();
|
||||
}
|
||||
|
||||
interface B {
|
||||
void foo();
|
||||
}
|
||||
|
||||
{
|
||||
Object c0 = (A & B) ()->{};
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class LambdaConv10 {
|
||||
|
||||
interface I<T, R> { public R call( T t); }
|
||||
|
||||
{
|
||||
I<Integer,Integer> in = (<error descr="Incompatible parameter types in lambda expression">int i</error>) -> 2 * i;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class Test {
|
||||
|
||||
Runnable r;
|
||||
{ r = r::run; }
|
||||
Runnable r1;
|
||||
{ r1 = () -> r1.run(); }
|
||||
|
||||
|
||||
{
|
||||
Runnable r = () -> <error descr="Variable 'r' might not have been initialized">r</error>.run();
|
||||
Runnable r1 = <error descr="Variable 'r1' might not have been initialized">r1</error>::run;
|
||||
}
|
||||
}
|
||||
-5
@@ -1,10 +1,5 @@
|
||||
class C {
|
||||
void test() {
|
||||
{
|
||||
I <warning descr="Use of '_' as an identifier might not be supported in releases after Java 8">_</warning> = new I() { public void f(int i) { } };
|
||||
accept(_);
|
||||
}
|
||||
|
||||
{
|
||||
accept(<error descr="Use of '_' as a lambda parameter name is not allowed">_</error> -> System.out.println(_));
|
||||
accept((int <error descr="Use of '_' as a lambda parameter name is not allowed">_</error>) -> System.out.println(_));
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
A f();
|
||||
}
|
||||
interface B {}
|
||||
|
||||
static abstract class C implements A, B {}
|
||||
static abstract class D implements A, B {}
|
||||
|
||||
interface I<T> {
|
||||
<error descr="Invalid method declaration; return type required">m</error>(T arg);
|
||||
}
|
||||
|
||||
void bar(C c) {
|
||||
foo(c, x -> x.f());
|
||||
foo(c, x -> x);
|
||||
}
|
||||
|
||||
<T> void foo(T t1, I<T> t3) {}
|
||||
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
interface F {
|
||||
<X> <error descr="Invalid method declaration; return type required">m</error>();
|
||||
}
|
||||
|
||||
void g() {}
|
||||
|
||||
{
|
||||
F f = this::g;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Test {
|
||||
interface I {
|
||||
void foo();
|
||||
}
|
||||
|
||||
private Object o;
|
||||
|
||||
public static void main(String[] args){
|
||||
I i = <error descr="Non-static field 'o' cannot be referenced from a static context">o</error>::wait;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
class Test {
|
||||
private static void m(int i) {System.out.println(i);}
|
||||
private static void <warning descr="Private method 'm(java.lang.Integer)' is never used">m</warning>(Integer i) {System.out.println(i);}
|
||||
|
||||
interface I {
|
||||
void foo(int p);
|
||||
}
|
||||
|
||||
static {
|
||||
I s = Test::m;
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
|
||||
static void m(Integer i) { }
|
||||
|
||||
interface I1 {
|
||||
void m(int x);
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
void m(Integer x);
|
||||
}
|
||||
|
||||
static void call(I1 i1) { System.out.println(i1); }
|
||||
static void call(I2 i2) { System.out.println(i2); }
|
||||
|
||||
static {
|
||||
call<error descr="Ambiguous method call: both 'Test2.call(I1)' and 'Test2.call(I2)' match">(Test2::m)</error>;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
class Test {
|
||||
|
||||
interface I0 {
|
||||
void m();
|
||||
}
|
||||
|
||||
interface I1 {
|
||||
void m(Object a);
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
void m(Object a1, Object a2);
|
||||
}
|
||||
|
||||
interface IVarargs {
|
||||
void m(Object... as);
|
||||
}
|
||||
|
||||
void call(I0 p) { }
|
||||
void call(I1 p) { }
|
||||
void call(I2 p) { }
|
||||
void call(IVarargs p) { }
|
||||
|
||||
void test() {
|
||||
call(() -> { });
|
||||
call<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(IVarargs)' match">(p1 -> { })</error>;
|
||||
call((p1, p2) -> {});
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
class Test {
|
||||
interface I { Object in<EOLError descr="';' expected"></EOLError>
|
||||
<error descr="Invalid method declaration; return type required">voke</error>(); }
|
||||
interface IStr { String foo(); }
|
||||
|
||||
public static void call(IStr str) {}
|
||||
public static void call(I i) { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
call<error descr="Ambiguous method call: both 'Test.call(IStr)' and 'Test.call(I)' match">(()-> null)</error>;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
class Test {
|
||||
interface I { Object invoke(); }
|
||||
interface IStr { String foo(); }
|
||||
|
||||
private static void call(IStr str) {
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
private static void <warning descr="Private method 'call(Test.I)' is never used">call</warning>(I i) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
call(()-> null);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
class Test {
|
||||
|
||||
interface I1 {String m();}
|
||||
interface I2 {void m();}
|
||||
|
||||
void call(I1 p) { }
|
||||
void call(I2 p) { }
|
||||
|
||||
void test() {
|
||||
call<error descr="Ambiguous method call: both 'Test.call(I1)' and 'Test.call(I2)' match">(() -> { throw new RuntimeException(); })</error>;
|
||||
call(() -> { if (true) return ""; throw new RuntimeException(); });
|
||||
call(() -> { if (true) return; throw new RuntimeException(); });
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
class Test {
|
||||
|
||||
interface A {
|
||||
A f();
|
||||
}
|
||||
interface B {}
|
||||
|
||||
static abstract class C implements A, B {}
|
||||
static abstract class D implements A, B {}
|
||||
|
||||
interface I<T> {
|
||||
T m(T arg);
|
||||
}
|
||||
|
||||
void bar(C c) {
|
||||
foo(c, <error descr="Incompatible return type A in lambda expression">x -> x.f()</error>);
|
||||
foo(c, x -> x);
|
||||
}
|
||||
|
||||
<T> void foo(T t1, I<T> t3) {}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class Test {
|
||||
interface I {
|
||||
void m();
|
||||
}
|
||||
|
||||
<T> void call(T t) {}
|
||||
<T extends Runnable> void call1(T t) {}
|
||||
|
||||
{
|
||||
call<error descr="'call(T)' in 'Test' cannot be applied to '(<lambda expression>)'">(() -> {})</error>;
|
||||
call1(() -> {});
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
class BBB {
|
||||
|
||||
static <T> void f() {
|
||||
TerminalOp<T, LinkedHashSet<T>> <warning descr="Variable 'reduceOp' is never used">reduceOp</warning> = BBB.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::add, LinkedHashSet::addAll);
|
||||
TerminalOp<T, LinkedHashSet<T>> <warning descr="Variable 'reduceOp' is never used">reduceOp</warning> = BBB.<T, LinkedHashSet<T>>makeRef(LinkedHashSet::new, LinkedHashSet::<warning descr="Unchecked call to 'add(E)' as a member of raw type 'HashSet'">add</warning>, LinkedHashSet::<warning descr="Unchecked call to 'addAll(Collection<? extends E>)' as a member of raw type 'AbstractCollection'">addAll</warning>);
|
||||
}
|
||||
|
||||
public static <T, U> TerminalOp<T, U> makeRef(U <warning descr="Parameter 'seed' is never used">seed</warning>, BiFunction<U, ? super T, U> <warning descr="Parameter 'reducer' is never used">reducer</warning>, BinaryOperator<U> <warning descr="Parameter 'combiner' is never used">combiner</warning>) {
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
interface I {
|
||||
static void a() {}
|
||||
}
|
||||
|
||||
interface J {
|
||||
void foo();
|
||||
}
|
||||
|
||||
class Test {
|
||||
{
|
||||
J j = I::a;
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
|
||||
interface I<T> {
|
||||
void m(List<T> l, T el);
|
||||
}
|
||||
|
||||
{
|
||||
I<String> i1 = List::add;
|
||||
System.out.println(i1);
|
||||
I i2 = List::<warning descr="Unchecked call to 'add(E)' as a member of raw type 'java.util.List'">add</warning>;
|
||||
System.out.println(i2);
|
||||
}
|
||||
}
|
||||
@@ -341,6 +341,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testIDEA120563() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testIDEA121400() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testIDEA123316() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testUnrelatedReturnInTypeArgs() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testIDEA123352() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testIDEA123518() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
public void testIDEA64103() { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); }
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FunctionalExpressionIncompleteHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/incomplete";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{
|
||||
new UnusedSymbolLocalInspection(),
|
||||
};
|
||||
}
|
||||
|
||||
public void testMissedFunctionalInterfaceMethodReturnType() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest(final boolean checkWarnings) {
|
||||
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
+6
@@ -78,6 +78,7 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testAmbiguitySpecificReturn() { doTest(true); }
|
||||
public void testFunctionalInterfaceAnnotation() { doTest(); }
|
||||
public void testFunctionalInterfaceAnnotation2() { doTest(); }
|
||||
public void testFunctionalInterfaceAnnotation3() { doTest(); }
|
||||
public void testAmbiguityReturnValueResolution() { doTest(); }
|
||||
public void testAmbiguityReturnValueResolution1() { doTest(); }
|
||||
public void testAmbiguityReturnValueResolution2() { doTest(true); }
|
||||
@@ -100,6 +101,11 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testBreakContinueInside() {doTest();}
|
||||
public void testSameLambdaParamNames() {doTest();}
|
||||
public void testIDEA123308() {doTest();}
|
||||
public void testIntersection() {doTest();}
|
||||
public void testNoBoxingInLambdaFormalParams() {doTest();}
|
||||
public void testGenericNotGenericInterfaceMethod() {doTest();}
|
||||
public void testInferredFromCast() {doTest();}
|
||||
public void testReferencedFromSelf() {doTest();}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.codeInsight.daemon.lambda;
|
||||
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.compiler.JavacQuirksInspection;
|
||||
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LightAdvHighlightingJdk8Test extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/advHighlighting";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{
|
||||
new JavacQuirksInspection(),
|
||||
};
|
||||
}
|
||||
|
||||
public void testUnderscore() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
+4
@@ -99,6 +99,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testQualifiersInStaticContext() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+20
@@ -75,6 +75,26 @@ public class MostSpecificResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteMethodInInterface() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testMostSpecificByReturnType() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDifferentParamsLength() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testNoReturnTypeResolutionForThrownException() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testBoxingAndOverloadResolution() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
+8
@@ -198,6 +198,14 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testOnlyLambdaAtTypeParameterPlace() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLiftedIntersectionType() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+8
@@ -237,6 +237,14 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRefOnStaticInterfaceMethod() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUncheckedMethodReference() throws Exception {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+7
-3
@@ -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.
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.application.options;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.options.SearchableConfigurable;
|
||||
import com.intellij.openapi.options.UnnamedConfigurable;
|
||||
@@ -34,6 +35,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
@@ -44,7 +46,8 @@ import java.util.Map;
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public abstract class ModuleAwareProjectConfigurable<T extends UnnamedConfigurable> implements SearchableConfigurable {
|
||||
public abstract class ModuleAwareProjectConfigurable<T extends UnnamedConfigurable> implements SearchableConfigurable,
|
||||
Configurable.NoScroll {
|
||||
@NotNull
|
||||
private final Project myProject;
|
||||
private final String myDisplayName;
|
||||
@@ -113,7 +116,8 @@ public abstract class ModuleAwareProjectConfigurable<T extends UnnamedConfigurab
|
||||
for (Module module : modules) {
|
||||
final T configurable = createModuleConfigurable(module);
|
||||
myModuleConfigurables.put(module, configurable);
|
||||
final JComponent component = configurable.createComponent();
|
||||
final JComponent component = new JBScrollPane(configurable.createComponent());
|
||||
component.setBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
cardPanel.add(component, module.getName());
|
||||
}
|
||||
moduleList.addListSelectionListener(new ListSelectionListener() {
|
||||
|
||||
+2
-1
@@ -329,6 +329,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
tool.inspectionStarted(inspectionManager, this, getPresentation(toolWrapper));
|
||||
}
|
||||
|
||||
final boolean headlessEnvironment = ApplicationManager.getApplication().isHeadlessEnvironment();
|
||||
final Map<String, InspectionToolWrapper> map = getInspectionWrappersMap(localTools);
|
||||
scope.accept(new PsiElementVisitor() {
|
||||
@Override
|
||||
@@ -336,7 +337,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (virtualFile == null) return;
|
||||
|
||||
if (myView == null) {
|
||||
if (myView == null && !headlessEnvironment) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,12 @@ class FindInProjectTask {
|
||||
try {
|
||||
myProgress.setIndeterminate(true);
|
||||
myProgress.setText("Scanning indexed files...");
|
||||
final Set<PsiFile> filesForFastWordSearch = getFilesForFastWordSearch();
|
||||
final Set<PsiFile> filesForFastWordSearch = ApplicationManager.getApplication().runReadAction(new Computable<Set<PsiFile>>() {
|
||||
@Override
|
||||
public Set<PsiFile> compute() {
|
||||
return getFilesForFastWordSearch();
|
||||
}
|
||||
});
|
||||
myProgress.setIndeterminate(false);
|
||||
|
||||
searchInFiles(filesForFastWordSearch, processPresentation, consumer);
|
||||
|
||||
@@ -54,7 +54,8 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
|
||||
myNavigationLabel.setEnabled(false);
|
||||
myFooterLabel.setEnabled(false);
|
||||
init();
|
||||
initCurrentStep();
|
||||
initCurrentStep(true);
|
||||
setSize(400, 300);
|
||||
System.setProperty(StartupActionScriptManager.STARTUP_WIZARD_MODE, "true");
|
||||
}
|
||||
|
||||
@@ -125,7 +126,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
|
||||
}
|
||||
if (e.getSource() == myBackButton) {
|
||||
myIndex--;
|
||||
initCurrentStep();
|
||||
initCurrentStep(false);
|
||||
return;
|
||||
}
|
||||
if (e.getSource() == myNextButton) {
|
||||
@@ -134,7 +135,7 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
|
||||
return;
|
||||
}
|
||||
myIndex++;
|
||||
initCurrentStep();
|
||||
initCurrentStep(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,8 +149,9 @@ public class CustomizeIDEWizardDialog extends DialogWrapper implements ActionLis
|
||||
super.doOKAction();
|
||||
}
|
||||
|
||||
private void initCurrentStep() {
|
||||
private void initCurrentStep(boolean forward) {
|
||||
final AbstractCustomizeWizardStep myCurrentStep = mySteps.get(myIndex);
|
||||
myCurrentStep.beforeShown(forward);
|
||||
myCardLayout.swipe(myContentPanel, myCurrentStep.getTitle(), JBCardLayout.SwipeDirection.AUTO, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
+10
-6
@@ -78,12 +78,7 @@ public class BackspaceAction extends EditorAction {
|
||||
|
||||
private static void doBackSpaceAtCaret(@NotNull Editor editor) {
|
||||
if(editor.getSelectionModel().hasSelection()) {
|
||||
int newOffset = editor.getSelectionModel().getSelectionStart();
|
||||
if (EditorActionUtil.canEditAtOffset(editor, newOffset)) {
|
||||
editor.getCaretModel().moveToOffset(newOffset);
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
EditorModificationUtil.deleteSelectedText(editor);
|
||||
}
|
||||
doBackspaceAction(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,4 +126,13 @@ public class BackspaceAction extends EditorAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doBackspaceAction(@NotNull Editor editor) {
|
||||
int newOffset = editor.getSelectionModel().getSelectionStart();
|
||||
if (EditorActionUtil.canEditAtOffset(editor, newOffset)) {
|
||||
editor.getCaretModel().moveToOffset(newOffset);
|
||||
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
EditorModificationUtil.deleteSelectedText(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-8
@@ -14,23 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: max
|
||||
* Date: May 14, 2002
|
||||
* Time: 7:18:30 PM
|
||||
* To change template for new class use
|
||||
* Code Style | Class Templates options (Tools | IDE Options).
|
||||
*/
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.EditorModificationUtil;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
|
||||
import com.intellij.openapi.ide.CopyPasteManager;
|
||||
|
||||
/*
|
||||
* Created by IntelliJ IDEA.
|
||||
* User: max
|
||||
* Date: May 14, 2002
|
||||
* Time: 7:18:30 PM
|
||||
*/
|
||||
public class DeleteToWordEndAction extends TextComponentEditorAction {
|
||||
public DeleteToWordEndAction() {
|
||||
super(new Handler(false));
|
||||
@@ -60,6 +59,12 @@ public class DeleteToWordEndAction extends TextComponentEditorAction {
|
||||
if (myNegateCamelMode) {
|
||||
camelMode = !camelMode;
|
||||
}
|
||||
|
||||
if (editor.getSelectionModel().hasSelection()) {
|
||||
EditorModificationUtil.deleteSelectedText(editor);
|
||||
return;
|
||||
}
|
||||
|
||||
deleteToWordEnd(editor, camelMode);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -24,9 +24,7 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
@@ -81,6 +79,10 @@ public class DeleteToWordStartAction extends TextComponentEditorAction {
|
||||
@Override
|
||||
public void executeWriteAction(Editor editor, DataContext dataContext) {
|
||||
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
|
||||
if (editor.getSelectionModel().hasSelection()) {
|
||||
BackspaceAction.doBackspaceAction(editor);
|
||||
return;
|
||||
}
|
||||
deleteToWordStart(editor);
|
||||
}
|
||||
|
||||
|
||||
@@ -363,21 +363,23 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean doNotExecuteBecauseAppIsInactive =
|
||||
!myApp.isActive() && !canExecuteOnInactiveApplication(cmd) && Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive");
|
||||
if (!Registry.is("focus.fix.lost.cursor")) {
|
||||
boolean doNotExecuteBecauseAppIsInactive =
|
||||
!myApp.isActive() && !canExecuteOnInactiveApplication(cmd) && Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive");
|
||||
|
||||
if (doNotExecuteBecauseAppIsInactive) {
|
||||
if (myCallbackOnActivation != null) {
|
||||
myCallbackOnActivation.setRejected();
|
||||
if (myFocusCommandOnAppActivation != null) {
|
||||
resetCommand(myFocusCommandOnAppActivation, true);
|
||||
if (doNotExecuteBecauseAppIsInactive) {
|
||||
if (myCallbackOnActivation != null) {
|
||||
myCallbackOnActivation.setRejected();
|
||||
if (myFocusCommandOnAppActivation != null) {
|
||||
resetCommand(myFocusCommandOnAppActivation, true);
|
||||
}
|
||||
}
|
||||
|
||||
myFocusCommandOnAppActivation = cmd;
|
||||
myCallbackOnActivation = result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
myFocusCommandOnAppActivation = cmd;
|
||||
myCallbackOnActivation = result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1152,6 +1154,7 @@ public class FocusManagerImpl extends IdeFocusManager implements Disposable {
|
||||
|
||||
@Override
|
||||
public boolean isFocusTransferEnabled() {
|
||||
if (Registry.is("focus.fix.lost.cursor")) return true;
|
||||
return myApp.isActive() || !Registry.is("actionSystem.suspendFocusTransferIfApplicationInactive");
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.ExpirableRunnable;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.FocusCommand;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
|
||||
@@ -452,7 +453,8 @@ public class FocusTrackback {
|
||||
}
|
||||
|
||||
public void cleanParentWindow() {
|
||||
if (myParentWindow != null) {
|
||||
if (!Registry.is("focus.fix.lost.cursor")) return;
|
||||
if (myParentWindow != null) {
|
||||
try {
|
||||
Method tmpLost = Window.class.getDeclaredMethod("setTemporaryLostComponent", Component.class);
|
||||
tmpLost.setAccessible(true);
|
||||
|
||||
@@ -390,3 +390,6 @@ editor.richcopy.debug=false
|
||||
editor.richcopy.max.size.megabytes=10
|
||||
allow.dialog.based.popups=false
|
||||
allow.dialog.based.popups.description=Allows to use a JDialog as popup toplevel
|
||||
|
||||
focus.fix.lost.cursor=true
|
||||
focus.fix.lost.cursor.description=See IDEA-79312
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
s<caret>text<caret>o<selection>t<caret></selection> text
|
||||
an<caret> l<caret>yet a<selection>not<caret></selection> line
|
||||
s<caret>text<caret>o<caret>r text
|
||||
an<caret>er l<caret>yet a<caret>her line
|
||||
+2
-2
@@ -1,2 +1,2 @@
|
||||
Ab<caret>Dabra<caret>Hum<selection><caret>D</selection>ump Hu<selection>mpDu<caret></selection>
|
||||
<selection>YetAnot<caret>HumpedWord</selection>
|
||||
Ab<caret>Dabra<caret>Hum<caret>ump Hu<caret>mp
|
||||
<caret>
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
<caret>some <caret>t
|
||||
<caret>ther <caret>t
|
||||
<caret>other line<caret>yet another line
|
||||
o<caret>er t<caret>t
|
||||
<caret> line<caret>yet another line
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
<caret>aCa<caret>
|
||||
<caret>pDump Hump<caret>mp
|
||||
Yet<caret>herHumpedWord
|
||||
Hum<caret>ump Hu<caret>mp
|
||||
<caret>
|
||||
+1
-1
@@ -75,7 +75,7 @@ public class InterfaceMayBeAnnotatedFunctionalInspection extends BaseInspection
|
||||
if (LambdaHighlightingUtil.checkInterfaceFunctional(aClass) != null) {
|
||||
return;
|
||||
}
|
||||
final List<MethodSignature> candidates = LambdaUtil.findFunctionCandidates(aClass);
|
||||
final List<HierarchicalMethodSignature> candidates = LambdaUtil.findFunctionCandidates(aClass);
|
||||
if (candidates == null || candidates.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ public class GitHistoryUtils {
|
||||
AUTHOR_NAME, AUTHOR_EMAIL);
|
||||
h.setStdoutSuppressed(true);
|
||||
h.addParameters(parser.getPretty(), "--encoding=UTF-8");
|
||||
h.addParameters("--full-history", "--sparse");
|
||||
h.addParameters("--full-history");
|
||||
h.addParameters("--date-order");
|
||||
h.addParameters(parameters);
|
||||
h.endOptions();
|
||||
|
||||
@@ -165,7 +165,9 @@ public class GitLogProvider implements VcsLogProvider {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return GitHistoryUtils.readCommits(myProject, root, userRegistry, GitHistoryUtils.LOG_ALL);
|
||||
List<String> parameters = new ArrayList<String>(GitHistoryUtils.LOG_ALL);
|
||||
parameters.add("--sparse");
|
||||
return GitHistoryUtils.readCommits(myProject, root, userRegistry, parameters);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -315,6 +317,7 @@ public class GitLogProvider implements VcsLogProvider {
|
||||
|
||||
// note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths
|
||||
if (filterCollection.getStructureFilter() != null) {
|
||||
filterParameters.add("--simplify-merges");
|
||||
filterParameters.add("--");
|
||||
for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) {
|
||||
filterParameters.add(file.getPath());
|
||||
|
||||
@@ -25,7 +25,6 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
@@ -48,7 +47,8 @@ import org.zmlx.hg4idea.util.HgErrorUtil;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.zmlx.hg4idea.util.HgUtil.*;
|
||||
import static org.zmlx.hg4idea.util.HgUtil.getNamesWithoutHashes;
|
||||
import static org.zmlx.hg4idea.util.HgUtil.getNewBranchNameFromUser;
|
||||
|
||||
public class HgBranchPopupActions {
|
||||
|
||||
@@ -62,8 +62,8 @@ public class HgBranchPopupActions {
|
||||
|
||||
ActionGroup createActions(@Nullable DefaultActionGroup toInsert) {
|
||||
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
|
||||
popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot()));
|
||||
popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot()));
|
||||
popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository));
|
||||
popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository));
|
||||
popupGroup.addAction(new HgShowUnnamedHeadsForCurrentBranchAction(myProject, myRepository));
|
||||
if (toInsert != null) {
|
||||
popupGroup.addAll(toInsert);
|
||||
@@ -92,24 +92,24 @@ public class HgBranchPopupActions {
|
||||
}
|
||||
|
||||
private static class HgNewBranchAction extends NewBranchAction<HgRepository> {
|
||||
@NotNull final VirtualFile myPreselectedRepo;
|
||||
@NotNull final HgRepository myPreselectedRepo;
|
||||
|
||||
HgNewBranchAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull VirtualFile preselectedRepo) {
|
||||
HgNewBranchAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull HgRepository preselectedRepo) {
|
||||
super(project, repositories);
|
||||
myPreselectedRepo = preselectedRepo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final String name = getNewBranchNameFromUser(myProject, "Create New Branch");
|
||||
final String name = getNewBranchNameFromUser(myPreselectedRepo, "Create New Branch");
|
||||
if (name == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
new HgBranchCreateCommand(myProject, myPreselectedRepo, name).execute(new HgCommandResultHandler() {
|
||||
new HgBranchCreateCommand(myProject, myPreselectedRepo.getRoot(), name).execute(new HgCommandResultHandler() {
|
||||
@Override
|
||||
public void process(@Nullable HgCommandResult result) {
|
||||
getRepositoryManager(myProject).updateRepository(myPreselectedRepo);
|
||||
myPreselectedRepo.update();
|
||||
if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
|
||||
new HgCommandResultNotifier(myProject)
|
||||
.notifyError(result, "Creation failed", "Branch creation [" + name + "] failed");
|
||||
@@ -124,11 +124,11 @@ public class HgBranchPopupActions {
|
||||
}
|
||||
|
||||
private static class HgNewBookmarkAction extends DumbAwareAction {
|
||||
protected final List<HgRepository> myRepositories;
|
||||
protected Project myProject;
|
||||
@NotNull final VirtualFile myPreselectedRepo;
|
||||
@NotNull protected final List<HgRepository> myRepositories;
|
||||
@NotNull protected Project myProject;
|
||||
@NotNull final HgRepository myPreselectedRepo;
|
||||
|
||||
HgNewBookmarkAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull VirtualFile preselectedRepo) {
|
||||
HgNewBookmarkAction(@NotNull Project project, @NotNull List<HgRepository> repositories, @NotNull HgRepository preselectedRepo) {
|
||||
super("New Bookmark", "Create new bookmark", null);
|
||||
myProject = project;
|
||||
myRepositories = repositories;
|
||||
@@ -146,12 +146,12 @@ public class HgBranchPopupActions {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
|
||||
final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myProject);
|
||||
final HgBookmarkDialog bookmarkDialog = new HgBookmarkDialog(myPreselectedRepo);
|
||||
bookmarkDialog.show();
|
||||
if (bookmarkDialog.isOK()) {
|
||||
try {
|
||||
final String name = bookmarkDialog.getName();
|
||||
new HgBookmarkCommand(myProject, myPreselectedRepo, name).createBookmark(bookmarkDialog.isActive());
|
||||
new HgBookmarkCommand(myProject, myPreselectedRepo.getRoot(), name).createBookmark(bookmarkDialog.isActive());
|
||||
}
|
||||
catch (HgCommandException exception) {
|
||||
HgAbstractGlobalAction.handleException(myProject, exception);
|
||||
|
||||
@@ -38,6 +38,8 @@ import org.zmlx.hg4idea.util.HgUtil;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE;
|
||||
|
||||
public class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(HgLogProvider.class);
|
||||
@@ -47,8 +49,6 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
@NotNull private final VcsLogRefManager myRefSorter;
|
||||
@NotNull private final VcsLogObjectsFactory myVcsObjectsFactory;
|
||||
|
||||
private static final String RECENT_HEAD = "tip";
|
||||
|
||||
public HgLogProvider(@NotNull Project project, @NotNull HgRepositoryManager repositoryManager, @NotNull VcsLogObjectsFactory factory) {
|
||||
myProject = project;
|
||||
myRepositoryManager = repositoryManager;
|
||||
@@ -119,7 +119,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
}
|
||||
String currentRevision = repository.getCurrentRevision();
|
||||
if (currentRevision != null) { // null => fresh repository
|
||||
refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(currentRevision), RECENT_HEAD, HgRefManager.HEAD, root));
|
||||
refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(currentRevision), TIP_REFERENCE, HgRefManager.HEAD, root));
|
||||
}
|
||||
for (HgNameWithHashInfo tagInfo : tags) {
|
||||
refs.add(myVcsObjectsFactory.createRef(tagInfo.getHash(), tagInfo.getName(), HgRefManager.TAG, root));
|
||||
@@ -172,7 +172,7 @@ public class HgLogProvider implements VcsLogProvider {
|
||||
|
||||
boolean atLeastOneBranchExists = false;
|
||||
for (String branchName : filterCollection.getBranchFilter().getBranchNames()) {
|
||||
if (branchName.equals(RECENT_HEAD) || branchExists(repository, branchName)) {
|
||||
if (branchName.equals(TIP_REFERENCE) || branchExists(repository, branchName)) {
|
||||
filterParameters.add(prepareParameter("branch", branchName));
|
||||
atLeastOneBranchExists = true;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package org.zmlx.hg4idea.ui;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.ValidationInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import com.intellij.ui.components.JBCheckBox;
|
||||
import com.intellij.ui.components.JBLabel;
|
||||
import com.intellij.ui.components.JBTextField;
|
||||
@@ -11,8 +9,11 @@ import com.intellij.util.ui.GridBag;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
import org.zmlx.hg4idea.util.HgReferenceValidator;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
|
||||
import static com.intellij.util.ui.UIUtil.DEFAULT_HGAP;
|
||||
@@ -22,11 +23,13 @@ import static com.intellij.util.ui.UIUtil.DEFAULT_VGAP;
|
||||
* @author Nadya Zabrodina
|
||||
*/
|
||||
public class HgBookmarkDialog extends DialogWrapper {
|
||||
@NotNull private HgRepository myRepository;
|
||||
@NotNull private JBTextField myBookmarkName;
|
||||
@NotNull private JBCheckBox myActiveCheckbox;
|
||||
|
||||
public HgBookmarkDialog(@Nullable Project project) {
|
||||
super(project, false);
|
||||
public HgBookmarkDialog(@NotNull HgRepository repository) {
|
||||
super(repository.getProject(), false);
|
||||
myRepository = repository;
|
||||
setTitle("Create Bookmark");
|
||||
setResizable(false);
|
||||
init();
|
||||
@@ -62,6 +65,12 @@ public class HgBookmarkDialog extends DialogWrapper {
|
||||
|
||||
JLabel icon = new JLabel(UIUtil.getQuestionIcon(), SwingConstants.LEFT);
|
||||
myBookmarkName = new JBTextField(13);
|
||||
myBookmarkName.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void textChanged(DocumentEvent e) {
|
||||
validateFields();
|
||||
}
|
||||
});
|
||||
|
||||
JBLabel bookmarkLabel = new JBLabel("Bookmark name:");
|
||||
bookmarkLabel.setLabelFor(myBookmarkName);
|
||||
@@ -75,6 +84,19 @@ public class HgBookmarkDialog extends DialogWrapper {
|
||||
return contentPanel;
|
||||
}
|
||||
|
||||
private void validateFields() {
|
||||
HgReferenceValidator validator = HgReferenceValidator.newInstance(myRepository);
|
||||
String name = getName();
|
||||
if (!validator.checkInput(name)) {
|
||||
String message = validator.getErrorText(name);
|
||||
setErrorText(message == null ? "You have to specify bookmark name." : message);
|
||||
setOKActionEnabled(false);
|
||||
return;
|
||||
}
|
||||
setErrorText(null);
|
||||
setOKActionEnabled(true);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return !myActiveCheckbox.isSelected();
|
||||
}
|
||||
@@ -83,14 +105,4 @@ public class HgBookmarkDialog extends DialogWrapper {
|
||||
public String getName() {
|
||||
return myBookmarkName.getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ValidationInfo doValidate() {
|
||||
String message = "You have to specify bookmark name.";
|
||||
if (StringUtil.isEmptyOrSpaces(getName())) {
|
||||
return new ValidationInfo(message, myBookmarkName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE;
|
||||
|
||||
public class HgCommonDialogWithChoices extends DialogWrapper {
|
||||
|
||||
|
||||
@@ -119,7 +121,8 @@ public class HgCommonDialogWithChoices extends DialogWrapper {
|
||||
HgRepository repo = hgRepositorySelectorComponent.getRepository();
|
||||
branchSelector.setModel(new DefaultComboBoxModel(repo.getOpenedBranches().toArray()));
|
||||
DefaultComboBoxModel tagComboBoxModel = new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getTags()).toArray());
|
||||
tagComboBoxModel.addElement("tip"); //HgRepository does not store 'tip' tag because it is internal and not included in tags file
|
||||
tagComboBoxModel
|
||||
.addElement(TIP_REFERENCE); //HgRepository does not store 'tip' tag because it is internal and not included in tags file
|
||||
tagSelector.setModel(tagComboBoxModel);
|
||||
bookmarkSelector.setModel(new DefaultComboBoxModel(HgUtil.getNamesWithoutHashes(repo.getBookmarks()).toArray()));
|
||||
update();
|
||||
|
||||
@@ -14,11 +14,12 @@ package org.zmlx.hg4idea.ui;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
import org.zmlx.hg4idea.util.HgReferenceValidator;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
@@ -34,17 +35,10 @@ public class HgTagDialog extends DialogWrapper {
|
||||
public HgTagDialog(@NotNull Project project, @NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
|
||||
super(project, false);
|
||||
hgRepositorySelectorComponent.setTitle("Select repository to tag");
|
||||
DocumentListener documentListener = new DocumentListener() {
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
update();
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
update();
|
||||
DocumentListener documentListener = new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
validateFields();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -67,19 +61,23 @@ public class HgTagDialog extends DialogWrapper {
|
||||
private void setRoots(@NotNull Collection<HgRepository> repos, @Nullable HgRepository selectedRepo) {
|
||||
hgRepositorySelectorComponent.setRoots(repos);
|
||||
hgRepositorySelectorComponent.setSelectedRoot(selectedRepo);
|
||||
update();
|
||||
}
|
||||
|
||||
protected JComponent createCenterPanel() {
|
||||
return contentPanel;
|
||||
}
|
||||
|
||||
private void update() {
|
||||
setOKActionEnabled(validateOptions());
|
||||
}
|
||||
|
||||
private boolean validateOptions() {
|
||||
return !StringUtil.isEmptyOrSpaces(tagTxt.getText());
|
||||
private void validateFields() {
|
||||
HgReferenceValidator validator = HgReferenceValidator.newInstance(hgRepositorySelectorComponent.getRepository());
|
||||
String name = getTagName();
|
||||
if (!validator.checkInput(name)) {
|
||||
String message = validator.getErrorText(name);
|
||||
setErrorText(message == null ? "You have to specify tag name." : message);
|
||||
setOKActionEnabled(false);
|
||||
return;
|
||||
}
|
||||
setErrorText(null);
|
||||
setOKActionEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 org.zmlx.hg4idea.util;
|
||||
|
||||
import com.intellij.openapi.ui.InputValidatorEx;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.zmlx.hg4idea.util.HgUtil.TIP_REFERENCE;
|
||||
|
||||
public class HgReferenceValidator implements InputValidatorEx {
|
||||
|
||||
private final HgRepository myRepository;
|
||||
private String myErrorText;
|
||||
|
||||
private static final Pattern ILLEGAL = Pattern.compile(
|
||||
".*:.*|" + // colon character is not allowed
|
||||
"[0-9]*" // reference name couldn't contain only digits
|
||||
);
|
||||
|
||||
private HgReferenceValidator(@NotNull HgRepository repository) {
|
||||
myRepository = repository;
|
||||
}
|
||||
|
||||
public static HgReferenceValidator newInstance(@NotNull HgRepository repository) {
|
||||
return new HgReferenceValidator(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInput(@Nullable String name) {
|
||||
if (StringUtil.isEmptyOrSpaces(name)) {
|
||||
return false;
|
||||
}
|
||||
if (ILLEGAL.matcher(name).matches()) {
|
||||
myErrorText = "Invalid name for branch/tag";
|
||||
return false;
|
||||
}
|
||||
return !isReservedWord(name) && !hasConflictsWithAnotherBranch(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canClose(@Nullable String name) {
|
||||
return checkInput(name);
|
||||
}
|
||||
|
||||
boolean isReservedWord(@Nullable String name) {
|
||||
myErrorText = TIP_REFERENCE.equals(name) ? String.format("The name \'%s\' is reserved.", name) : null;
|
||||
return myErrorText != null;
|
||||
}
|
||||
|
||||
boolean hasConflictsWithAnotherBranch(@Nullable String name) {
|
||||
Collection<String> branches = myRepository.getBranches().keySet();
|
||||
String currentBranch = myRepository.getCurrentBranch(); // branches set doesn't contain uncommitted branch -> need an addition check
|
||||
myErrorText = currentBranch.equals(name) || branches.contains(name)
|
||||
? String.format("A branch with the \'%s\' name already exists", name) : null;
|
||||
return myErrorText != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getErrorText(@Nullable String inputString) {
|
||||
return myErrorText;
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@ public abstract class HgUtil {
|
||||
public static final int MANY_FILES = 100;
|
||||
private static final Logger LOG = Logger.getInstance(HgUtil.class);
|
||||
public static final String DOT_HG = ".hg";
|
||||
public static final String TIP_REFERENCE = "tip";
|
||||
|
||||
public static File copyResourceToTempFile(String basename, String extension) throws IOException {
|
||||
final InputStream in = HgUtil.class.getClassLoader().getResourceAsStream("python/" + basename + extension);
|
||||
@@ -323,14 +324,17 @@ public abstract class HgUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a message dialog to enter the name of new branch.
|
||||
* @return name of new branch or {@code null} if user has cancelled the dialog.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getNewBranchNameFromUser(@NotNull Project project,
|
||||
@NotNull String dialogTitle) {
|
||||
return Messages.showInputDialog(project, "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon());
|
||||
}
|
||||
* Shows a message dialog to enter the name of new branch.
|
||||
*
|
||||
* @return name of new branch or {@code null} if user has cancelled the dialog.
|
||||
*/
|
||||
@Nullable
|
||||
public static String getNewBranchNameFromUser(@NotNull HgRepository repository,
|
||||
@NotNull String dialogTitle) {
|
||||
return Messages.showInputDialog(repository.getProject(), "Enter the name of new branch:", dialogTitle, Messages.getQuestionIcon(), "",
|
||||
HgReferenceValidator.newInstance(repository));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks is a merge operation is in progress on the given repository.
|
||||
* Actually gets the number of parents of the current revision. If there are 2 parents, then a merge is going on. Otherwise there is
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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 hg4idea.test.validator;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import hg4idea.test.HgPlatformTest;
|
||||
import hg4idea.test.HgTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.zmlx.hg4idea.repo.HgRepository;
|
||||
import org.zmlx.hg4idea.util.HgReferenceValidator;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static com.intellij.openapi.vcs.Executor.cd;
|
||||
import static com.intellij.openapi.vcs.Executor.echo;
|
||||
import static hg4idea.test.HgExecutor.hg;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class HgReferenceValidatorTest extends HgPlatformTest {
|
||||
|
||||
private HgReferenceValidator myValidator;
|
||||
private static final String BRANCH_NAME = "Abranch";
|
||||
private static final String UNCOMMITTED_BRANCH = "uncommitted new branch";
|
||||
|
||||
@NotNull private final String myBranchName;
|
||||
private final boolean myExpected;
|
||||
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
HgTestUtil.updateDirectoryMappings(myProject, myRepository);
|
||||
HgRepository hgRepository = HgUtil.getRepositoryManager(myProject).getRepositoryForRoot(myRepository);
|
||||
assertNotNull(hgRepository);
|
||||
myValidator = HgReferenceValidator.newInstance(hgRepository);
|
||||
cd(myRepository);
|
||||
hg("branch '" + BRANCH_NAME + "'");
|
||||
String firstFile = "file.txt";
|
||||
echo(firstFile, BRANCH_NAME);
|
||||
hg("commit -m 'createdBranch " + BRANCH_NAME + "' ");
|
||||
hg("branch '" + UNCOMMITTED_BRANCH + "'");
|
||||
hgRepository.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
HgReferenceValidatorTest.super.tearDown();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors", "UnusedParameters"})
|
||||
public HgReferenceValidatorTest(@NotNull String name, @NotNull String branchName, boolean expected) {
|
||||
myBranchName = branchName;
|
||||
myExpected = expected;
|
||||
}
|
||||
|
||||
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
public static Collection<Object[]> createData() {
|
||||
return ContainerUtil.newArrayList(new Object[][]{
|
||||
{"WORD", "branch", true},
|
||||
{"UNDERSCORED_WORD", "new_branch", true},
|
||||
{"HIERARCHY", "user/branch", true},
|
||||
{"HIERARCHY_2", "user/branch/sub_branch", true},
|
||||
{"BEGINS_WITH_SLASH", "/branch", true},
|
||||
{"WITH_DOTS", "complex.branch.name", true},
|
||||
{"WITH_WHITESPACES", "branch with whitespaces", true},
|
||||
{"WITH_SPECIAL_CHARS", "bra~nch-^%$", true},
|
||||
{"NOT_RESERVED", "TIP", true},
|
||||
{"CONTAINS_COLON", "bra:nch", false},
|
||||
{"ONLY_DIGITS", "876876", false},
|
||||
{"START_WITH_COLON", ":branch", false},
|
||||
{"ENDS_WITH_COLON", "branch:", false},
|
||||
{"RESERVED_WORD", "tip", false},
|
||||
{"BRANCH_CONFLICT", BRANCH_NAME, false},
|
||||
{"UNCOMMITTED_BRANCH_CONFLICT", UNCOMMITTED_BRANCH, false},
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValid() {
|
||||
assertEquals(" Wrong validation for " + myBranchName, myExpected, myValidator.checkInput(myBranchName));
|
||||
assertEquals(" Should be valid " + myBranchName, myExpected, myValidator.canClose(myBranchName));
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 50 KiB |
Reference in New Issue
Block a user