consumer,
diff --git a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementVisitor.java b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementVisitor.java
index 9cc26549c24f..1a18e7b48d53 100644
--- a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementVisitor.java
+++ b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -21,6 +21,13 @@ package com.intellij.psi;
import com.intellij.util.containers.Stack;
+/**
+ * a JavaElementVisitor which also visits all children elements
+ * in a tree pre-order, see Tree traversal:Pre-order for details.
+ *
+ * Note: This visitor handles all elements recursively, so it can consume a large amount of stack space for very deep trees.
+ * For such deep trees please consider using {@link JavaRecursiveElementWalkingVisitor} instead.
+ */
public abstract class JavaRecursiveElementVisitor extends JavaElementVisitor {
// This stack thing is intended to prevent exponential child traversing due to visitReferenceExpression calls both visitRefElement
// and visitExpression.
diff --git a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java
index d5ed67d3525c..9cbb53998336 100644
--- a/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java
+++ b/java/java-psi-api/src/com/intellij/psi/JavaRecursiveElementWalkingVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -21,6 +21,13 @@ package com.intellij.psi;
import org.jetbrains.annotations.NotNull;
+/**
+ * a JavaElementVisitor which also visits all children elements
+ * in a tree pre-order, see Tree traversal:Pre-order for details.
+ *
+ * Note: This visitor handles all containing elements without consuming stack space, so it can be used even for very deep trees.
+ * Note 2: This visitor works for source-based PSI only. Any elements implementing {@link PsiCompiledElement} will be rejected.
+ */
public abstract class JavaRecursiveElementWalkingVisitor extends JavaElementVisitor {
private final PsiWalkingState myWalkingState = new PsiWalkingState(this){
@Override
diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
index 7e0786281066..5872b4f76d96 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -520,7 +520,8 @@ public class LambdaUtil {
}
else if (statements[0] instanceof PsiExpressionStatement) {
expression = ((PsiExpressionStatement)statements[0]).getExpression();
- } else if (statements[0] instanceof PsiBlockStatement) {
+ }
+ else if (statements[0] instanceof PsiBlockStatement) {
return extractSingleExpressionFromBody(((PsiBlockStatement)statements[0]).getCodeBlock());
}
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
index 6141e725b213..5da8840fc108 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java
@@ -557,6 +557,9 @@ public final class PsiUtil extends PsiUtilCore {
!JavaVersionService.getInstance().isAtLeast(((PsiCapturedWildcardType)lastParmType).getContext(), JavaSdkVersion.JDK_1_8)) {
lastParmType = ((PsiCapturedWildcardType)lastParmType).getWildcard();
}
+ if (lastParmType instanceof PsiClassType) {
+ lastParmType = ((PsiClassType)lastParmType).setLanguageLevel(languageLevel);
+ }
for (int i = parms.length - 1; i < args.length; i++) {
PsiType argType = args[i];
if (argType == null || !function.isApplicable(lastParmType, argType, allowUncheckedConversion, i)) {
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 9d482cd4d9a6..809dc516d992 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -78,6 +78,7 @@ public class TypeConversionUtil {
return "FAKE TYPE";
}
};
+ private static final Key ORIGINAL_CONTEXT = Key.create("ORIGINAL_CONTEXT");
static {
TYPE_TO_RANK_MAP.put(PsiType.BYTE, BYTE_RANK);
@@ -1291,7 +1292,7 @@ public class TypeConversionUtil {
@Override
public PsiType visitClassType(PsiClassType classType) {
final PsiClass aClass = classType.resolve();
- if (aClass instanceof PsiTypeParameter) {
+ if (aClass instanceof PsiTypeParameter && !isFreshVariable((PsiTypeParameter)aClass)) {
return typeParameterErasure((PsiTypeParameter)aClass, beforeSubstitutor);
}
return classType.rawType();
@@ -1474,6 +1475,19 @@ public class TypeConversionUtil {
return true;
}
+ public static boolean areSameFreshVariables(PsiTypeParameter p1, PsiTypeParameter p2) {
+ final PsiElement originalContext = p1.getUserData(ORIGINAL_CONTEXT);
+ return originalContext != null && originalContext == p2.getUserData(ORIGINAL_CONTEXT);
+ }
+
+ public static boolean isFreshVariable(PsiTypeParameter typeParameter) {
+ return typeParameter.getUserData(ORIGINAL_CONTEXT) != null;
+ }
+
+ public static void markAsFreshVariable(PsiTypeParameter parameter, PsiElement context) {
+ parameter.putUserData(ORIGINAL_CONTEXT, context);
+ }
+
private interface Caster {
@NotNull
Object cast(@NotNull Object operand);
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
index 9c4492eb9cb3..e5a2ee13331b 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java
@@ -16,10 +16,7 @@
package com.intellij.codeInsight;
import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.RecursionGuard;
-import com.intellij.openapi.util.RecursionManager;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.PsiClassImplUtil;
@@ -49,7 +46,6 @@ import java.util.*;
*/
public class ExceptionUtil {
@NonNls private static final String CLONE_METHOD_NAME = "clone";
- public static final RecursionGuard ourThrowsGuard = RecursionManager.createGuard("checkedExceptionsGuard");
private ExceptionUtil() {}
@@ -457,7 +453,7 @@ public class ExceptionUtil {
return Collections.emptyList();
}
- final PsiSubstitutor substitutor = getSubstitutor(result, methodCall);
+ final PsiSubstitutor substitutor = result.getSubstitutor();
if (!isArrayClone(method, methodCall) && methodCall instanceof PsiMethodCallExpression) {
final PsiFile containingFile = (containingMethod == null ? methodCall : containingMethod).getContainingFile();
final MethodResolverProcessor processor = new MethodResolverProcessor((PsiMethodCallExpression)methodCall, containingFile);
@@ -471,7 +467,7 @@ public class ExceptionUtil {
if (element instanceof PsiMethod &&
MethodSignatureUtil.areSignaturesEqual(method, (PsiMethod)element) &&
!MethodSignatureUtil.isSuperMethod((PsiMethod)element, method)) {
- return Pair.create((PsiMethod)element, getSubstitutor(info, methodCall));
+ return Pair.create((PsiMethod)element, info.getSubstitutor());
}
return null;
}
@@ -497,25 +493,6 @@ public class ExceptionUtil {
return getUnhandledExceptions(method, methodCall, topElement, substitutor);
}
- private static PsiSubstitutor getSubstitutor(final JavaResolveResult result, PsiCallExpression methodCall) {
- final PsiLambdaExpression expression = PsiTreeUtil.getParentOfType(methodCall, PsiLambdaExpression.class);
- final PsiSubstitutor substitutor;
- if (expression != null) {
- final PsiElement parent = methodCall.getParent();
- final boolean callInReturnStatement = parent == expression ||
- parent instanceof PsiReturnStatement && PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class, true, PsiMethod.class) == expression;
- substitutor = callInReturnStatement ? ourThrowsGuard.doPreventingRecursion(expression, false, new Computable() {
- @Override
- public PsiSubstitutor compute() {
- return result.getSubstitutor();
- }
- }) : result.getSubstitutor();
- } else {
- substitutor = result.getSubstitutor();
- }
- return substitutor == null ? ((MethodCandidateInfo)result).getSiteSubstitutor() : substitutor;
- }
-
public static void retainExceptions(List ex, List thrownEx) {
final List replacement = new ArrayList();
for (Iterator iterator = ex.iterator(); iterator.hasNext(); ) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java
index 0cf2ee42cbf3..815f47650540 100644
--- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java
+++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java
@@ -29,10 +29,7 @@ import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.compiled.ClsFileImpl;
import com.intellij.psi.impl.file.PsiBinaryFileImpl;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.org.objectweb.asm.ClassReader;
-import org.jetbrains.org.objectweb.asm.ClassVisitor;
-import org.jetbrains.org.objectweb.asm.Label;
-import org.jetbrains.org.objectweb.asm.Opcodes;
+import org.jetbrains.org.objectweb.asm.*;
/**
* @author max
@@ -79,7 +76,7 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider {
final Ref ref = Ref.create(Boolean.FALSE);
try {
- new MyClassReader(file.contentsToByteArray(false)).accept(new ClassVisitor(Opcodes.ASM5) {
+ new ClassReader(file.contentsToByteArray(false)).accept(new ClassVisitor(Opcodes.ASM5) {
@Override
public void visitOuterClass(String owner, String name, String desc) {
ref.set(Boolean.TRUE);
@@ -94,6 +91,11 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider {
throw new ProcessCanceledException();
}
}
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
+ throw new ProcessCanceledException();
+ }
}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
}
catch (ProcessCanceledException ignored) { }
@@ -111,15 +113,4 @@ public class ClassFileViewProvider extends SingleRootFileViewProvider {
public SingleRootFileViewProvider createCopy(@NotNull VirtualFile copy) {
return new ClassFileViewProvider(getManager(), copy, false);
}
-
- private static class MyClassReader extends ClassReader {
- public MyClassReader(byte[] b) {
- super(b);
- }
-
- @Override
- protected Label readLabel(int offset, Label[] labels) {
- return null;
- }
- }
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
index 4b16c7183de8..6d0d853a5098 100644
--- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.PsiConflictResolver;
@@ -535,7 +534,7 @@ public class PsiDiamondTypeImpl extends PsiDiamondType {
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
final PsiClass psiClass = resolveResult.getElement();
if (psiClass != null) {
- if (psiClass instanceof PsiTypeParameter && InferenceSession.isFreshVariable((PsiTypeParameter)psiClass)) {
+ if (psiClass instanceof PsiTypeParameter && TypeConversionUtil.isFreshVariable((PsiTypeParameter)psiClass)) {
return false;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
index 6f92e020a8cf..08fef26ae05d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java
@@ -1082,7 +1082,7 @@ public class PsiClassImplUtil {
PsiTypeParameter p2 = (PsiTypeParameter)another;
return p1.getIndex() == p2.getIndex() &&
- (aClass.getManager().areElementsEquivalent(p1.getOwner(), p2.getOwner()) || InferenceSession.areSameFreshVariables(p1, p2));
+ (aClass.getManager().areElementsEquivalent(p1.getOwner(), p2.getOwner()) || TypeConversionUtil.areSameFreshVariables(p1, p2));
}
else {
return false;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
index 7f963e18cbc0..a563e8107b56 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java
@@ -559,7 +559,8 @@ public class ClsFileImpl extends ClsRepositoryPsiElement
return myIsPhysical;
}
- @SuppressWarnings("UnusedDeclaration") // used by Kotlin compiler
+ /** @deprecated override {@link #isPhysical()} instead (to be removed in IDEA 17) */
+ @SuppressWarnings("UnusedDeclaration")
public void setPhysical(boolean isPhysical) {
myIsPhysical = isPhysical;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
index e1560cff12d7..464d8ed1e393 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -26,6 +26,7 @@ import com.intellij.psi.impl.java.stubs.impl.*;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
import com.intellij.util.cls.ClsFormatException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,7 +39,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
-import static com.intellij.psi.CommonClassNames.*;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
/**
* @author max
@@ -64,6 +66,7 @@ public class StubBuildingVisitor extends ClassVisitor {
private final StubElement myParent;
private final int myAccess;
private final String myShortName;
+ private String myInternalName;
private PsiClassStub myResult;
private PsiModifierListStub myModList;
@@ -82,7 +85,11 @@ public class StubBuildingVisitor extends ClassVisitor {
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- String fqn = getFqn(name, myShortName, myParent instanceof PsiClassStub ? ((PsiClassStub)myParent).getQualifiedName() : null);
+ myInternalName = name;
+ String parentName = myParent instanceof PsiClassStub ? ((PsiClassStub)myParent).getQualifiedName() :
+ myParent instanceof PsiJavaFileStub ? ((PsiJavaFileStub)myParent).getPackageName() :
+ null;
+ String fqn = getFqn(name, myShortName, parentName);
String shortName = myShortName != null && name.endsWith(myShortName) ? myShortName : PsiNameHelper.getShortClassName(fqn);
int flags = myAccess | access;
@@ -133,37 +140,33 @@ public class StubBuildingVisitor extends ClassVisitor {
convertedInterfaces.remove(JAVA_LANG_ANNOTATION_ANNOTATION);
}
newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces));
- newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult);
+ newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.EMPTY_STRING_ARRAY);
}
else {
- if (convertedSuper == null ||
- JAVA_LANG_OBJECT.equals(convertedSuper) ||
- isEnum && (JAVA_LANG_ENUM.equals(convertedSuper) || (JAVA_LANG_ENUM + "<" + fqn + ">").equals(convertedSuper))) {
- newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult);
+ if (convertedSuper == null || "java/lang/Object".equals(superName) || isEnum && "java/lang/Enum".equals(superName)) {
+ newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, ArrayUtil.EMPTY_STRING_ARRAY);
}
else {
- newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, convertedSuper);
+ newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, new String[]{convertedSuper});
}
newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult, ArrayUtil.toStringArray(convertedInterfaces));
}
}
- public static String getFqn(@NotNull String internalName, @Nullable String shortName, @Nullable String parentName) {
+ private static String getFqn(@NotNull String internalName, @Nullable String shortName, @Nullable String parentName) {
if (shortName == null || !internalName.endsWith(shortName)) {
return getClassName(internalName);
}
- else if (internalName.length() == shortName.length()) {
+ if (internalName.length() == shortName.length()) {
return shortName;
}
- else {
- if (parentName == null) {
- parentName = getClassName(internalName.substring(0, internalName.length() - shortName.length() - 1));
- }
- return parentName + "." + shortName;
+ if (parentName == null) {
+ parentName = getClassName(internalName.substring(0, internalName.length() - shortName.length() - 1));
}
+ return parentName + '.' + shortName;
}
- public static void newReferenceList(JavaClassReferenceListElementType type, StubElement parent, String... types) {
+ public static void newReferenceList(JavaClassReferenceListElementType type, StubElement parent, String[] types) {
PsiReferenceList.Role role;
if (type == JavaStubElementTypes.EXTENDS_LIST) role = PsiReferenceList.Role.EXTENDS_LIST;
@@ -176,8 +179,8 @@ public class StubBuildingVisitor extends ClassVisitor {
}
@Nullable
- private static String parseClassDescription(final String superName, final String[] interfaces, final List convertedInterfaces) {
- final String convertedSuper = superName != null ? getClassName(superName) : null;
+ private static String parseClassDescription(String superName, String[] interfaces, List convertedInterfaces) {
+ String convertedSuper = superName != null ? getClassName(superName) : null;
for (String anInterface : interfaces) {
convertedInterfaces.add(getClassName(anInterface));
}
@@ -185,161 +188,101 @@ public class StubBuildingVisitor extends ClassVisitor {
}
@Nullable
- private static String parseClassSignature(final CharacterIterator signatureIterator, final List convertedInterfaces)
- throws ClsFormatException {
- final String convertedSuper = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator);
+ private static String parseClassSignature(CharacterIterator signatureIterator, List convertedInterfaces) throws ClsFormatException {
+ String convertedSuper = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator);
while (signatureIterator.current() != CharacterIterator.DONE) {
- final String ifs = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator);
+ String ifs = SignatureParsing.parseTopLevelClassRefSignature(signatureIterator);
if (ifs == null) throw new ClsFormatException();
-
convertedInterfaces.add(ifs);
}
return convertedSuper;
}
- private static int packCommonFlags(final int access) {
+ private static int packCommonFlags(int access) {
int flags = 0;
- if ((access & Opcodes.ACC_PRIVATE) != 0) {
- flags |= ModifierFlags.PRIVATE_MASK;
- }
- else if ((access & Opcodes.ACC_PROTECTED) != 0) {
- flags |= ModifierFlags.PROTECTED_MASK;
- }
- else if ((access & Opcodes.ACC_PUBLIC) != 0) {
- flags |= ModifierFlags.PUBLIC_MASK;
- }
- else {
- flags |= ModifierFlags.PACKAGE_LOCAL_MASK;
- }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) flags |= ModifierFlags.PRIVATE_MASK;
+ else if ((access & Opcodes.ACC_PROTECTED) != 0) flags |= ModifierFlags.PROTECTED_MASK;
+ else if ((access & Opcodes.ACC_PUBLIC) != 0) flags |= ModifierFlags.PUBLIC_MASK;
+ else flags |= ModifierFlags.PACKAGE_LOCAL_MASK;
- if ((access & Opcodes.ACC_STATIC) != 0) {
- flags |= ModifierFlags.STATIC_MASK;
- }
- if ((access & Opcodes.ACC_FINAL) != 0) {
- flags |= ModifierFlags.FINAL_MASK;
- }
+ if ((access & Opcodes.ACC_STATIC) != 0) flags |= ModifierFlags.STATIC_MASK;
+ if ((access & Opcodes.ACC_FINAL) != 0) flags |= ModifierFlags.FINAL_MASK;
return flags;
}
- private static int packClassFlags(final int access) {
+ private static int packClassFlags(int access) {
int flags = packCommonFlags(access);
-
- if ((access & Opcodes.ACC_ABSTRACT) != 0) {
- flags |= ModifierFlags.ABSTRACT_MASK;
- }
-
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) flags |= ModifierFlags.ABSTRACT_MASK;
return flags;
}
- private static int packFieldFlags(final int access) {
+ private static int packFieldFlags(int access) {
int flags = packCommonFlags(access);
-
- if ((access & Opcodes.ACC_VOLATILE) != 0) {
- flags |= ModifierFlags.VOLATILE_MASK;
- }
- if ((access & Opcodes.ACC_TRANSIENT) != 0) {
- flags |= ModifierFlags.TRANSIENT_MASK;
- }
-
+ if ((access & Opcodes.ACC_VOLATILE) != 0) flags |= ModifierFlags.VOLATILE_MASK;
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) flags |= ModifierFlags.TRANSIENT_MASK;
return flags;
}
- private static int packMethodFlags(final int access, boolean isInterface) {
+ private static int packMethodFlags(int access, boolean isInterface) {
int flags = packCommonFlags(access);
- if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
- flags |= ModifierFlags.SYNCHRONIZED_MASK;
- }
- if ((access & Opcodes.ACC_NATIVE) != 0) {
- flags |= ModifierFlags.NATIVE_MASK;
- }
- if ((access & Opcodes.ACC_ABSTRACT) != 0) {
- flags |= ModifierFlags.ABSTRACT_MASK;
- }
- else if (isInterface && (access & Opcodes.ACC_STATIC) == 0) {
- flags |= ModifierFlags.DEFENDER_MASK;
- }
- if ((access & Opcodes.ACC_STRICT) != 0) {
- flags |= ModifierFlags.STRICTFP_MASK;
- }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) flags |= ModifierFlags.SYNCHRONIZED_MASK;
+ if ((access & Opcodes.ACC_NATIVE) != 0) flags |= ModifierFlags.NATIVE_MASK;
+ if ((access & Opcodes.ACC_STRICT) != 0) flags |= ModifierFlags.STRICTFP_MASK;
+
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) flags |= ModifierFlags.ABSTRACT_MASK;
+ else if (isInterface && (access & Opcodes.ACC_STATIC) == 0) flags |= ModifierFlags.DEFENDER_MASK;
return flags;
}
@Override
- public void visitSource(final String source, final String debug) {
+ public void visitSource(String source, String debug) {
((PsiClassStubImpl)myResult).setSourceFileName(source);
}
@Override
- public void visitOuterClass(final String owner, final String name, final String desc) {
+ public void visitOuterClass(String owner, String name, String desc) {
if (myParent instanceof PsiFileStub) {
throw new OutOfOrderInnerClassException();
}
}
@Override
- public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
- return new AnnotationTextCollector(desc, new AnnotationResultCallback() {
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return new AnnotationTextCollector(desc, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
new PsiAnnotationStubImpl(myModList, text);
}
});
}
@Override
- public void visitInnerClass(final String name, final String outerName, final String innerName, final int access) {
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0) return;
- if (!isCorrectName(innerName) || outerName == null) return;
+ if (innerName == null || outerName == null) return;
- if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) {
+ if ((getClassName(outerName) + '.' + innerName).equals(myResult.getQualifiedName()) && myParent instanceof PsiFileStub) {
// our result is inner class
- if (myParent instanceof PsiFileStub) {
- throw new OutOfOrderInnerClassException();
+ throw new OutOfOrderInnerClassException();
+ }
+
+ if (myInternalName.equals(outerName)) {
+ T innerClass = myInnersStrategy.findInnerClass(innerName, mySource);
+ if (innerClass != null) {
+ myInnersStrategy.accept(innerClass, new StubBuildingVisitor(innerClass, myInnersStrategy, myResult, access, innerName));
}
}
- if (!namesEqual(outerName, myResult.getQualifiedName())) {
- return;
- }
-
- T innerClass = myInnersStrategy.findInnerClass(innerName, mySource);
- if (innerClass != null) {
- StubBuildingVisitor visitor = new StubBuildingVisitor(innerClass, myInnersStrategy, myResult, access, innerName);
- myInnersStrategy.accept(innerClass, visitor);
- }
- }
-
- private static boolean isCorrectName(String name) {
- return name != null;
- }
-
- private static boolean namesEqual(String signature, String fqn) {
- if (fqn == null) return true; // impossible case, just ignore
- if (fqn.length() != signature.length()) return false;
-
- int p = 0;
- int dot;
- while ((dot = fqn.indexOf('.', p)) >= 0) {
- if (!signature.regionMatches(p, fqn, p, dot - p)) {
- return false;
- }
- char ch = signature.charAt(dot);
- if (ch != '/' && ch != '$') {
- return false;
- }
- p = dot + 1;
- }
- return fqn.regionMatches(p, signature, p, fqn.length() - p);
}
@Override
@Nullable
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if ((access & Opcodes.ACC_SYNTHETIC) != 0) return null;
- if (!isCorrectName(name)) return null;
+ if (name == null) return null;
byte flags = PsiFieldStubImpl.packFlags((access & Opcodes.ACC_ENUM) != 0, (access & Opcodes.ACC_DEPRECATED) != 0, false, false);
TypeInfo type = fieldType(desc, signature);
@@ -367,22 +310,18 @@ public class StubBuildingVisitor extends ClassVisitor {
@NotNull
private static TypeInfo fieldTypeViaDescription(@NotNull String desc) {
Type type = Type.getType(desc);
- final int dim = type.getSort() == Type.ARRAY ? type.getDimensions() : 0;
+ int dim = type.getSort() == Type.ARRAY ? type.getDimensions() : 0;
if (dim > 0) {
type = type.getElementType();
}
- return new TypeInfo(getTypeText(type), (byte)dim, false, PsiAnnotationStub.EMPTY_ARRAY); //todo read annos from .class file
+ return new TypeInfo(getTypeText(type), (byte)dim, false, PsiAnnotationStub.EMPTY_ARRAY);
}
private static final String[] parameterNames = {"p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9"};
@Override
@Nullable
- public MethodVisitor visitMethod(final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions) {
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
// JLS 13.1 says: Any constructs introduced by the compiler that do not have a corresponding construct in the source code
// must be marked as synthetic, except for default constructors and the class initialization method.
// However Scala compiler erroneously generates ACC_BRIDGE instead of ACC_SYNTHETIC flag for in-trait implementation delegation.
@@ -403,9 +342,9 @@ public class StubBuildingVisitor extends ClassVisitor {
boolean isVarargs = (access & Opcodes.ACC_VARARGS) != 0;
boolean isAnnotationMethod = myResult.isAnnotationType();
- if (!isConstructor && !isCorrectName(name)) return null;
+ if (!isConstructor && name == null) return null;
- final byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false, false);
+ byte flags = PsiMethodStubImpl.packFlags(isConstructor, isAnnotationMethod, isVarargs, isDeprecated, false, false);
String canonicalMethodName = isConstructor ? myResult.getName() : name;
List args = new ArrayList();
@@ -422,20 +361,20 @@ public class StubBuildingVisitor extends ClassVisitor {
args = args.subList(2, args.size());
}
- final boolean isNonStaticInnerClassConstructor =
+ boolean isNonStaticInnerClassConstructor =
isConstructor && !(myParent instanceof PsiFileStub) && (myModList.getModifiersMask() & Opcodes.ACC_STATIC) == 0;
boolean parsedViaGenericSignature = stub.isParsedViaGenericSignature();
- final boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor;
+ boolean shouldSkipFirstParamForNonStaticInnerClassConstructor = !parsedViaGenericSignature && isNonStaticInnerClassConstructor;
- final PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub);
- final int paramCount = args.size();
- final PsiParameterStubImpl[] paramStubs = new PsiParameterStubImpl[paramCount];
+ PsiParameterListStubImpl parameterList = new PsiParameterListStubImpl(stub);
+ int paramCount = args.size();
+ PsiParameterStubImpl[] paramStubs = new PsiParameterStubImpl[paramCount];
for (int i = 0; i < paramCount; i++) {
if (shouldSkipFirstParamForNonStaticInnerClassConstructor && i == 0) continue;
String arg = args.get(i);
boolean isEllipsisParam = isVarargs && i == paramCount - 1;
- final TypeInfo typeInfo = TypeInfo.fromString(arg, isEllipsisParam);
+ TypeInfo typeInfo = TypeInfo.fromString(arg, isEllipsisParam);
String paramName = i < parameterNames.length ? parameterNames[i] : "p" + (i + 1);
PsiParameterStubImpl parameterStub = new PsiParameterStubImpl(parameterList, paramName, typeInfo, isEllipsisParam);
@@ -475,8 +414,8 @@ public class StubBuildingVisitor extends ClassVisitor {
@NotNull
public static String parseMethodViaDescription(@NotNull String desc, @NotNull PsiMethodStubImpl stub, @NotNull List args) {
- final String returnType = getTypeText(Type.getReturnType(desc));
- final Type[] argTypes = Type.getArgumentTypes(desc);
+ String returnType = getTypeText(Type.getReturnType(desc));
+ Type[] argTypes = Type.getArgumentTypes(desc);
for (Type argType : argTypes) {
args.add(getTypeText(argType));
}
@@ -522,11 +461,11 @@ public class StubBuildingVisitor extends ClassVisitor {
private static class AnnotationTextCollector extends AnnotationVisitor {
private final StringBuilder myBuilder = new StringBuilder();
- private final AnnotationResultCallback myCallback;
+ private final Consumer myCallback;
private boolean hasParams = false;
private final String myDesc;
- public AnnotationTextCollector(@Nullable String desc, AnnotationResultCallback callback) {
+ public AnnotationTextCollector(@Nullable String desc, Consumer callback) {
super(ASM_API);
myCallback = callback;
@@ -537,18 +476,18 @@ public class StubBuildingVisitor extends ClassVisitor {
}
@Override
- public void visit(final String name, final Object value) {
+ public void visit(String name, Object value) {
valuePairPrefix(name);
myBuilder.append(constToString(value, null, true));
}
@Override
- public void visitEnum(final String name, final String desc, final String value) {
+ public void visitEnum(String name, String desc, String value) {
valuePairPrefix(name);
- myBuilder.append(getTypeText(Type.getType(desc))).append(".").append(value);
+ myBuilder.append(getTypeText(Type.getType(desc))).append('.').append(value);
}
- private void valuePairPrefix(final String name) {
+ private void valuePairPrefix(String name) {
if (!hasParams) {
hasParams = true;
if (myDesc != null) {
@@ -565,23 +504,23 @@ public class StubBuildingVisitor extends ClassVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(final String name, final String desc) {
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
valuePairPrefix(name);
- return new AnnotationTextCollector(desc, new AnnotationResultCallback() {
+ return new AnnotationTextCollector(desc, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
myBuilder.append(text);
}
});
}
@Override
- public AnnotationVisitor visitArray(final String name) {
+ public AnnotationVisitor visitArray(String name) {
valuePairPrefix(name);
- myBuilder.append("{");
- return new AnnotationTextCollector(null, new AnnotationResultCallback() {
+ myBuilder.append('{');
+ return new AnnotationTextCollector(null, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
myBuilder.append(text).append('}');
}
});
@@ -592,23 +531,23 @@ public class StubBuildingVisitor extends ClassVisitor {
if (hasParams && myDesc != null) {
myBuilder.append(')');
}
- myCallback.callback(myBuilder.toString());
+ myCallback.consume(myBuilder.toString());
}
}
private static class AnnotationCollectingVisitor extends FieldVisitor {
private final PsiModifierListStub myModList;
- private AnnotationCollectingVisitor(final PsiModifierListStub modList) {
+ private AnnotationCollectingVisitor(PsiModifierListStub modList) {
super(ASM_API);
myModList = modList;
}
@Override
- public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
- return new AnnotationTextCollector(desc, new AnnotationResultCallback() {
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return new AnnotationTextCollector(desc, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
new PsiAnnotationStubImpl(myModList, text);
}
});
@@ -627,9 +566,9 @@ public class StubBuildingVisitor extends ClassVisitor {
private AnnotationParamCollectingVisitor(@NotNull PsiMethodStub owner,
@NotNull PsiModifierListStub modList,
- final int ignoreCount,
- final int paramIgnoreCount,
- final int paramCount,
+ int ignoreCount,
+ int paramIgnoreCount,
+ int paramCount,
@NotNull PsiParameterStubImpl[] paramStubs) {
super(ASM_API);
myOwner = owner;
@@ -641,10 +580,10 @@ public class StubBuildingVisitor extends ClassVisitor {
}
@Override
- public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
- return new AnnotationTextCollector(desc, new AnnotationResultCallback() {
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return new AnnotationTextCollector(desc, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
new PsiAnnotationStubImpl(myModList, text);
}
});
@@ -652,9 +591,9 @@ public class StubBuildingVisitor extends ClassVisitor {
@Override
public AnnotationVisitor visitAnnotationDefault() {
- return new AnnotationTextCollector(null, new AnnotationResultCallback() {
+ return new AnnotationTextCollector(null, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
((PsiMethodStubImpl)myOwner).setDefaultValueText(text);
}
});
@@ -690,9 +629,9 @@ public class StubBuildingVisitor extends ClassVisitor {
if (parameter < myParamIgnoreCount) {
return null;
}
- return new AnnotationTextCollector(desc, new AnnotationResultCallback() {
+ return new AnnotationTextCollector(desc, new Consumer() {
@Override
- public void callback(final String text) {
+ public void consume(String text) {
new PsiAnnotationStubImpl(myOwner.findParameter(parameter - myParamIgnoreCount).getModList(), text);
}
});
@@ -716,7 +655,7 @@ public class StubBuildingVisitor extends ClassVisitor {
}
if (value instanceof Long) {
- return value.toString() + "L";
+ return value.toString() + 'L';
}
if (value instanceof Integer) {
@@ -732,7 +671,7 @@ public class StubBuildingVisitor extends ClassVisitor {
}
if (value instanceof Double) {
- final double d = (Double)value;
+ double d = (Double)value;
if (Double.isInfinite(d)) {
return d > 0 ? DOUBLE_POSITIVE_INF : DOUBLE_NEGATIVE_INF;
}
@@ -743,7 +682,7 @@ public class StubBuildingVisitor extends ClassVisitor {
}
if (value instanceof Float) {
- final float v = (Float)value;
+ float v = (Float)value;
if (Float.isInfinite(v)) {
return v > 0 ? FLOAT_POSITIVE_INF : FLOAT_NEGATIVE_INF;
@@ -752,7 +691,7 @@ public class StubBuildingVisitor extends ClassVisitor {
return FLOAT_NAN;
}
else {
- return Float.toString(v) + "f";
+ return Float.toString(v) + 'f';
}
}
@@ -774,17 +713,13 @@ public class StubBuildingVisitor extends ClassVisitor {
return null;
}
- private interface AnnotationResultCallback {
- void callback(String text);
- }
-
- private static String getClassName(final String name) {
+ private static String getClassName(String name) {
return getTypeText(Type.getObjectType(name));
}
@NotNull
private static String getTypeText(@NotNull Type type) {
- final String raw = type.getClassName();
+ String raw = type.getClassName();
// As the '$' char is a valid java identifier and is actively used by byte code generators, the problem is
// which occurrences of this char should be replaced and which should not.
// Heuristic: replace only those $ occurrences that are surrounded non-"$" chars
@@ -792,4 +727,4 @@ public class StubBuildingVisitor extends ClassVisitor {
// Leading and trailing $ chars should be left unchanged.
return raw.indexOf('$') >= 0 ? REGEX_PATTERN.matcher(raw).replaceAll("\\.") : raw;
}
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassInitializerStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassInitializerStubImpl.java
index 2fc4983786e0..457ca0515374 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassInitializerStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassInitializerStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiClassInitializer;
@@ -25,6 +21,9 @@ import com.intellij.psi.impl.java.stubs.PsiClassInitializerStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+/**
+ * @author max
+ */
public class PsiClassInitializerStubImpl extends StubBase implements PsiClassInitializerStub {
public PsiClassInitializerStubImpl(final StubElement parent) {
super(parent, JavaStubElementTypes.CLASS_INITIALIZER);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassReferenceListStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassReferenceListStubImpl.java
index 73d0f5304a45..24e7c656442f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassReferenceListStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiClassReferenceListStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.*;
@@ -33,6 +29,9 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.io.StringRef;
+/**
+ * @author max
+ */
public class PsiClassReferenceListStubImpl extends StubBase implements PsiClassReferenceListStub {
private final PsiReferenceList.Role myRole;
private final StringRef[] myNames;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportListStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportListStubImpl.java
index 6f275a481298..e1382e546728 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportListStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportListStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiImportList;
@@ -25,6 +21,9 @@ import com.intellij.psi.impl.java.stubs.PsiImportListStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+/**
+ * @author max
+ */
public class PsiImportListStubImpl extends StubBase implements PsiImportListStub {
public PsiImportListStubImpl(final StubElement parent) {
super(parent, JavaStubElementTypes.IMPORT_LIST);
@@ -32,8 +31,6 @@ public class PsiImportListStubImpl extends StubBase implements Ps
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("PsiImportListStub");
- return builder.toString();
+ return "PsiImportListStub";
}
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
index 65c60197491c..699946cb81ce 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.JavaPsiFacade;
@@ -33,6 +29,9 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.Nullable;
+/**
+ * @author max
+ */
public class PsiImportStatementStubImpl extends StubBase implements PsiImportStatementStub {
private final byte myFlags;
private final StringRef myText;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
index b8c7f14930df..2b9f44090593 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiMethodStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiMethod;
@@ -35,6 +31,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
+/**
+ * @author max
+ */
public class PsiMethodStubImpl extends StubBase implements PsiMethodStub {
private final TypeInfo myReturnType;
private final byte myFlags;
@@ -212,4 +211,4 @@ public class PsiMethodStubImpl extends StubBase implements PsiMethodS
builder.append("]");
return builder.toString();
}
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiModifierListStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiModifierListStubImpl.java
index 0980c9a3e1f4..e238b4a2c661 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiModifierListStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiModifierListStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiModifierList;
@@ -25,6 +21,9 @@ import com.intellij.psi.impl.java.stubs.PsiModifierListStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+/**
+ * @author max
+ */
public class PsiModifierListStubImpl extends StubBase implements PsiModifierListStub {
private final int myMask;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterListStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterListStubImpl.java
index e6f29b2db092..cfc3aa550a2a 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterListStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiParameterListStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiParameterList;
@@ -25,6 +21,9 @@ import com.intellij.psi.impl.java.stubs.PsiParameterListStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+/**
+ * @author max
+ */
public class PsiParameterListStubImpl extends StubBase implements PsiParameterListStub {
public PsiParameterListStubImpl(final StubElement parent) {
super(parent, JavaStubElementTypes.PARAMETER_LIST);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterListStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterListStubImpl.java
index a71fb7475563..9fbffcc6fc05 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterListStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterListStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiTypeParameterList;
@@ -25,6 +21,9 @@ import com.intellij.psi.impl.java.stubs.PsiTypeParameterListStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
+/**
+ * @author max
+ */
public class PsiTypeParameterListStubImpl extends StubBase implements PsiTypeParameterListStub{
public PsiTypeParameterListStubImpl(final StubElement parent) {
super(parent, JavaStubElementTypes.TYPE_PARAMETER_LIST);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterStubImpl.java
index 4f2a83519025..a315c3ad4ac6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiTypeParameterStubImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2016 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,10 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiTypeParameter;
@@ -32,6 +28,9 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
+/**
+ * @author max
+ */
public class PsiTypeParameterStubImpl extends StubBase implements PsiTypeParameterStub {
private final StringRef myName;
@@ -47,9 +46,7 @@ public class PsiTypeParameterStubImpl extends StubBase impleme
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("PsiTypeParameter[").append(myName).append(']');
- return builder.toString();
+ return "PsiTypeParameter[" + myName + ']';
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
index e5b9763c41d7..e1531c92dc90 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/FunctionalInterfaceParameterizationUtil.java
@@ -18,7 +18,6 @@ package com.intellij.psi.impl.source.resolve.graphInference;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
-import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
index b120d5dfac12..7e213cd0bbf2 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceIncorporationPhase.java
@@ -24,6 +24,7 @@ import com.intellij.psi.impl.source.resolve.graphInference.constraints.StrictSub
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Processor;
import java.util.*;
@@ -182,7 +183,7 @@ public class InferenceIncorporationPhase {
private static Boolean isInferenceVariableOrFreshTypeParameter(PsiType eqBound) {
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(eqBound);
if (psiClass instanceof InferenceVariable ||
- psiClass instanceof PsiTypeParameter && InferenceSession.isFreshVariable((PsiTypeParameter)psiClass)) return true;
+ psiClass instanceof PsiTypeParameter && TypeConversionUtil.isFreshVariable((PsiTypeParameter)psiClass)) return true;
return false;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
index b64ba29df4fc..4c9ca46acde3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java
@@ -42,7 +42,6 @@ public class InferenceSession {
private static final Logger LOG = Logger.getInstance("#" + InferenceSession.class.getName());
public static final Key LOWER_BOUND = Key.create("LowBound");
public static final Key UPPER_BOUND = Key.create("UpperBound");
- private static final Key ORIGINAL_CONTEXT = Key.create("ORIGINAL_CONTEXT");
private static final Key ERASED = Key.create("UNCHECKED_CONVERSION");
private static final Function, PsiType> UPPER_BOUND_FUNCTION = new Function, PsiType>() {
@Override
@@ -1038,7 +1037,7 @@ public class InferenceSession {
}
parameter.putUserData(UPPER_BOUND,
composeBound(var, InferenceBound.UPPER, UPPER_BOUND_FUNCTION, ySubstitutor.putAll(substitutor), true));
- parameter.putUserData(ORIGINAL_CONTEXT, myContext);
+ TypeConversionUtil.markAsFreshVariable(parameter, myContext);
if (!var.addBound(elementFactory.createType(parameter), InferenceBound.EQ)) {
return false;
}
@@ -1507,7 +1506,7 @@ public class InferenceSession {
LOG.assertTrue(parameters1.length == parameters2.length);
}
- final int paramsLength = !varargs ? parameters1.length : parameters1.length - 1;
+ final int paramsLength = !varargs ? parameters1.length : Math.max(parameters1.length, parameters2.length) - 1;
for (int i = 0; i < paramsLength; i++) {
PsiType sType = getParameterType(parameters1, i, siteSubstitutor1, false);
PsiType tType = session.substituteWithInferenceVariables(getParameterType(parameters2, i, siteSubstitutor1, varargs));
@@ -1768,15 +1767,6 @@ public class InferenceSession {
return s.substitute(type);
}
- public static boolean areSameFreshVariables(PsiTypeParameter p1, PsiTypeParameter p2) {
- final PsiElement originalContext = p1.getUserData(ORIGINAL_CONTEXT);
- return originalContext != null && originalContext == p2.getUserData(ORIGINAL_CONTEXT);
- }
-
- public static boolean isFreshVariable(PsiTypeParameter typeParameter) {
- return typeParameter.getUserData(ORIGINAL_CONTEXT) != null;
- }
-
public static PsiClass findParameterizationOfTheSameGenericClass(List upperBounds,
Processor> processor) {
for (int i = 0; i < upperBounds.size(); i++) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSessionContainer.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSessionContainer.java
index 39484a509d58..4ca48d1c0f6e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSessionContainer.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSessionContainer.java
@@ -198,18 +198,32 @@ public class InferenceSessionContainer {
if (parent instanceof PsiCall) {
break;
}
- if (parent instanceof PsiCodeBlock && PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class) == null) {
- break;
- }
- if (parent instanceof PsiLambdaExpression) {
- boolean inReturnExpressions = false;
- for (PsiExpression expression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)parent)) {
- inReturnExpressions |= PsiTreeUtil.isAncestor(expression, context, false);
- }
- if (!inReturnExpressions) {
+
+ final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class);
+ if (parent instanceof PsiCodeBlock) {
+ if (lambdaExpression == null) {
break;
}
+ else {
+ boolean inReturnExpressions = false;
+ for (PsiExpression expression : LambdaUtil.getReturnExpressions(lambdaExpression)) {
+ inReturnExpressions |= PsiTreeUtil.isAncestor(expression, context, false);
+ }
+
+ if (!inReturnExpressions) {
+ break;
+ }
+
+ if (LambdaUtil.getFunctionalTypeMap().containsKey(lambdaExpression)) {
+ break;
+ }
+ }
}
+
+ if (parent instanceof PsiLambdaExpression && LambdaUtil.getFunctionalTypeMap().containsKey(parent)) {
+ break;
+ }
+
final PsiCall psiCall = PsiTreeUtil.getParentOfType(parent, PsiCall.class);
if (psiCall == null) {
break;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
index 9c8ce5882286..523c7daf86b1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java
@@ -17,7 +17,6 @@ package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
@@ -118,12 +117,7 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
final List thrownTypes = new ArrayList();
final PsiElement body = myExpression instanceof PsiLambdaExpression ? ((PsiLambdaExpression)myExpression).getBody() : myExpression;
if (body != null) {
- final List exceptions = ExceptionUtil.ourThrowsGuard.doPreventingRecursion(myExpression, false, new Computable>() {
- @Override
- public List compute() {
- return ExceptionUtil.getUnhandledExceptions(new PsiElement[] {body});
- }
- });
+ final List exceptions = ExceptionUtil.getUnhandledExceptions(new PsiElement[] {body});
if (exceptions != null) {
thrownTypes.addAll(ContainerUtil.filter(exceptions, new Condition() {
@Override
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CodeBlockLambdaWithIsValueCompatibleChecks.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CodeBlockLambdaWithIsValueCompatibleChecks.java
new file mode 100644
index 000000000000..f5fb284da5e2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CodeBlockLambdaWithIsValueCompatibleChecks.java
@@ -0,0 +1,23 @@
+import java.util.Optional;
+
+class Test {
+ public static void main(String[] args) {
+ Optional> eith =
+ Optional.of(new Either());
+
+ eith.map(either -> {
+ String foo = Test.foo(either);
+ return foo;
+ }).orElse("Hello");
+
+ eith.map(either -> {
+ return Test.foo(either);
+ }).orElse("Hello");
+
+ eith.map(either -> Test.foo(either)).orElse("Hello");
+ }
+
+ private static A foo(Either either) throws X { return null; }
+}
+
+class Either { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/LongerParamsWhenVarargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/LongerParamsWhenVarargs.java
new file mode 100644
index 000000000000..57b52d91d23a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/overloadResolution/LongerParamsWhenVarargs.java
@@ -0,0 +1,21 @@
+interface Node<T> {
+
+ @SafeVarargs
+ static Node of(T value, Node... children) {
+ System.out.println(value);
+ System.out.println(children);
+ return null;
+ }
+
+
+ @SafeVarargs
+ static Node of(T1... values) {
+ System.out.println(values);
+ return null;
+ }
+
+ static void test() {
+ Node.of(1, Node.of(2), Node.of(3));
+ Node.of(1, Node.of(2), Node. of(3));
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterBlockLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterBlockLambda.java
new file mode 100644
index 000000000000..c5fc4f967c50
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterBlockLambda.java
@@ -0,0 +1,9 @@
+// "Replace method call on lambda with lambda body" "true"
+import java.util.function.Supplier;
+
+class Test {
+ {
+ String s = "";
+ String str = s;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterExprLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterExprLambda.java
new file mode 100644
index 000000000000..b63be02a9295
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterExprLambda.java
@@ -0,0 +1,6 @@
+// "Replace method call on lambda with lambda body" "true"
+import java.util.function.Supplier;
+
+class Test {
+ String s = "";
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterMethodRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterMethodRef.java
new file mode 100644
index 000000000000..bd2262d5df9b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/afterMethodRef.java
@@ -0,0 +1,10 @@
+// "Replace method call on method reference with corresponding method call" "true"
+import java.util.function.Supplier;
+
+class Test {
+ String s = foo();
+
+ private String foo() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambda.java
new file mode 100644
index 000000000000..e920715c0f91
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambda.java
@@ -0,0 +1,11 @@
+// "Replace method call on lambda with lambda body" "true"
+import java.util.function.Supplier;
+
+class Test {
+ {
+ String str = ((Supplier)() -> {
+ String s = "";
+ return s;
+ }).get();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambdaInFieldDeclaration.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambdaInFieldDeclaration.java
new file mode 100644
index 000000000000..714721e2826e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeBlockLambdaInFieldDeclaration.java
@@ -0,0 +1,9 @@
+// "Replace method call on lambda with lambda body" "false"
+import java.util.function.Supplier;
+
+class Test {
+ String str = ((Supplier) () -> {
+ String s = "";
+ return s;
+ }).get();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeExprLambda.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeExprLambda.java
new file mode 100644
index 000000000000..8303b227f987
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeExprLambda.java
@@ -0,0 +1,8 @@
+// "Replace method call on lambda with lambda body" "true"
+import java.util.function.Supplier;
+
+class Test {
+ String s = ((Supplier) () -> {
+ return "";
+ }).get();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeMethodRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeMethodRef.java
new file mode 100644
index 000000000000..6368b6b8e1ca
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeMethodRef.java
@@ -0,0 +1,10 @@
+// "Replace method call on method reference with corresponding method call" "true"
+import java.util.function.Supplier;
+
+class Test {
+ String s = ((Supplier) this::foo).get();
+
+ private String foo() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeUnresolvedMethodRef.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeUnresolvedMethodRef.java
new file mode 100644
index 000000000000..47fd75c03525
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage/beforeUnresolvedMethodRef.java
@@ -0,0 +1,6 @@
+// "Replace method call on method reference with corresponding method call" "false"
+import java.util.function.Supplier;
+
+class Test {
+ String s = ((Supplier) this::foo).get();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicate.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicate.java
new file mode 100644
index 000000000000..2e8598624932
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicate.java
@@ -0,0 +1,8 @@
+// "Replace with qualifier" "true"
+import java.util.function.Predicate;
+
+class Test {
+ void foo(Predicate p){
+ Predicate stringPredicate = p;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicateInheritor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicateInheritor.java
new file mode 100644
index 000000000000..311417295d5d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/afterPredicateInheritor.java
@@ -0,0 +1,12 @@
+// "Replace with qualifier" "true"
+import java.util.function.Predicate;
+
+class Test implements Predicate {
+ void foo(){
+ Predicate stringPredicate = this;
+ }
+
+ public boolean test(String s) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicate.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicate.java
new file mode 100644
index 000000000000..67d9a0ac4203
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicate.java
@@ -0,0 +1,8 @@
+// "Replace with qualifier" "true"
+import java.util.function.Predicate;
+
+class Test {
+ void foo(Predicate p){
+ Predicate stringPredicate = p::test;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicateInheritor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicateInheritor.java
new file mode 100644
index 000000000000..2270c5685ba9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference/beforePredicateInheritor.java
@@ -0,0 +1,12 @@
+// "Replace with qualifier" "true"
+import java.util.function.Predicate;
+
+class Test implements Predicate {
+ void foo(){
+ Predicate stringPredicate = this::test;
+ }
+
+ public boolean test(String s) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java
new file mode 100644
index 000000000000..c522b20a52f2
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java
@@ -0,0 +1,15 @@
+import java.util.function.Supplier;
+
+public class Test {
+
+ public Test() {
+ this(0);
+ }
+
+ public Test(int i) {}
+
+
+ {
+ Supplier sup = Test::new;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java.after b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java.after
new file mode 100644
index 000000000000..34fbae24db7b
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoConstructorRef.java.after
@@ -0,0 +1,15 @@
+import java.util.function.Supplier;
+
+public class Test {
+
+ public Test() {
+ this(0);
+ }
+
+ public Test(int i) {}
+
+
+ {
+ Supplier sup = () -> new Test(0);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java
new file mode 100644
index 000000000000..762b0f595b7b
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java
@@ -0,0 +1,11 @@
+import java.util.function.Supplier;
+
+class Test {
+ {
+ Supplier sup = this::get;
+ }
+
+ private String get() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java.after b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java.after
new file mode 100644
index 000000000000..2a7e11c5fe08
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineMethod/InlineIntoMethodRef.java.after
@@ -0,0 +1,11 @@
+import java.util.function.Supplier;
+
+class Test {
+ {
+ Supplier sup = () -> null;
+ }
+
+ private String get() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineMethod/SideEffectsInMethodRefQualifier.java b/java/java-tests/testData/refactoring/inlineMethod/SideEffectsInMethodRefQualifier.java
new file mode 100644
index 000000000000..a138b39b60a1
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineMethod/SideEffectsInMethodRefQualifier.java
@@ -0,0 +1,13 @@
+
+import java.util.function.Supplier;
+
+public class Test {
+
+ {
+ Supplier sup = new Test()::get;
+ }
+
+ private String get() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy.java b/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy.java
new file mode 100644
index 000000000000..3f578b3425a2
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy.java
@@ -0,0 +1,3 @@
+class A {
+ public <T> void foo() {}
+}
diff --git a/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy_after.java b/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy_after.java
new file mode 100644
index 000000000000..0604b2502c29
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/TypeParameterNoMethodHierarchy_after.java
@@ -0,0 +1,3 @@
+class A {
+ public void foo() {}
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
index ff73bcfdb83f..d6188766f1b8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
@@ -264,6 +264,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testCodeBlockLambdaWithIsValueCompatibleChecks() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java
index 5e7519b18e3e..41d03b6e7d23 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/OverloadResolutionTest.java
@@ -195,6 +195,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testLongerParamsWhenVarargs() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(true);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialFunctionalExpressionUsageInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialFunctionalExpressionUsageInspectionTest.java
new file mode 100644
index 000000000000..5de09e455807
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialFunctionalExpressionUsageInspectionTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2016 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.quickFix;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.TrivialFunctionalExpressionUsageInspection;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.testFramework.IdeaTestUtil;
+import org.jetbrains.annotations.NotNull;
+
+
+public class TrivialFunctionalExpressionUsageInspectionTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[]{
+ new TrivialFunctionalExpressionUsageInspection(),
+ };
+ }
+
+ public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/trivialFunctionalExpressionUsage";
+ }
+
+ @Override
+ protected Sdk getProjectJDK() {
+ return IdeaTestUtil.getMockJdk18();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialMethodReferenceInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialMethodReferenceInspectionTest.java
new file mode 100644
index 000000000000..00263f77aab1
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/TrivialMethodReferenceInspectionTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2016 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.quickFix;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.TrivialMethodReferenceInspection;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.testFramework.IdeaTestUtil;
+import org.jetbrains.annotations.NotNull;
+
+
+public class TrivialMethodReferenceInspectionTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[]{
+ new TrivialMethodReferenceInspection(),
+ };
+ }
+
+ public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/trivialMethodReference";
+ }
+
+ @Override
+ protected Sdk getProjectJDK() {
+ return IdeaTestUtil.getMockJdk18();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
index 280b8fd2b8ae..719a074891ef 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
@@ -280,6 +280,10 @@ public class SafeDeleteTest extends MultiFileTestCase {
public void testTypeParameterWithinMethodHierarchy() throws Exception {
doSingleFileTest();
}
+
+ public void testTypeParameterNoMethodHierarchy() throws Exception {
+ doSingleFileTest();
+ }
public void testClassWithInnerStaticImport() throws Exception {
doTest("ClassWithInnerStaticImport");
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java
index 5b1e5a733c7b..ba6395fa993b 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineMethodTest.java
@@ -292,6 +292,18 @@ public class InlineMethodTest extends LightRefactoringTestCase {
doTestInlineThisOnly();
}
+ public void testInlineIntoMethodRef() throws Exception {
+ doTestInlineThisOnly();
+ }
+
+ public void testInlineIntoConstructorRef() throws Exception {
+ doTestInlineThisOnly();
+ }
+
+ public void testSideEffectsInMethodRefQualifier() throws Exception {
+ doTestConflict("Inlined method is used in method reference with side effects in qualifier");
+ }
+
private void doTestInlineThisOnly() {
@NonNls String fileName = "/refactoring/inlineMethod/" + getTestName(false) + ".java";
configureByFile(fileName);
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java
index d986896c3b8d..3987df0e2f26 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/FluentIterableConversionUtil.java
@@ -29,12 +29,11 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeEvaluator;
+import com.intellij.refactoring.util.LambdaRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SmartList;
import com.intellij.util.text.UniqueNameGenerator;
import com.siyeh.ig.psiutils.ParenthesesUtils;
-import com.siyeh.ipp.types.ReplaceMethodRefWithLambdaIntention;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -157,7 +156,7 @@ public class FluentIterableConversionUtil {
}
if (argument instanceof PsiMethodReferenceExpression) {
- argument = ReplaceMethodRefWithLambdaIntention.convertMethodReferenceToLambda((PsiMethodReferenceExpression)argument, true);
+ argument = LambdaRefactoringUtil.convertMethodReferenceToLambda((PsiMethodReferenceExpression)argument, true, true);
}
if (argument instanceof PsiLambdaExpression) {
List> iterableReturnValues = new SmartList>();
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java
index dbb79921a2ec..2635b15893c6 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaFluentIterableConversionRule.java
@@ -297,9 +297,15 @@ public class GuavaFluentIterableConversionRule extends BaseGuavaTypeConversionRu
TypeConversionDescriptorBase descriptor = null;
if (FLUENT_ITERABLE.equals(containingClass.getQualifiedName())) {
descriptor = getOneMethodDescriptor(methodName, method, current.getType(), null, current);
+ if (descriptor == null) {
+ return null;
+ }
}
else if (GuavaOptionalConversionRule.GUAVA_OPTIONAL.equals(containingClass.getQualifiedName())) {
descriptor = optionalDescriptor.getValue().findConversion(null, null, method, current.getMethodExpression(), labeler);
+ if (descriptor == null) {
+ return null;
+ }
}
if (descriptor == null) {
addToMigrateChainQualifier(labeler, current);
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java
index a7f9d0a1f850..32b434d04e7d 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicateConversionRule.java
@@ -64,7 +64,7 @@ public class GuavaPredicateConversionRule extends GuavaLambdaConversionRule {
return new TypeConversionDescriptorBase() {
@Override
public PsiExpression replace(PsiExpression expression, TypeEvaluator evaluator) throws IncorrectOperationException {
- return (PsiExpression)expression.replace(JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::test", expression));
+ return (PsiExpression)expression.replace(JavaPsiFacade.getElementFactory(expression.getProject()).createExpressionFromText(expression.getText() + "::apply", expression));
}
};
}
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicatesUtil.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicatesUtil.java
index bff50ba3da83..b24aa7c12ea3 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicatesUtil.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/guava/GuavaPredicatesUtil.java
@@ -45,7 +45,7 @@ public class GuavaPredicatesUtil {
static TypeConversionDescriptorBase tryConvertIfPredicates(PsiMethod method, PsiExpression context) {
final String name = method.getName();
if (name.equals("alwaysTrue") || name.equals("alwaysFalse")) {
- return new TypeConversionDescriptorWithLocalVariable(name, "$x$ -> " + name.contains("True") + "");
+ return createConstantPredicate(name, name.contains("True"));
}
else if (name.equals("isNull") || name.equals("notNull")) {
final String operation = name.equals("isNull") ? "==" : "!=";
@@ -54,7 +54,10 @@ public class GuavaPredicatesUtil {
else if (name.equals("equalTo")) {
return new TypeConversionDescriptorWithLocalVariable("equalTo", "$x$ -> java.util.Objects.equals($x$, $v$)");
}
- if (!isConvertablePredicatesMethod(method)) return null;
+ if (!isConvertablePredicatesMethod(method, (PsiMethodCallExpression)context)) return null;
+ if (((PsiMethodCallExpression)context).getArgumentList().getExpressions().length == 0) {
+ return createConstantPredicate(name, name.equals("and"));
+ }
if (PREDICATES_AND_OR.contains(name) && canMigrateAndOrOr((PsiMethodCallExpression)context)) {
return new AndOrOrConversionDescriptor(GuavaConversionUtil.addTypeParameters(GuavaLambda.PREDICATE.getJavaAnalogueClassQName(), context.getType(), context));
}
@@ -64,6 +67,11 @@ public class GuavaPredicatesUtil {
return null;
}
+ @NotNull
+ private static TypeConversionDescriptorWithLocalVariable createConstantPredicate(String methodName, boolean value) {
+ return new TypeConversionDescriptorWithLocalVariable(methodName, "$x$ -> " + value + "");
+ }
+
private static class TypeConversionDescriptorWithLocalVariable extends TypeConversionDescriptor {
private final String myReplaceByStringTemplate;
@@ -95,7 +103,7 @@ public class GuavaPredicatesUtil {
}
- public static boolean isConvertablePredicatesMethod(@NotNull PsiMethod method) {
+ public static boolean isConvertablePredicatesMethod(@NotNull PsiMethod method, PsiMethodCallExpression context) {
if (method.getParameterList().getParametersCount() == 1) {
final PsiParameter parameter = method.getParameterList().getParameters()[0];
final PsiClass psiClass = PsiTypesUtil.getPsiClass(parameter.getType().getDeepComponentType());
@@ -103,7 +111,8 @@ public class GuavaPredicatesUtil {
return false;
}
}
- return true;
+ final PsiExpression[] expressions = context.getArgumentList().getExpressions();
+ return !(expressions.length == 1 && expressions[0].getType() instanceof PsiArrayType);
}
private static boolean canMigrateAndOrOr(PsiMethodCallExpression expr) {
diff --git a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java
index de1e374d238b..480a17c124be 100644
--- a/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java
+++ b/java/typeMigration/test/com/intellij/codeInsight/inspections/GuavaInspectionTest.java
@@ -255,6 +255,10 @@ public class GuavaInspectionTest extends JavaCodeInsightFixtureTestCase {
doTestAllFile();
}
+ public void testFluentIterableElementTypeChanged() {
+ doTest();
+ }
+
private void doTestNoQuickFixes(Class extends PsiElement>... highlightedElements) {
myFixture.configureByFile(getTestName(true) + ".java");
myFixture.enableInspections(new GuavaInspection());
diff --git a/java/typeMigration/test/com/intellij/refactoring/MigrateTypeSignatureTest.java b/java/typeMigration/test/com/intellij/refactoring/MigrateTypeSignatureTest.java
index 328b8462fed0..464d76bf41cb 100644
--- a/java/typeMigration/test/com/intellij/refactoring/MigrateTypeSignatureTest.java
+++ b/java/typeMigration/test/com/intellij/refactoring/MigrateTypeSignatureTest.java
@@ -522,7 +522,7 @@ public class MigrateTypeSignatureTest extends TypeMigrationTestBase {
final PsiType toType) {
final RulesProvider provider = new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
+ public PsiType migrationType(PsiElement context) throws Exception {
return toType;
}
diff --git a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java
index 91d31a03b869..da90f6f7bd93 100644
--- a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java
+++ b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java
@@ -709,7 +709,7 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
private void doTestCatchParameter(final PsiType rootType, final PsiType migrationType) {
start(new RulesProvider() {
@Override
- public PsiType migrationType() {
+ public PsiType migrationType(PsiElement context) {
return migrationType;
}
@@ -807,7 +807,7 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
}
public void testMethodReturnTypeWithTypeParameter() {
- doTestReturnType("meth", myFactory.createTypeFromText("java.util.List", null));
+ doTestReturnType("meth", "java.util.List");
}
public void testBooleanGetterMethodName() {
@@ -826,11 +826,11 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
doTestFieldType("fooDontMigrateName", PsiType.BOOLEAN);
}
- private void doTestReturnType(final String methodName, final PsiType migrationType) {
+ private void doTestReturnType(final String methodName, final String migrationType) {
start(new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
- return migrationType;
+ public PsiType migrationType(PsiElement context) throws Exception {
+ return myFactory.createTypeFromText(migrationType, context);
}
@Override
@@ -848,7 +848,7 @@ public class TypeMigrationTest extends TypeMigrationTestBase {
private void doTestForeachParameter(final PsiType migrationType) {
start(new RulesProvider() {
@Override
- public PsiType migrationType() {
+ public PsiType migrationType(PsiElement context) {
return migrationType;
}
diff --git a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTestBase.java b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTestBase.java
index 43ee0cc7702e..889511a5670e 100644
--- a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTestBase.java
+++ b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTestBase.java
@@ -57,7 +57,7 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
final PsiType toType) {
final RulesProvider provider = new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
+ public PsiType migrationType(PsiElement context) throws Exception {
return toType;
}
@@ -84,7 +84,7 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
protected void doTestFieldType(@NonNls final String fieldName, String className, final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
+ public PsiType migrationType(PsiElement context) throws Exception {
return migrationType;
}
@@ -108,7 +108,7 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
+ public PsiType migrationType(PsiElement context) throws Exception {
return migrationType;
}
@@ -128,7 +128,7 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
protected void doTestFirstParamType(@NonNls final String methodName, String className, final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
- public PsiType migrationType() throws Exception {
+ public PsiType migrationType(PsiElement context) throws Exception {
return migrationType;
}
@@ -159,10 +159,11 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
assertNotNull("Class " + className + " not found", aClass);
- final PsiType migrationType = provider.migrationType();
+ final PsiElement migrationElement = provider.victims(aClass);
+ final PsiType migrationType = provider.migrationType(migrationElement);
final TypeMigrationRules rules = new TypeMigrationRules();
rules.setBoundScope(new LocalSearchScope(aClass.getContainingFile()));
- final TestTypeMigrationProcessor pr = new TestTypeMigrationProcessor(getProject(), provider.victims(aClass), migrationType, rules);
+ final TestTypeMigrationProcessor pr = new TestTypeMigrationProcessor(getProject(), migrationElement, migrationType, rules);
final UsageInfo[] usages = pr.findUsages();
final String report = pr.getLabeler().getMigrationReport();
@@ -210,7 +211,7 @@ public abstract class TypeMigrationTestBase extends MultiFileTestCase {
}
interface RulesProvider {
- PsiType migrationType() throws Exception;
+ PsiType migrationType(PsiElement context) throws Exception;
PsiElement victims(PsiClass aClass);
}
diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged.java b/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged.java
new file mode 100644
index 000000000000..5f0f8693e51f
--- /dev/null
+++ b/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged.java
@@ -0,0 +1,10 @@
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+
+import java.util.List;
+
+public class FluentTransformer {
+ public FluentIterable transformGeneric(FluentIterable p1, Function p2) {
+ return p1.transform(p2);
+ }
+}
\ No newline at end of file
diff --git a/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged_after.java b/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged_after.java
new file mode 100644
index 000000000000..567a62ebcbf1
--- /dev/null
+++ b/java/typeMigration/testData/inspections/guava/fluentIterableElementTypeChanged_after.java
@@ -0,0 +1,9 @@
+import com.google.common.base.Function;
+
+import java.util.stream.Stream;
+
+public class FluentTransformer {
+ public Stream transformGeneric(Stream p1, Function p2) {
+ return p1.map(p2::apply);
+ }
+}
\ No newline at end of file
diff --git a/java/typeMigration/testData/refactoring/typeMigration/t17/after/Test.items b/java/typeMigration/testData/refactoring/typeMigration/t17/after/Test.items
index aa0aa0551659..59b74e1b30bb 100644
--- a/java/typeMigration/testData/refactoring/typeMigration/t17/after/Test.items
+++ b/java/typeMigration/testData/refactoring/typeMigration/t17/after/Test.items
@@ -1,18 +1,11 @@
Types:
PsiField:f : B
-PsiMethodCallExpression:f.foo(s) : B
-PsiMethodCallExpression:s.add(f) : boolean
-PsiParameter:s : java.util.Set
+PsiMethodCallExpression:f.foo(s) : A
PsiReferenceExpression:f : B
PsiReferenceExpression:f : B
-PsiReferenceExpression:s : java.util.Set
-PsiReferenceExpression:s : java.util.Set
Conversions:
-f -> $
f.foo(s) -> $
-s -> $
-s.add(f) -> $
New expression type changes:
Fails:
diff --git a/java/typeMigration/testData/refactoring/typeMigration/t17/after/test.java b/java/typeMigration/testData/refactoring/typeMigration/t17/after/test.java
index 73530057f21b..d90d101faed2 100644
--- a/java/typeMigration/testData/refactoring/typeMigration/t17/after/test.java
+++ b/java/typeMigration/testData/refactoring/typeMigration/t17/after/test.java
@@ -2,7 +2,7 @@ import java.util.*;
class Test {
B f;
- A bar(Set s) {
+ A bar(Set s) {
s.add(f);
return f.foo(s);
}
diff --git a/java/typeMigration/testData/refactoring/typeMigration/t93/after/Test.items b/java/typeMigration/testData/refactoring/typeMigration/t93/after/Test.items
index ea2fc9440478..aaa26f9139cb 100644
--- a/java/typeMigration/testData/refactoring/typeMigration/t93/after/Test.items
+++ b/java/typeMigration/testData/refactoring/typeMigration/t93/after/Test.items
@@ -1,11 +1,8 @@
Types:
-PsiField:f : java.util.Map
PsiParameter:b : boolean
PsiReferenceExpression:b : boolean
-PsiReferenceExpression:f : java.util.Map
Conversions:
-f -> $
New expression type changes:
Fails:
diff --git a/platform/built-in-server/built-in-server-tests.iml b/platform/built-in-server/built-in-server-tests.iml
index 1ee2004f04e2..b5a8959c65f0 100644
--- a/platform/built-in-server/built-in-server-tests.iml
+++ b/platform/built-in-server/built-in-server-tests.iml
@@ -1,6 +1,6 @@
-
+
@@ -22,5 +22,6 @@
+
\ No newline at end of file
diff --git a/platform/built-in-server/built-in-server.iml b/platform/built-in-server/built-in-server.iml
index a49a37419e3b..1d39586de48e 100644
--- a/platform/built-in-server/built-in-server.iml
+++ b/platform/built-in-server/built-in-server.iml
@@ -1,11 +1,9 @@
-
+
-
-
diff --git a/platform/built-in-server/client/.gitignore b/platform/built-in-server/client/.gitignore
index fee741232909..e31ba3b844e9 100644
--- a/platform/built-in-server/client/.gitignore
+++ b/platform/built-in-server/client/.gitignore
@@ -1,3 +1,4 @@
node_modules/
npm-debug.log
-out/
\ No newline at end of file
+out/
+.idea/
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/.npmignore b/platform/built-in-server/client/node-rpc-client/.npmignore
new file mode 100644
index 000000000000..b81bb34ca62a
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/.npmignore
@@ -0,0 +1,6 @@
+src/
+test/
+node-rpc-client.iml
+typings/node/
+tsconfig.json
+tsd.json
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/LICENSE b/platform/built-in-server/client/node-rpc-client/LICENSE
new file mode 100644
index 000000000000..63cb0f0363c5
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/LICENSE
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2016 JetBrains
+
+ 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.
+
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/node-rpc-client.iml b/platform/built-in-server/client/node-rpc-client/node-rpc-client.iml
index 80cc7391bd40..3b9278ee9a90 100644
--- a/platform/built-in-server/client/node-rpc-client/node-rpc-client.iml
+++ b/platform/built-in-server/client/node-rpc-client/node-rpc-client.iml
@@ -2,7 +2,11 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/package.json b/platform/built-in-server/client/node-rpc-client/package.json
index 2f5c4fbc836d..3aca753b69d2 100644
--- a/platform/built-in-server/client/node-rpc-client/package.json
+++ b/platform/built-in-server/client/node-rpc-client/package.json
@@ -2,8 +2,10 @@
"name": "ij-rpc-client",
"version": "0.0.1",
"description": "IntelliJ Platform RPC client",
+ "license": "Apache-2.0",
+ "main": "./out/rpc-node.js",
"scripts": {
- "compile": "rimraf app/out && tsconfig -i 2 && tsc",
+ "compile": "rimraf out && tsconfig -i 2 && tsc",
"test": "mocha --harmony_default_parameters --harmony_rest_parameters"
},
"repository": {
@@ -11,12 +13,15 @@
"url": "https://github.com/JetBrains/intellij-community.git"
},
"devDependencies": {
+ "dts-generator": "^1.6.3",
+ "mocha": "^2.3.4",
"rimraf": "^2.5.0",
"should": "^8.0.2",
"tsconfig-glob": "^0.3.3",
"typescript": "^1.8.0-dev.20151231"
},
"dependencies": {
- "bluebird": "^3.1.1"
+ "bluebird": "^3.1.1",
+ "debug": "^2.2.0"
}
}
diff --git a/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts b/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts
deleted file mode 100644
index 45343ddd758c..000000000000
--- a/platform/built-in-server/client/node-rpc-client/src/rpc-client.ts
+++ /dev/null
@@ -1,139 +0,0 @@
-import * as net from "net"
-import { JsonRpc, Transport } from "./rpc"
-
-export class RpcClient {
- connect(port: number = 63342) {
- const socket = net.connect({port: port}, () => {
- console.log("Connected to IJ RPC server localhost: " + port)
- })
-
- const transport = new SocketTransport(socket)
- const jsonRpc = new JsonRpc(transport)
- const decoder = new MessageDecoder(jsonRpc.messageReceived)
- socket.on("data", decoder.messageReceived)
- }
-}
-
-const enum State {LENGTH, CONTENT}
-
-export class SocketTransport implements Transport {
- private headerBuffer = new Buffer(4)
-
- opened: () => void
-
- constructor(private socket: net.Socket = new net.Socket()) {
- }
-
- connect(port: number = 63342) {
- this.socket.connect(port, null, ()=> {
- const opened = this.opened
- if (opened != null) {
- opened()
- }
- })
- this.socket.on("error", (e: Error) => {
- console.error(e)
- })
- this.socket.write(new Buffer([67, 72, 105, -107, 126, -21, -81, -72, 64, 54, -87, -88, 0, -46, -48, 34, -7, -67]))
- }
-
- send(id: number, domain: string, command: string, params: any[] = null): void {
- const encodedParams = JSON.stringify(params)
- const header = (id == -1 ? '' : (id + ', ')) + '"' + domain + '", "' + command + '"';
- this.headerBuffer.writeUInt32BE(header.length + Buffer.byteLength(encodedParams), 0)
- this.socket.write(this.headerBuffer)
- this.socket.write(header)
- this.socket.write(encodedParams)
- }
-
- sendResult(id: number, result: any): void {
- this.sendResultOrError(id, result, false)
- }
-
- sendError(id: number, error: any): void {
- this.sendResultOrError(id, error, true)
- }
-
- private sendResultOrError(id: number, result: any, isError: boolean): void {
- var encodedResult = JSON.stringify(result)
- var header = id + ', "' + (isError ? 'e' : 'r') + '"';
- this.headerBuffer.writeUInt32BE(Buffer.byteLength(encodedResult) + header.length, 0)
- this.socket.write(this.headerBuffer)
- this.socket.write(encodedResult)
- }
-}
-
-class MessageDecoder {
- private state: State = State.LENGTH
- private contentLength: number = 0
-
- private buffers: Array = []
- private totalBufferLength: number = 0
- private offset: number = 0
-
- constructor(private messageProcessor: (message: any)=>void) {
- }
-
- private byteConsumed(count: number) {
- this.offset += count
- this.totalBufferLength -= count
- }
-
- messageReceived(buffer: Buffer) {
- this.totalBufferLength += buffer.length
-
- while (true) {
- //noinspection FallThroughInSwitchStatementJS
- switch (this.state) {
- case State.LENGTH:
- {
- if (this.totalBufferLength < 4) {
- this.buffers.push(buffer)
- return
- }
-
- var totalBuffer: Buffer
- if (this.buffers.length === 0) {
- totalBuffer = buffer
- }
- else {
- this.buffers.push(buffer)
- totalBuffer = Buffer.concat(this.buffers, this.totalBufferLength)
- this.buffers.length = 0
- }
-
- this.state = State.CONTENT
- this.contentLength = totalBuffer.readUInt32BE(this.offset)
- this.byteConsumed(4)
- buffer = totalBuffer
- }
-
- case State.CONTENT:
- {
- if (this.totalBufferLength < this.contentLength) {
- this.buffers.push(buffer)
- return
- }
-
- var totalBuffer: Buffer
- if (this.buffers.length === 0) {
- totalBuffer = buffer
- }
- else {
- this.buffers.push(buffer)
- totalBuffer = Buffer.concat(this.buffers, this.totalBufferLength)
- this.buffers.length = 0
- }
-
- var message = JSON.parse(totalBuffer.toString('utf8', this.offset, this.contentLength));
- this.state = State.LENGTH
- this.byteConsumed(this.contentLength)
- this.contentLength = 0
- buffer = totalBuffer
-
- this.messageProcessor(message)
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/src/rpc-node.ts b/platform/built-in-server/client/node-rpc-client/src/rpc-node.ts
new file mode 100644
index 000000000000..84f336047cc8
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/src/rpc-node.ts
@@ -0,0 +1,173 @@
+import * as net from "net"
+import { JsonRpc, Transport } from "./rpc"
+const debug = require("debug")("rpc")
+
+export function connect(port: number = 63342, domains: { [domainName:string]: { [methodName:string]:Function; }; } = null): JsonRpc {
+ const transport = new SocketTransport()
+ const server = new JsonRpc(transport, domains)
+ transport.connect(port)
+ return server
+}
+
+export class SocketTransport implements Transport {
+ opened: () => void
+ messageReceived: (message: Array) => void
+
+ constructor(private socket: net.Socket = new net.Socket()) {
+ }
+
+ connect(port: number = 63342) {
+ this.socket.connect(port, null, ()=> {
+ debug("Connected to %s", port)
+ const opened = this.opened
+ if (opened != null) {
+ opened()
+ }
+ })
+ this.socket.on("error", (e: Error) => {
+ console.error(e)
+ })
+
+ const messageReceived = this.messageReceived
+ if (messageReceived == null) {
+ console.warn("messageReceived is not specified, input will be ignored")
+ }
+ else {
+ const messageDecoder = new MessageDecoder(messageReceived)
+ this.socket.on("data", messageDecoder.messageReceived.bind(messageDecoder))
+ }
+
+ this.socket.write(new Buffer([67, 72, 105, -107, 126, -21, -81, -72, 64, 54, -87, -88, 0, -46, -48, 34, -7, -67]))
+ }
+
+ send(id: number, domain: string, command: string, params: any[] = null): void {
+ const encodedParams = params == null || params.length === 0 ? null : JSON.stringify(params)
+ const header = '[' + (id == -1 ? '' : (id + ', ')) + '"' + domain + '", "' + command + '"'
+ const headerBuffer = new Buffer(4)
+ headerBuffer.writeUInt32BE(header.length + (encodedParams == null ? 0 : Buffer.byteLength(encodedParams)) + 1 /* ] symbol*/, 0)
+ this.socket.write(headerBuffer)
+
+ debug("out: %s%s]", header, encodedParams || "")
+
+ this.socket.write(header)
+ if (encodedParams != null) {
+ this.socket.write(encodedParams)
+ }
+ this.socket.write(']')
+ }
+
+ sendResult(id: number, result: any): void {
+ this.sendResultOrError(id, result, false)
+ }
+
+ sendError(id: number, error: any): void {
+ this.sendResultOrError(id, error, true)
+ }
+
+ private sendResultOrError(id: number, result: any, isError: boolean): void {
+ var encodedResult = JSON.stringify(result)
+ var header = id + ', "' + (isError ? 'e' : 'r') + '"'
+ const headerBuffer = new Buffer(4)
+ headerBuffer.writeUInt32BE(Buffer.byteLength(encodedResult) + header.length, 0)
+ this.socket.write(headerBuffer)
+ this.socket.write(encodedResult)
+ }
+}
+
+const enum State {LENGTH, CONTENT}
+
+class MessageDecoder {
+ private state = State.LENGTH
+ private contentLength = 0
+
+ private buffers: Array = []
+ private messageBuffer: Buffer
+
+ private readableByteCount = 0
+
+ private messageBufferOffset = 0
+
+ constructor(private messageProcessor: (message: any)=>void) {
+ }
+
+ private concatBuffer(buffer: Buffer): Buffer {
+ if (this.buffers.length === 0) {
+ return buffer
+ }
+
+ this.buffers.push(buffer)
+ let totalBuffer = Buffer.concat(this.buffers, this.readableByteCount)
+ this.buffers.length = 0
+ return totalBuffer
+ }
+
+ messageReceived(buffer: Buffer) {
+ let offset = 0
+ this.readableByteCount += buffer.length
+ while (true) {
+ //noinspection FallThroughInSwitchStatementJS
+ switch (this.state) {
+ case State.LENGTH: {
+ if (this.readableByteCount < 4) {
+ if (offset != 0) {
+ buffer = buffer.slice(offset)
+ }
+ this.buffers.push(buffer)
+ return
+ }
+
+ buffer = this.concatBuffer(buffer)
+ this.state = State.CONTENT
+ this.contentLength = buffer.readUInt32BE(offset)
+ offset += 4
+
+ if ((buffer.length - offset) < this.contentLength) {
+ this.messageBuffer = new Buffer(this.contentLength)
+ buffer.copy(this.messageBuffer, 0, offset)
+ this.messageBufferOffset = 0
+ this.readableByteCount = 0
+ return
+ }
+
+ this.readableByteCount = buffer.length - offset
+ }
+
+ case State.CONTENT: {
+ let rawMessage: string
+ if (this.messageBuffer == null) {
+ rawMessage = buffer.toString("utf8", offset, offset + this.contentLength)
+ offset += this.contentLength
+ this.readableByteCount = buffer.length - offset
+ }
+ else {
+ const requiredByteCount = this.messageBuffer.length - this.messageBufferOffset
+ if (requiredByteCount > this.readableByteCount) {
+ buffer.copy(this.messageBuffer, this.messageBufferOffset, offset)
+ this.messageBufferOffset += this.readableByteCount
+ this.readableByteCount = 0
+ return
+ }
+ else {
+ const newOffset = offset + requiredByteCount
+ buffer.copy(this.messageBuffer, this.messageBufferOffset, offset, newOffset)
+ offset = newOffset
+ this.readableByteCount = buffer.length - offset
+ rawMessage = this.messageBuffer.toString("utf8")
+ }
+ }
+
+ debug("in: %s", rawMessage)
+ try {
+ this.state = State.LENGTH
+ this.contentLength = 0
+
+ this.messageProcessor(JSON.parse(rawMessage))
+ }
+ catch (e) {
+ console.error("Error: %s,\nInput: %s", e, rawMessage)
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/src/rpc.ts b/platform/built-in-server/client/node-rpc-client/src/rpc.ts
index 7aba41a980da..40f5fca7cc2e 100644
--- a/platform/built-in-server/client/node-rpc-client/src/rpc.ts
+++ b/platform/built-in-server/client/node-rpc-client/src/rpc.ts
@@ -8,6 +8,11 @@ class PromiseCallback {
export interface Transport {
opened?: () => void
+ /**
+ * Internal use only (JsonRpc configure it).
+ */
+ messageReceived: (message: Array) => void
+
connect(port: number): void
send(id: number, domain: string, command: string, params: any[]): void
@@ -17,26 +22,57 @@ export interface Transport {
sendError(id: number, error: any):void
}
+interface Map {
+ clear(): void;
+ delete(key: K): boolean;
+ get(key: K): V;
+ has(key: K): boolean;
+ set(key: K, value?: V): Map;
+}
+
+interface MapConstructor {
+ new (): Map
+
+ prototype: Map
+}
+declare var Map: MapConstructor
+
export class JsonRpc {
private messageIdCounter = 0
private callbacks: Map = new Map()
- private domains: Map = new Map()
+ private domains = new Map()
- constructor(private transport: Transport) {
+ constructor(private transport: Transport, domains: { [domainName:string]: { [methodName:string]:Function; }; } = null) {
+ this.domains = new Map()
+ if (domains != null) {
+ for (let name of Object.getOwnPropertyNames(domains)) {
+ this.domains.set(name, domains[name])
+ }
+ }
+
+ transport.messageReceived = this.messageReceived.bind(this)
+ }
+
+ public registerDomain(name: string, commands: any) {
+ if (this.domains.has(name)) {
+ throw Error("Domain " + name + " is already registered")
+ }
+
+ this.domains.set(name, commands)
}
public call(domain: string, command: string, ...params: any[]): Promise {
return new Promise((resolve: (value: T) => void, reject: (error?: any) => void) => {
- var id = this.messageIdCounter++;
+ const id = this.messageIdCounter++
this.callbacks.set(id, new PromiseCallback(resolve, reject))
this.transport.send(id, domain, command, params)
})
}
- messageReceived(message: Array) {
- if (message.length === 1 || (message.length === 2 && !(typeof message[1] === 'string'))) {
- var promiseCallback = this.callbacks.get(message[0])
- var singletonArray = safeGet(message, 1)
+ private messageReceived(message: Array) {
+ if (message.length === 1 || (message.length === 2 && !(typeof message[1] === "string"))) {
+ const promiseCallback = this.callbacks.get(message[0])
+ const singletonArray = safeGet(message, 1)
if (singletonArray == null) {
promiseCallback.resolve()
}
@@ -45,9 +81,9 @@ export class JsonRpc {
}
}
else {
- var id: number
- var offset: number
- if (typeof message[0] === 'string') {
+ let id: number
+ let offset: number
+ if (typeof message[0] === "string") {
id = -1
offset = 0
}
@@ -56,21 +92,31 @@ export class JsonRpc {
offset = 1
}
- var onRejected = id === -1 ? null : (error: any) => this.transport.sendError(id, error)
+ const domainName = message[offset]
+ if (domainName === "e") {
+ console.assert(id != -1)
+ console.assert(message.length === 3)
+ this.callbacks.get(id).reject(message[2])
+ return
+ }
+
+ const onRejected = id === -1 ? null : (error: any) => this.transport.sendError(id, error)
try {
- var object = this.domains.get(message[offset])
- var method = object[message[offset + 1]]
- var result: any
- var args = safeGet(message, offset + 2)
- if (args === null) {
- result = method.call(object)
- }
- else {
- result = method.apply(object, args)
+ const object = this.domains.get(domainName)
+ if (object == null) {
+ const e = "Cannot find domain " + domainName
+ console.warn(e)
+ if (onRejected != null) {
+ onRejected(e)
+ }
+ return
}
+ const method = object[message[offset + 1]]
+ const args = safeGet(message, offset + 2)
+ const result: any = (args === null) ? method.call(object) : method.apply(object, args)
if (id !== -1) {
- var onFulfilled = (result: any) => this.transport.sendResult(id, result)
+ const onFulfilled = (result: any) => this.transport.sendResult(id, result)
if (result instanceof Promise) {
(>result).done(onFulfilled, onRejected)
}
diff --git a/platform/built-in-server/client/node-rpc-client/test/test.js b/platform/built-in-server/client/node-rpc-client/test/test.js
index 5fa4efa3f6cc..712c2b3fd70a 100644
--- a/platform/built-in-server/client/node-rpc-client/test/test.js
+++ b/platform/built-in-server/client/node-rpc-client/test/test.js
@@ -1,30 +1,19 @@
-const should = require("should")
-const rpcClient = require("../out/rpc-client")
+const assertThat = require("should/as-function")
+
+const rpcNode = require("../out/rpc-node")
const rpc = require("../out/rpc")
describe("RPC", function () {
it("connect", function (done) {
- const transport = new rpcClient.SocketTransport()
+ const transport = new rpcNode.SocketTransport()
transport.opened = function () {
done()
}
transport.connect()
})
- it("connect", function (done) {
- this.timeout(5000000)
- const transport = new rpcClient.SocketTransport()
- transport.opened = function () {
- }
- transport.connect(63343)
-
- const rpcServer = new rpc.JsonRpc(transport)
- rpcServer.call("Ide", "about")
- .then(function (r) {
- console.log(r)
- done()
- }, function (e) {
- throw e
- })
+ it("call method", function () {
+ const rpcServer = rpcNode.connect(63343)
+ return assertThat(rpcServer.call("Ide", "about")).fulfilled()
})
})
\ No newline at end of file
diff --git a/platform/built-in-server/client/node-rpc-client/tsconfig.json b/platform/built-in-server/client/node-rpc-client/tsconfig.json
index c7a0c1aa243f..09f524694bbe 100644
--- a/platform/built-in-server/client/node-rpc-client/tsconfig.json
+++ b/platform/built-in-server/client/node-rpc-client/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"module": "commonjs",
- "target": "es6",
+ "target": "es5",
"noImplicitAny": true,
"removeComments": true,
"outDir": "out",
@@ -18,7 +18,7 @@
"files": [
"typings/bluebird/bluebird.d.ts",
"typings/node/node.d.ts",
- "src/rpc-client.ts",
+ "src/rpc-node.ts",
"src/rpc.ts"
]
}
diff --git a/platform/built-in-server/client/node-rpc-client/tsd.json b/platform/built-in-server/client/node-rpc-client/tsd.json
index 924203dfa87c..fb9bc081f931 100644
--- a/platform/built-in-server/client/node-rpc-client/tsd.json
+++ b/platform/built-in-server/client/node-rpc-client/tsd.json
@@ -9,6 +9,9 @@
},
"bluebird/bluebird.d.ts": {
"commit": "dc9dabe74a5be62613b17a3605309783a12ff28a"
+ },
+ "debug/debug.d.ts": {
+ "commit": "627b6c158b73494c803f36fc2fe00ad75faa8fde"
}
}
}
diff --git a/platform/built-in-server/client/node-rpc-client/typings/debug/debug.d.ts b/platform/built-in-server/client/node-rpc-client/typings/debug/debug.d.ts
new file mode 100644
index 000000000000..b43cd238c3cf
--- /dev/null
+++ b/platform/built-in-server/client/node-rpc-client/typings/debug/debug.d.ts
@@ -0,0 +1,38 @@
+// Type definitions for debug
+// Project: https://github.com/visionmedia/debug
+// Definitions by: Seon-Wook Park , Gal Talmor
+// Definitions: https://github.com/borisyankov/DefinitelyTyped
+
+declare var debug: debug.IDebug;
+
+// Support AMD require
+declare module 'debug' {
+ export = debug;
+}
+
+declare module debug {
+ export interface IDebug {
+ (namespace: string): debug.IDebugger,
+ coerce: (val: any) => any,
+ disable: () => void,
+ enable: (namespaces: string) => void,
+ enabled: (namespaces: string) => boolean,
+
+ names: string[],
+ skips: string[],
+
+ formatters: IFormatters
+ }
+
+ export interface IFormatters {
+ [formatter: string]: Function
+ }
+
+ export interface IDebugger {
+ (formatter: any, ...args: any[]): void;
+
+ enabled: boolean;
+ log: Function;
+ namespace: string;
+ }
+}
diff --git a/platform/built-in-server/src/net.kt b/platform/built-in-server/src/net.kt
new file mode 100644
index 000000000000..64cbc78e096c
--- /dev/null
+++ b/platform/built-in-server/src/net.kt
@@ -0,0 +1,7 @@
+package com.intellij.util.net
+
+import java.net.InetAddress
+import java.net.InetSocketAddress
+
+@JvmOverloads
+fun loopbackSocketAddress(port: Int = -1) = InetSocketAddress(InetAddress.getLoopbackAddress(), if (port == -1) NetUtils.findAvailableSocketPort() else port)
\ No newline at end of file
diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/SingleConnectionNetService.kt b/platform/built-in-server/src/org/jetbrains/builtInWebServer/SingleConnectionNetService.kt
index 1b30103e9440..1e498e716b19 100644
--- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/SingleConnectionNetService.kt
+++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/SingleConnectionNetService.kt
@@ -3,7 +3,7 @@ package org.jetbrains.builtInWebServer
import com.intellij.execution.process.OSProcessHandler
import com.intellij.openapi.project.Project
import com.intellij.util.Consumer
-import com.intellij.util.net.NetUtils
+import com.intellij.util.net.loopbackSocketAddress
import io.netty.bootstrap.Bootstrap
import io.netty.channel.Channel
import org.jetbrains.concurrency.AsyncPromise
@@ -11,7 +11,6 @@ import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.catchError
import org.jetbrains.concurrency.resolvedPromise
import org.jetbrains.io.*
-import java.net.InetSocketAddress
import java.util.concurrent.atomic.AtomicReference
abstract class SingleConnectionNetService(project: Project) : NetService(project) {
@@ -29,7 +28,7 @@ abstract class SingleConnectionNetService(project: Project) : NetService(project
this.bootstrap = bootstrap
this.port = port
- bootstrap.connect(InetSocketAddress(NetUtils.getLoopbackAddress(), port), promise)?.let {
+ bootstrap.connect(loopbackSocketAddress(port), promise)?.let {
promise.catchError {
processChannel.set(it)
addCloseListener(it)
@@ -45,7 +44,7 @@ abstract class SingleConnectionNetService(project: Project) : NetService(project
}
val promise = AsyncPromise()
- bootstrap!!.connect(InetSocketAddress(NetUtils.getLoopbackAddress(), port), promise)?.let {
+ bootstrap!!.connect(loopbackSocketAddress(port), promise)?.let {
promise.catchError {
processChannel.set(it)
addCloseListener(it)
diff --git a/platform/built-in-server/src/org/jetbrains/io/SubServer.java b/platform/built-in-server/src/org/jetbrains/io/SubServer.java
index 96f4f13693ad..c5e58d805f36 100644
--- a/platform/built-in-server/src/org/jetbrains/io/SubServer.java
+++ b/platform/built-in-server/src/org/jetbrains/io/SubServer.java
@@ -19,7 +19,7 @@ import com.intellij.ide.XmlRpcServer;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Disposer;
-import com.intellij.util.net.NetUtils;
+import com.intellij.util.net.NetKt;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
@@ -76,7 +76,7 @@ public final class SubServer implements CustomPortServerManager.CustomPortServic
}
try {
- bootstrap.localAddress(user.isAvailableExternally() ? new InetSocketAddress(port) : new InetSocketAddress(NetUtils.getLoopbackAddress(), port));
+ bootstrap.localAddress(user.isAvailableExternally() ? new InetSocketAddress(port) : NetKt.loopbackSocketAddress(port));
channelRegistrar.add(bootstrap.bind().syncUninterruptibly().channel());
return true;
}
diff --git a/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiService.kt b/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiService.kt
index 7d79cdbbf4f3..08e57eb93001 100644
--- a/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiService.kt
+++ b/platform/built-in-server/src/org/jetbrains/io/fastCgi/FastCgiService.kt
@@ -26,6 +26,7 @@ import io.netty.channel.Channel
import io.netty.handler.codec.http.*
import org.jetbrains.builtInWebServer.SingleConnectionNetService
import org.jetbrains.concurrency.Promise
+import org.jetbrains.concurrency.doneRun
import org.jetbrains.io.*
import java.util.concurrent.atomic.AtomicInteger
@@ -82,8 +83,8 @@ abstract class FastCgiService(project: Project) : SingleConnectionNetService(pro
promise = processHandler.get()
}
- (promise as Promise)
- .done { fastCgiRequest.writeToServerChannel(notEmptyContent, processChannel.get()!!) }
+ promise
+ .doneRun { fastCgiRequest.writeToServerChannel(notEmptyContent, processChannel.get()!!) }
.rejected {
Promise.logError(LOG, it)
handleError(fastCgiRequest, notEmptyContent)
diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/Client.java b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/Client.java
index 9480877340eb..e53cb5a09808 100644
--- a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/Client.java
+++ b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/Client.java
@@ -34,6 +34,7 @@ public abstract class Client extends UserDataHolderBase {
return channel.alloc();
}
+ @NotNull
protected abstract ChannelFuture send(@NotNull ByteBuf message);
public abstract void sendHeartbeat();
diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.java b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.java
deleted file mode 100644
index 891ba6b9fed7..000000000000
--- a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.jetbrains.io.jsonRpc;
-
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.SimpleTimer;
-import com.intellij.openapi.util.SimpleTimerTask;
-import gnu.trove.THashSet;
-import gnu.trove.TObjectProcedure;
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.util.AttributeKey;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.concurrency.AsyncPromise;
-import org.jetbrains.io.webSocket.WebSocketServerOptions;
-
-import java.util.List;
-
-public class ClientManager implements Disposable {
- public static final AttributeKey CLIENT = AttributeKey.valueOf("SocketHandler.client");
-
- private final SimpleTimerTask heartbeatTimer;
-
- @Nullable
- private final ClientListener listener;
-
- @NotNull
- public final ExceptionHandler exceptionHandler;
-
- private final THashSet clients = new THashSet();
-
- public ClientManager() {
- this(null, new ExceptionHandlerImpl());
- }
-
- public ClientManager(@Nullable ClientListener listener, @NotNull ExceptionHandler exceptionHandler) {
- this(null, exceptionHandler, listener);
- }
-
- public ClientManager(@Nullable WebSocketServerOptions options, @NotNull ExceptionHandler exceptionHandler, @Nullable ClientListener listener) {
- this.exceptionHandler = exceptionHandler;
- this.listener = listener;
-
- heartbeatTimer = SimpleTimer.getInstance().setUp(new Runnable() {
- @Override
- public void run() {
- synchronized (clients) {
- if (clients.isEmpty()) {
- return;
- }
-
- clients.forEach(new TObjectProcedure() {
- @Override
- public boolean execute(Client client) {
- if (client.channel.isActive()) {
- client.sendHeartbeat();
- }
- return true;
- }
- });
- }
- }
- }, (options == null ? new WebSocketServerOptions() : options).heartbeatDelay);
- }
-
- public void addClient(@NotNull Client client) {
- synchronized (clients) {
- clients.add(client);
- }
- }
-
- public int getClientCount() {
- synchronized (clients) {
- return clients.size();
- }
- }
-
- public boolean hasClients() {
- return getClientCount() > 0;
- }
-
- @Override
- public void dispose() {
- try {
- heartbeatTimer.cancel();
- }
- finally {
- synchronized (clients) {
- clients.clear();
- }
- }
- }
-
- public void send(final int messageId, @NotNull final ByteBuf message, @Nullable final List>> results) {
- forEachClient(new TObjectProcedure() {
- private boolean first;
-
- @Override
- public boolean execute(final Client client) {
- try {
- AsyncPromise> result = client.send(messageId, first ? message : message.duplicate());
- first = false;
- if (results != null) {
- results.add(result);
- }
- }
- catch (Throwable e) {
- exceptionHandler.exceptionCaught(e);
- }
- return true;
- }
- });
- }
-
- public boolean disconnectClient(@NotNull ChannelHandlerContext context, @NotNull Client client, boolean closeChannel) {
- synchronized (clients) {
- if (!clients.remove(client)) {
- return false;
- }
- }
-
- try {
- context.attr(CLIENT).remove();
-
- if (closeChannel) {
- context.channel().close();
- }
-
- client.rejectAsyncResults(exceptionHandler);
- }
- finally {
- if (listener != null) {
- listener.disconnected(client);
- }
- }
- return true;
- }
-
- public void forEachClient(@NotNull TObjectProcedure procedure) {
- synchronized (clients) {
- if (clients.isEmpty()) {
- return;
- }
-
- clients.forEach(procedure);
- }
- }
-}
\ No newline at end of file
diff --git a/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.kt b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.kt
new file mode 100644
index 000000000000..5bed61f85081
--- /dev/null
+++ b/platform/built-in-server/src/org/jetbrains/io/jsonRpc/ClientManager.kt
@@ -0,0 +1,104 @@
+package org.jetbrains.io.jsonRpc
+
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.util.SimpleTimer
+import gnu.trove.THashSet
+import gnu.trove.TObjectProcedure
+import io.netty.buffer.ByteBuf
+import io.netty.channel.ChannelHandlerContext
+import io.netty.util.AttributeKey
+import org.jetbrains.concurrency.Promise
+import org.jetbrains.io.webSocket.WebSocketServerOptions
+
+val CLIENT = AttributeKey.valueOf