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:
+11
-7
@@ -48,11 +48,11 @@ public class HighlightControlFlowUtil {
|
||||
private HighlightControlFlowUtil() { }
|
||||
|
||||
@Nullable
|
||||
public static HighlightInfo checkMissingReturnStatement(PsiMethod method) {
|
||||
PsiCodeBlock body = method.getBody();
|
||||
public static HighlightInfo checkMissingReturnStatement(PsiCodeBlock body, PsiType returnType) {
|
||||
|
||||
if (body == null
|
||||
|| method.getReturnType() == null
|
||||
|| PsiType.VOID.equals(method.getReturnType())) {
|
||||
|| returnType == null
|
||||
|| PsiType.VOID.equals(returnType)) {
|
||||
return null;
|
||||
}
|
||||
// do not compute constant expressions for if() statement condition
|
||||
@@ -68,9 +68,13 @@ public class HighlightControlFlowUtil {
|
||||
HighlightInfoType.ERROR,
|
||||
context,
|
||||
JavaErrorMessages.message("missing.return.statement"));
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new AddReturnFix(method));
|
||||
IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fix);
|
||||
final PsiElement parent = body.getParent();
|
||||
if (parent instanceof PsiMethod) {
|
||||
final PsiMethod method = (PsiMethod)parent;
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new AddReturnFix(method));
|
||||
IntentionAction fix = QUICK_FIX_FACTORY.createMethodReturnFix(method, PsiType.VOID, true);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, fix);
|
||||
}
|
||||
return highlightInfo;
|
||||
}
|
||||
}
|
||||
|
||||
+24
-4
@@ -282,6 +282,12 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
} else {
|
||||
myHolder.add(HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, "Lambda expression not expected here"));
|
||||
}
|
||||
if (!myHolder.hasErrorResults()) {
|
||||
final PsiElement body = expression.getBody();
|
||||
if (body instanceof PsiCodeBlock) {
|
||||
myHolder.add(HighlightControlFlowUtil.checkUnreachableStatement((PsiCodeBlock)body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,10 +339,24 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
super.visitJavaToken(token);
|
||||
if (!myHolder.hasErrorResults()
|
||||
&& token.getTokenType() == JavaTokenType.RBRACE
|
||||
&& token.getParent() instanceof PsiCodeBlock
|
||||
&& token.getParent().getParent() instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)token.getParent().getParent();
|
||||
myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(method));
|
||||
&& token.getParent() instanceof PsiCodeBlock) {
|
||||
|
||||
final PsiElement gParent = token.getParent().getParent();
|
||||
final PsiCodeBlock codeBlock;
|
||||
final PsiType returnType;
|
||||
if (gParent instanceof PsiMethod) {
|
||||
PsiMethod method = (PsiMethod)gParent;
|
||||
codeBlock = method.getBody();
|
||||
returnType = method.getReturnType();
|
||||
} else if (gParent instanceof PsiLambdaExpression) {
|
||||
final PsiElement body = ((PsiLambdaExpression)gParent).getBody();
|
||||
if (!(body instanceof PsiCodeBlock)) return;
|
||||
codeBlock = (PsiCodeBlock)body;
|
||||
returnType = LambdaUtil.getFunctionalInterfaceReturnType((PsiLambdaExpression)gParent);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
myHolder.add(HighlightControlFlowUtil.checkMissingReturnStatement(codeBlock, returnType));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-1
@@ -97,7 +97,12 @@ public class RedundantLambdaCodeBlockInspection extends BaseJavaLocalInspectionT
|
||||
return returnStatement.getReturnValue();
|
||||
}
|
||||
else {
|
||||
return ((PsiExpressionStatement)statements[0]).getExpression();
|
||||
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
|
||||
final PsiType psiType = expression.getType();
|
||||
if (psiType != PsiType.VOID) {
|
||||
return null;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +92,25 @@ public class LambdaUtil {
|
||||
public static boolean isLambdaFullyInferred(PsiLambdaExpression expression, PsiType functionalInterfaceType) {
|
||||
if (expression.getParameterList().getParametersCount() > 0 ||
|
||||
getFunctionalInterfaceReturnType(functionalInterfaceType) != PsiType.VOID) { //todo check that void lambdas without params check
|
||||
if (functionalInterfaceType instanceof PsiClassType && ((PsiClassType)functionalInterfaceType).isRaw()) return false;
|
||||
if (!checkRawAcceptable(expression, functionalInterfaceType)) {
|
||||
return false;
|
||||
}
|
||||
return !dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkRawAcceptable(PsiLambdaExpression expression, PsiType functionalInterfaceType) {
|
||||
PsiElement parent = expression.getParent();
|
||||
while (parent instanceof PsiParenthesizedExpression) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof PsiExpressionList && functionalInterfaceType instanceof PsiClassType && ((PsiClassType)functionalInterfaceType).isRaw()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
|
||||
final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(functionalInterfaceType);
|
||||
|
||||
+11
-3
@@ -850,9 +850,17 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiReturnStatement) {
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
|
||||
if (method != null) {
|
||||
expectedType = method.getReturnType();
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
|
||||
if (lambdaExpression != null) {
|
||||
expectedType = LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression.getFunctionalInterfaceType());
|
||||
if (expectedType == null) {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
} else {
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class);
|
||||
if (method != null) {
|
||||
expectedType = method.getReturnType();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiExpressionList) {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ class Test {
|
||||
{
|
||||
boolean flag = true;
|
||||
I i = flag ? (() -> 123) : (() -> 222);
|
||||
I i1 = flag ? (<error descr="Missing return value">() -> {}</error>) : (() -> 222);
|
||||
I i1 = flag ? (() -> {<error descr="Missing return statement">}</error>) : (() -> 222);
|
||||
Object i2 = flag ? (<error descr="Target type of a lambda conversion must be an interface">() -> 42</error>) : (<error descr="Target type of a lambda conversion must be an interface">() -> 222</error>);
|
||||
I i3 = flag ? (<error descr="Incompatible parameter types in lambda expression">(x) -> 42</error>) : (() -> 222);
|
||||
I i4 = flag ? (() -> 42) : new I() {
|
||||
|
||||
+4
-4
@@ -18,7 +18,7 @@ class Test2 {
|
||||
}
|
||||
{
|
||||
IntReturnType aI = <error descr="Incompatible return type void in lambda expression">() -> System.out.println()</error>;
|
||||
IntReturnType aI1 = <error descr="Missing return value">() -> {System.out.println();}</error>;
|
||||
IntReturnType aI1 = () -> {System.out.println();<error descr="Missing return statement">}</error>;
|
||||
IntReturnType aI2 = () -> {return 1;};
|
||||
IntReturnType aI3 = () -> 1;
|
||||
}
|
||||
@@ -32,10 +32,10 @@ class Test3 {
|
||||
}
|
||||
{
|
||||
XReturnType<Object> aI = <error descr="Incompatible return type void in lambda expression">() -> System.out.println()</error>;
|
||||
XReturnType<Object> aI1 = <error descr="Missing return value">() -> {System.out.println();}</error>;
|
||||
XReturnType<Object> aI1 = () -> {System.out.println();<error descr="Missing return statement">}</error>;
|
||||
XReturnType<Object> aI2 = () -> {return 1;};
|
||||
XReturnType<Object> aI3 = () -> 1;
|
||||
XReturnType<Object> aI4 = <error descr="Missing return value">() -> {}</error>;
|
||||
XReturnType<Object> aI4 = () -> {<error descr="Missing return statement">}</error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class Test4 {
|
||||
|
||||
{
|
||||
YXReturnType<Object> aI = <error descr="Incompatible return type void in lambda expression">() -> System.out.println()</error>;
|
||||
YXReturnType<Object> aI1 = <error descr="Missing return value">() -> {System.out.println();}</error>;
|
||||
YXReturnType<Object> aI1 = () -> {System.out.println();<error descr="Missing return statement">}</error>;
|
||||
YXReturnType<Object> aI2 = <error descr="Incompatible return type int in lambda expression">() -> {return 1;}</error>;
|
||||
YXReturnType<Object> aI3 = <error descr="Incompatible return type int in lambda expression">() -> 1</error>;
|
||||
YXReturnType<Object> aI4 = () -> new Y<Object>(){};
|
||||
|
||||
+12
@@ -58,3 +58,15 @@ class Test4 {
|
||||
public interface TerminalOp1<T, U> extends IntermediateOp1<T, U> {}
|
||||
|
||||
}
|
||||
|
||||
class Test5 {
|
||||
{
|
||||
Block empty = x -> {};
|
||||
Block<?> empty1 = x -> {};
|
||||
System.out.println((Block) x -> {});
|
||||
}
|
||||
|
||||
interface Block<T> {
|
||||
void apply(T t);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
class Test1 {
|
||||
interface Extractor<T, W> {
|
||||
Option<W> unapply(T t);
|
||||
}
|
||||
|
||||
public static abstract class Option<T> {
|
||||
private static class None<T> extends Option<T> {}
|
||||
|
||||
private static final Option NONE = new None();
|
||||
|
||||
public static <T> Option<T> none() {
|
||||
return NONE;
|
||||
}
|
||||
|
||||
public static <T> Option<T> option(T value) {
|
||||
if (value == null) {
|
||||
return NONE;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
Extractor<String, Integer> e = s -> {
|
||||
if (s.equals("1")) {
|
||||
return Option.option(1);
|
||||
} else {
|
||||
return Option.none();
|
||||
}
|
||||
};
|
||||
|
||||
Extractor<String, Integer> e1 = <error descr="Incompatible return type Option<String> in lambda expression">s -> {
|
||||
if (s.equals("1")) {
|
||||
return Option.option(1);
|
||||
} else {
|
||||
return Option.option("2");
|
||||
}
|
||||
}</error>;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Test1 {
|
||||
{
|
||||
Comparable<String> c = o -> {
|
||||
if (o == null) return 1;
|
||||
return -1;
|
||||
<error descr="Unreachable statement">System.out.println("Hello");</error>
|
||||
};
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// "Replace with one line expression" "false"
|
||||
class Test {
|
||||
{
|
||||
Runnable c = () -> <caret>{foo();};
|
||||
}
|
||||
|
||||
int foo() {return 1;}
|
||||
}
|
||||
+8
@@ -132,6 +132,14 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testVariableInitialization() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnreachableStatement() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testReturnValue() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ public class DataLanguageBlockWrapper implements ASTBlock, BlockEx, BlockWithPar
|
||||
if (node != null) {
|
||||
final PsiElement psi = node.getPsi();
|
||||
if (psi != null) {
|
||||
language = psi.getLanguage();
|
||||
language = psi.getContainingFile().getLanguage();
|
||||
}
|
||||
}
|
||||
myLanguage = language;
|
||||
|
||||
Reference in New Issue
Block a user