Merge branch 'bibaev/IDEA-172425-eval-expr-jdk-9'

This commit is contained in:
Vitaliy.Bibaev
2018-03-06 09:58:27 +03:00
76 changed files with 1218 additions and 248 deletions
@@ -3,6 +3,7 @@ package com.intellij.debugger.ui.impl.watch;
import com.intellij.compiler.CompilerConfiguration;
import com.intellij.compiler.server.BuildManager;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.openapi.application.ApplicationManager;
@@ -26,6 +27,8 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.extractMethodObject.ExtractLightMethodObjectHandler;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.frame.XSuspendContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.java.JavaBuilder;
@@ -140,11 +143,22 @@ public class CompilingEvaluatorImpl extends CompilingEvaluator {
if (Registry.is("debugger.compiling.evaluator") && psiContext != null) {
return ApplicationManager.getApplication().runReadAction((ThrowableComputable<ExpressionEvaluator, EvaluateException>)() -> {
try {
boolean useReflection = !Registry.is("debugger.compiling.evaluator.magic.accessor", true);
if (!useReflection) {
XSuspendContext suspendContext = XDebuggerManager.getInstance(project).getCurrentSession().getSuspendContext();
if (suspendContext instanceof SuspendContextImpl) {
JavaSdkVersion version =
JavaSdkVersion.fromVersionString(((SuspendContextImpl)suspendContext).getDebugProcess().getVirtualMachineProxy().version());
useReflection = version != null && version.isAtLeast(JavaSdkVersion.JDK_1_9);
}
}
ExtractLightMethodObjectHandler.ExtractedData data = ExtractLightMethodObjectHandler.extractLightMethodObject(
project,
findPhysicalContext(psiContext),
fragmentFactory.apply(psiContext),
getGeneratedClassName());
getGeneratedClassName(),
useReflection);
if (data != null) {
return new CompilingEvaluatorImpl(project, psiContext, data);
}
@@ -29,6 +29,7 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.extractMethod.AbstractExtractDialog;
import com.intellij.refactoring.extractMethod.InputVariables;
import com.intellij.refactoring.extractMethod.PrepareFailedException;
import com.intellij.refactoring.extractMethodObject.reflect.CompositeReflectionAccessor;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.VariableData;
import com.intellij.usageView.UsageInfo;
@@ -71,7 +72,8 @@ public class ExtractLightMethodObjectHandler {
public static ExtractedData extractLightMethodObject(final Project project,
@Nullable PsiElement originalContext,
@NotNull final PsiCodeFragment fragment,
final String methodName) throws PrepareFailedException {
final String methodName,
boolean useReflection) throws PrepareFailedException {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiElement[] elements = completeToStatementArray(fragment, elementFactory);
if (elements == null) {
@@ -196,25 +198,27 @@ public class ExtractLightMethodObjectHandler {
PsiStatement outStatement = elementFactory.createStatementFromText("System.out.println(" + outputVariables + ");", anchor);
outStatement = (PsiStatement)container.addAfter(outStatement, elementsCopy[elementsCopy.length - 1]);
copy.accept(new JavaRecursiveElementWalkingVisitor() {
private void makePublic(PsiMember method) {
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
if (!useReflection) {
copy.accept(new JavaRecursiveElementWalkingVisitor() {
private void makePublic(PsiMember method) {
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
VisibilityUtil.setVisibility(method.getModifierList(), PsiModifier.PUBLIC);
}
}
}
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
makePublic(method);
}
@Override
public void visitMethod(PsiMethod method) {
super.visitMethod(method);
makePublic(method);
}
@Override
public void visitField(PsiField field) {
super.visitField(field);
makePublic(field);
}
});
@Override
public void visitField(PsiField field) {
super.visitField(field);
makePublic(field);
}
});
}
final ExtractMethodObjectProcessor extractMethodObjectProcessor = new ExtractMethodObjectProcessor(project, null, elementsCopy, "") {
@Override
@@ -253,6 +257,16 @@ public class ExtractLightMethodObjectHandler {
}
final int startOffset = startOffsetInContainer + container.getTextRange().getStartOffset();
final PsiClass inner = extractMethodObjectProcessor.getInnerClass();
final PsiMethod[] methods = inner.findMethodsByName("invoke", false);
if (useReflection && methods.length == 1) {
final PsiMethod method = methods[0];
CompositeReflectionAccessor.createAccessorToEverything(inner, elementFactory)
.accessThroughReflection(method);
}
final String generatedCall = copy.getText().substring(startOffset, outStatement.getTextOffset());
return new ExtractedData(generatedCall,
(PsiClass)CodeStyleManager.getInstance(project).reformat(extractMethodObjectProcessor.getInnerClass()),
@@ -0,0 +1,8 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject;
/**
* @author Vitaliy.Bibaev
*/
public interface ItemToReplaceDescriptor {
}
@@ -0,0 +1,86 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vitaliy.Bibaev
*/
public class PsiReflectionAccessUtil {
public static boolean isAccessibleMember(@NotNull PsiMember classMember) {
return classMember.hasModifierProperty(PsiModifier.PUBLIC) && isAccessible(classMember.getContainingClass());
}
@Contract("null -> false")
public static boolean isAccessible(@Nullable PsiClass psiClass) {
if (psiClass == null) return false;
while (psiClass != null) {
if (!psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
return false;
}
psiClass = psiClass.getContainingClass();
}
return true;
}
@Nullable
public static String extractQualifier(@NotNull PsiReferenceExpression referenceExpression) {
PsiExpression qualifierExpression = referenceExpression.getQualifierExpression();
PsiType expressionType = qualifierExpression != null ? qualifierExpression.getType() : null;
return expressionType == null ? null : qualifierExpression.getText();
}
@Contract("null -> null")
@Nullable
public static PsiClass nearestAccessedClass(@Nullable PsiClass psiClass) {
while (psiClass != null && !psiClass.hasModifierProperty(PsiModifier.PUBLIC)) {
psiClass = psiClass.getSuperClass();
}
return psiClass;
}
@Nullable
public static String getAccessibleReturnType(@Nullable PsiType type) {
PsiClass psiClass = nearestAccessedClass(PsiUtil.resolveClassInType(type));
if (psiClass != null) {
return psiClass.getQualifiedName();
}
return type != null ? type.getCanonicalText() : null;
}
@Nullable
public static String getAccessibleReturnType(@Nullable PsiClass psiClass) {
psiClass = nearestAccessedClass(psiClass);
return psiClass == null ? null : psiClass.getQualifiedName();
}
@NotNull
@Contract(pure = true)
public static String classForName(@NotNull String typeName) {
return TypeConversionUtil.isPrimitive(typeName) ? typeName + ".class" : "java.lang.Class.forName(\"" + typeName + "\")";
}
@NotNull
public static String getUniqueMethodName(@NotNull PsiClass psiClass, @NotNull String prefix) {
if (!StringUtil.isJavaIdentifier(prefix)) throw new IllegalArgumentException("prefix must be a correct java identifier: " + prefix);
int i = 1;
String name;
do {
name = prefix + i;
i++;
}
while (psiClass.findMethodsByName(name, false).length != 0);
return name;
}
}
@@ -0,0 +1,41 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* @author Vitaliy.Bibaev
*/
public class CompositeReflectionAccessor implements ReflectionAccessor {
private final List<ReflectionAccessor> myAccessors = new ArrayList<>();
private CompositeReflectionAccessor() {
}
private void registerAccessor(@NotNull ReflectionAccessor accessor) {
myAccessors.add(accessor);
}
public static ReflectionAccessor createAccessorToEverything(@NotNull PsiClass psiClass, @NotNull PsiElementFactory elementFactory) {
CompositeReflectionAccessor compositeAccessor = new CompositeReflectionAccessor();
compositeAccessor.registerAccessor(new FieldReflectionAccessor(psiClass, elementFactory));
compositeAccessor.registerAccessor(new MethodReflectionAccessor(psiClass, elementFactory));
compositeAccessor.registerAccessor(new ConstructorReflectionAccessor(psiClass, elementFactory));
compositeAccessor.registerAccessor(new MethodReferenceReflectionAccessor(psiClass, elementFactory));
return compositeAccessor;
}
@Override
public void accessThroughReflection(@NotNull PsiElement element) {
for (ReflectionAccessor accessor : myAccessors) {
accessor.accessThroughReflection(element);
}
}
}
@@ -0,0 +1,104 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import com.intellij.refactoring.extractMethodObject.PsiReflectionAccessUtil;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author Vitaliy.Bibaev
*/
public class ConstructorReflectionAccessor extends ReflectionAccessorBase<ConstructorReflectionAccessor.ConstructorDescriptor> {
private static final Logger LOG = Logger.getInstance(ConstructorReflectionAccessor.class);
protected ConstructorReflectionAccessor(@NotNull PsiClass psiClass,
@NotNull PsiElementFactory elementFactory) {
super(psiClass, elementFactory);
}
@Override
protected List<ConstructorDescriptor> findItemsToReplace(@NotNull PsiElement element) {
List<ConstructorDescriptor> result = new ArrayList<>();
element.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitNewExpression(PsiNewExpression expression) {
super.visitNewExpression(expression);
if (expression.getAnonymousClass() != null || expression.getArrayInitializer() != null) return;
ConstructorDescriptor descriptor = ConstructorDescriptor.createIfInaccessible(expression);
if (descriptor != null) {
result.add(descriptor);
}
}
});
return result;
}
@Override
protected void grantAccess(@NotNull ConstructorDescriptor descriptor) {
String className = ClassUtil.getJVMClassName(descriptor.psiClass);
String returnType = PsiReflectionAccessUtil.getAccessibleReturnType(descriptor.psiClass);
PsiExpressionList argumentList = descriptor.newExpression.getArgumentList();
if (className == null || argumentList == null || returnType == null) {
LOG.debug("expression is incomplete");
return;
}
String methodName = PsiReflectionAccessUtil.getUniqueMethodName(getOuterClass(), "new" + className);
ReflectionAccessMethodBuilder methodBuilder = new ReflectionAccessMethodBuilder(methodName);
methodBuilder.accessedConstructor(className)
.setStatic(getOuterClass().hasModifierProperty(PsiModifier.STATIC))
.setReturnType(returnType);
if (descriptor.constructor != null) {
methodBuilder.addParameters(descriptor.constructor.getParameterList());
}
PsiMethod newPsiMethod = methodBuilder.build(getElementFactory(), getOuterClass());
getOuterClass().add(newPsiMethod);
String args = StreamEx.of(argumentList.getExpressions()).map(x -> x.getText()).joining(", ", "(", ")");
String newCallExpression = newPsiMethod.getName() + args;
descriptor.newExpression.replace(getElementFactory().createExpressionFromText(newCallExpression, descriptor.newExpression));
}
public static class ConstructorDescriptor implements ItemToReplaceDescriptor {
public final PsiNewExpression newExpression;
public final PsiClass psiClass;
// null if and only if default constructor is used
@Nullable public final PsiMethod constructor;
@Nullable
public static ConstructorDescriptor createIfInaccessible(@NotNull PsiNewExpression expression) {
PsiMethod constructor = expression.resolveConstructor();
if (constructor != null) {
PsiClass containingClass = constructor.getContainingClass();
if (containingClass != null && !PsiReflectionAccessUtil.isAccessibleMember(constructor)) {
return new ConstructorDescriptor(expression, constructor, containingClass);
}
}
else {
PsiJavaCodeReferenceElement classReference = expression.getClassReference();
if (classReference instanceof PsiClass && !PsiReflectionAccessUtil.isAccessible((PsiClass)classReference)) {
return new ConstructorDescriptor(expression, null, (PsiClass)classReference);
}
}
return null;
}
public ConstructorDescriptor(@NotNull PsiNewExpression expression, @Nullable PsiMethod constructor, PsiClass psiClass) {
newExpression = expression;
this.constructor = constructor;
this.psiClass = psiClass;
}
}
}
@@ -0,0 +1,9 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
/**
* @author Vitaliy.Bibaev
*/
public enum FieldAccessType {
GET, SET
}
@@ -0,0 +1,148 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import com.intellij.refactoring.extractMethodObject.PsiReflectionAccessUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* @author Vitaliy.Bibaev
*/
public class FieldReflectionAccessor extends ReferenceReflectionAccessorBase<FieldReflectionAccessor.FieldDescriptor> {
private static final Logger LOG = Logger.getInstance(FieldReflectionAccessor.class);
public FieldReflectionAccessor(@NotNull PsiClass psiClass,
@NotNull PsiElementFactory elementFactory) {
super(psiClass, elementFactory);
}
@Nullable
@Override
protected FieldDescriptor createDescriptor(@NotNull PsiReferenceExpression expression) {
final PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField) {
final PsiField field = (PsiField)resolved;
String name = field.getName();
if (name != null && !Objects.equals(field.getContainingClass(), getOuterClass()) && needReplace(field)) {
return new FieldDescriptor(field, expression);
}
}
return null;
}
@Override
protected void grantAccess(@NotNull FieldDescriptor descriptor) {
PsiElement parent = descriptor.expression.getParent();
if (parent instanceof PsiAssignmentExpression &&
Objects.equals(descriptor.expression, ((PsiAssignmentExpression)parent).getLExpression())) {
grantUpdateAccess((PsiAssignmentExpression)parent, descriptor);
}
else {
grantReadAccess(descriptor);
}
}
private void grantReadAccess(@NotNull FieldDescriptor descriptor) {
PsiClass outerClass = getOuterClass();
PsiMethod newMethod = createPsiMethod(descriptor, FieldAccessType.GET);
if (newMethod == null) return;
outerClass.add(newMethod);
String qualifier = qualify(descriptor);
String methodCall = newMethod.getName() + "(" + (qualifier == null ? "null" : qualifier) + ", null)";
descriptor.expression.replace(getElementFactory().createExpressionFromText(methodCall, descriptor.expression));
}
private void grantUpdateAccess(@NotNull PsiAssignmentExpression assignmentExpression, @NotNull FieldDescriptor descriptor) {
PsiClass outerClass = getOuterClass();
PsiMethod newMethod = createPsiMethod(descriptor, FieldAccessType.SET);
if (newMethod == null) return;
outerClass.add(newMethod);
PsiExpression rightExpression = assignmentExpression.getRExpression();
if (rightExpression == null) {
LOG.warn("Expression representing a new field value not found");
return;
}
String newValue = rightExpression.getText();
String qualifier = qualify(descriptor);
String args = (qualifier == null ? "null" : qualifier) + ", " + newValue;
String methodCallExpression = newMethod.getName() + "(" + args + ")";
PsiExpression newMethodCallExpression = getElementFactory().createExpressionFromText(methodCallExpression, descriptor.expression);
assignmentExpression.replace(newMethodCallExpression);
}
@Nullable
private PsiMethod createPsiMethod(@NotNull FieldDescriptor descriptor, FieldAccessType accessType) {
PsiClass outerClass = getOuterClass();
PsiClass containingClass = descriptor.field.getContainingClass();
String returnType = PsiReflectionAccessUtil.getAccessibleReturnType(descriptor.field.getType());
String className = containingClass == null ? null : ClassUtil.getJVMClassName(containingClass);
String fieldName = descriptor.field.getName();
if (className == null || fieldName == null) {
LOG.warn("Code is incomplete. Class name or field name not found");
return null;
}
if (returnType == null) {
LOG.warn("Could not resolve return type");
return null;
}
String methodName = PsiReflectionAccessUtil.getUniqueMethodName(outerClass, "accessToField" + StringUtil.capitalize(fieldName));
ReflectionAccessMethodBuilder methodBuilder = new ReflectionAccessMethodBuilder(methodName);
if (FieldAccessType.GET.equals(accessType)) {
methodBuilder.accessedField(className, fieldName)
.setReturnType(returnType);
}
else {
methodBuilder.updatedField(className, fieldName)
.setReturnType("void");
}
methodBuilder.setStatic(outerClass.hasModifierProperty(PsiModifier.STATIC))
.addParameter("java.lang.Object", "object")
.addParameter("java.lang.Object", "value");
return methodBuilder.build(getElementFactory(), outerClass);
}
protected boolean needReplace(@NotNull PsiField field) {
return !PsiReflectionAccessUtil.isAccessibleMember(field);
}
@Nullable
private static String qualify(@NotNull FieldDescriptor descriptor) {
String qualifier = PsiReflectionAccessUtil.extractQualifier(descriptor.expression);
if (qualifier == null) {
if (!descriptor.field.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = descriptor.field.getContainingClass();
if (containingClass != null) {
qualifier = containingClass.getQualifiedName() + ".this";
}
}
}
return qualifier;
}
public static class FieldDescriptor implements ItemToReplaceDescriptor {
public final PsiField field;
public final PsiReferenceExpression expression;
public FieldDescriptor(@NotNull PsiField field, @NotNull PsiReferenceExpression expression) {
this.field = field;
this.expression = expression;
}
}
}
@@ -0,0 +1,74 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.psi.*;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import com.intellij.refactoring.extractMethodObject.PsiReflectionAccessUtil;
import com.intellij.refactoring.extractMethodObject.reflect.ConstructorReflectionAccessor.ConstructorDescriptor;
import com.intellij.refactoring.util.LambdaRefactoringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.refactoring.extractMethodObject.reflect.ConstructorReflectionAccessor.ConstructorDescriptor.createIfInaccessible;
/**
* @author Vitaliy.Bibaev
*/
public class MethodReferenceReflectionAccessor
extends ReferenceReflectionAccessorBase<MethodReferenceReflectionAccessor.MethodReferenceDescriptor> {
private final MethodReflectionAccessor myMethodAccessor;
private final ConstructorReflectionAccessor myConstructorReflectionAccessor;
public MethodReferenceReflectionAccessor(@NotNull PsiClass psiClass,
@NotNull PsiElementFactory elementFactory) {
super(psiClass, elementFactory);
myMethodAccessor = new MethodReflectionAccessor(psiClass, elementFactory);
myConstructorReflectionAccessor = new ConstructorReflectionAccessor(psiClass, elementFactory);
}
@Nullable
@Override
protected MethodReferenceDescriptor createDescriptor(@NotNull PsiReferenceExpression expression) {
if (expression instanceof PsiMethodReferenceExpression) {
PsiElement resolvedElement = expression.resolve();
if (resolvedElement instanceof PsiMethod) {
PsiMethod method = (PsiMethod)resolvedElement;
if (!PsiReflectionAccessUtil.isAccessibleMember(method)) {
return new MethodReferenceDescriptor(method, (PsiMethodReferenceExpression)expression);
}
}
}
return null;
}
@Override
protected void grantAccess(@NotNull MethodReferenceDescriptor descriptor) {
PsiLambdaExpression lambda = LambdaRefactoringUtil.convertMethodReferenceToLambda(descriptor.expression, false, true);
if (lambda != null) {
PsiElement lambdaBody = lambda.getBody();
if (lambdaBody instanceof PsiNewExpression) {
ConstructorDescriptor constructorDescriptor = createIfInaccessible((PsiNewExpression)lambdaBody);
if (constructorDescriptor != null) {
myConstructorReflectionAccessor.grantAccess(constructorDescriptor);
}
}
else if (lambdaBody instanceof PsiMethodCallExpression) {
PsiMethodCallExpression callExpression = (PsiMethodCallExpression)lambdaBody;
PsiMethod method = callExpression.resolveMethod();
if (method != null) {
myMethodAccessor.grantAccess(new MethodReflectionAccessor.MethodCallDescriptor(callExpression, method));
}
}
}
}
public static class MethodReferenceDescriptor implements ItemToReplaceDescriptor {
public final PsiMethod method;
public final PsiMethodReferenceExpression expression;
public MethodReferenceDescriptor(@NotNull PsiMethod method, @NotNull PsiMethodReferenceExpression expression) {
this.method = method;
this.expression = expression;
}
}
}
@@ -0,0 +1,112 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import com.intellij.refactoring.extractMethodObject.PsiReflectionAccessUtil;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author Vitaliy.Bibaev
*/
public class MethodReflectionAccessor extends ReflectionAccessorBase<MethodReflectionAccessor.MethodCallDescriptor> {
private static final Logger LOG = Logger.getInstance(MethodReflectionAccessor.class);
protected MethodReflectionAccessor(@NotNull PsiClass psiClass,
@NotNull PsiElementFactory elementFactory) {
super(psiClass, elementFactory);
}
@Override
protected List<MethodCallDescriptor> findItemsToReplace(@NotNull PsiElement element) {
List<MethodCallDescriptor> result = new ArrayList<>();
element.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression expression) {
super.visitMethodCallExpression(expression);
PsiMethod method = expression.resolveMethod();
if (method != null && !Objects.equals(method.getContainingClass(), getOuterClass()) && needReplace(method)) {
result.add(new MethodCallDescriptor(expression, method));
}
}
});
return result;
}
@Override
protected void grantAccess(@NotNull MethodCallDescriptor descriptor) {
PsiClass outerClass = getOuterClass();
String returnType = PsiReflectionAccessUtil.getAccessibleReturnType(descriptor.method.getReturnType());
PsiClass containingClass = descriptor.method.getContainingClass();
String containingClassName = containingClass == null ? null : ClassUtil.getJVMClassName(containingClass);
String name = descriptor.method.getName();
if (returnType == null) {
LOG.warn("return type of" + descriptor.method.getName() + " method is null");
return;
}
if (containingClassName == null) {
LOG.warn("containing class for method \"" + name + "\" not found");
return;
}
String newMethodName = PsiReflectionAccessUtil.getUniqueMethodName(outerClass, "call" + StringUtil.capitalize(name));
ReflectionAccessMethodBuilder methodBuilder = new ReflectionAccessMethodBuilder(newMethodName);
PsiMethod newMethod = methodBuilder.accessedMethod(containingClassName, descriptor.method.getName())
.setStatic(outerClass.hasModifierProperty(PsiModifier.STATIC))
.addParameter("java.lang.Object", "object")
.addParameters(descriptor.method.getParameterList())
.setReturnType(returnType)
.build(getElementFactory(), getOuterClass());
outerClass.add(newMethod);
String qualifier = qualify(descriptor);
String args = StreamEx.of(descriptor.callExpression.getArgumentList().getExpressions())
.map(x -> x.getText())
.prepend(qualifier == null ? "null" : qualifier)
.joining(", ", "(", ")");
String newMethodCallExpression = newMethod.getName() + args;
descriptor.callExpression.replace(getElementFactory().createExpressionFromText(newMethodCallExpression, descriptor.callExpression));
}
private static boolean needReplace(@NotNull PsiMethod method) {
return !PsiReflectionAccessUtil.isAccessibleMember(method);
}
@Nullable
private static String qualify(@NotNull MethodCallDescriptor descriptor) {
String qualifier = PsiReflectionAccessUtil.extractQualifier(descriptor.callExpression.getMethodExpression());
if (qualifier == null) {
if (!descriptor.method.hasModifierProperty(PsiModifier.STATIC)) {
PsiClass containingClass = descriptor.method.getContainingClass();
if (containingClass != null) {
qualifier = containingClass.getQualifiedName() + ".this";
}
}
}
return qualifier;
}
public static class MethodCallDescriptor implements ItemToReplaceDescriptor {
public final PsiMethodCallExpression callExpression;
public final PsiMethod method;
public MethodCallDescriptor(@NotNull PsiMethodCallExpression expression, @NotNull PsiMethod method) {
callExpression = expression;
this.method = method;
}
}
}
@@ -0,0 +1,39 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.psi.*;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
/**
* @author Vitaliy.Bibaev
*/
public abstract class ReferenceReflectionAccessorBase<T extends ItemToReplaceDescriptor> extends ReflectionAccessorBase<T> {
public ReferenceReflectionAccessorBase(@NotNull PsiClass psiClass, @NotNull PsiElementFactory elementFactory) {
super(psiClass, elementFactory);
}
@Override
protected List<T> findItemsToReplace(@NotNull PsiElement element) {
List<T> result = new ArrayList<>();
element.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
final T descriptor = createDescriptor(expression);
if (descriptor != null) {
result.add(descriptor);
}
}
});
return result;
}
@Nullable
protected abstract T createDescriptor(@NotNull PsiReferenceExpression expression);
}
@@ -0,0 +1,286 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.extractMethodObject.PsiReflectionAccessUtil;
import com.intellij.util.SmartList;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.List;
/**
* @author Vitaliy.Bibaev
*/
public class ReflectionAccessMethodBuilder {
private boolean myIsStatic = false;
private String myReturnType = "void";
private final String myName;
private MyMemberAccessor myMemberAccessor;
private final List<ParameterInfo> myParameters = new SmartList<>();
public ReflectionAccessMethodBuilder(@NotNull String name) {
myName = name;
}
public PsiMethod build(@NotNull PsiElementFactory elementFactory,
@Nullable PsiElement context) {
checkRequirements();
String parameters = StreamEx.of(myParameters).map(p -> p.type + " " + p.name).joining(", ", "(", ")");
String returnExpression =
("void".equals(myReturnType) ? "member." : "return (" + myReturnType + ")member.") + myMemberAccessor.getAccessExpression();
String methodBody = " java.lang.Class<?> klass = " + myMemberAccessor.getClassLookupExpression() + ";\n" +
" " + myMemberAccessor.getMemberType() + " member = null;\n" +
" int interfaceNumber = -1;\n" +
" Class<?>[] interfaces = null;\n" +
" while (member == null) {\n" +
" try {\n" +
" member = klass." + myMemberAccessor.getMemberLookupExpression() + ";\n" +
" } catch (java.lang.ReflectiveOperationException e) {\n" +
" if (interfaceNumber == -1) {\n" +
" interfaces = klass.getInterfaces();\n" +
" interfaceNumber = 0;\n" +
" }\n" +
" if (interfaceNumber < interfaces.length) {\n" +
" klass = interfaces[interfaceNumber];\n" +
" interfaceNumber += 1;\n" +
" } else {\n" +
" klass = klass.getSuperclass();\n" +
" if (klass == null) throw e;\n" +
" interfaceNumber = -1;\n" +
" }\n" +
" }\n" +
" }\n" +
" member.setAccessible(true);\n" +
" " + returnExpression + ";\n";
List<String> possibleExceptions = myMemberAccessor.getPossibleExceptions();
if (!possibleExceptions.isEmpty()) {
methodBody = "try {\n" +
methodBody +
"}" +
createCatchBlocks(possibleExceptions);
}
String methodText =
"public" + (myIsStatic ? " static " : " ") + myReturnType + " " + myName + parameters + " { \n" + methodBody + "}\n";
return elementFactory.createMethodFromText(methodText, context);
}
private void checkRequirements() {
}
public ReflectionAccessMethodBuilder accessedMethod(@NotNull String jvmClassName, @NotNull String methodName) {
myMemberAccessor = new MyMethodAccessor(jvmClassName, methodName);
return this;
}
public ReflectionAccessMethodBuilder accessedField(@NotNull String jvmClassName, @NotNull String fieldName) {
myMemberAccessor = new MyFieldAccessor(jvmClassName, fieldName, FieldAccessType.GET);
return this;
}
public ReflectionAccessMethodBuilder updatedField(@NotNull String jvmClassName, @NotNull String fieldName) {
myMemberAccessor = new MyFieldAccessor(jvmClassName, fieldName, FieldAccessType.SET);
return this;
}
public ReflectionAccessMethodBuilder accessedConstructor(@NotNull String jvmClassName) {
myMemberAccessor = new MyConstructorAccessor(jvmClassName);
return this;
}
public ReflectionAccessMethodBuilder setReturnType(@NotNull String returnType) {
myReturnType = returnType;
return this;
}
public ReflectionAccessMethodBuilder setStatic(boolean isStatic) {
myIsStatic = isStatic;
return this;
}
public ReflectionAccessMethodBuilder addParameter(@NotNull String jvmType, @NotNull String name) {
myParameters.add(new ParameterInfo(jvmType.replace('$', '.'), name, jvmType));
return this;
}
public ReflectionAccessMethodBuilder addParameters(@NotNull PsiParameterList parameterList) {
PsiParameter[] parameters = parameterList.getParameters();
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
String name = parameter.getName();
PsiType type = parameter.getType();
myParameters.add(new ParameterInfo(type.getCanonicalText(), name == null ? "arg" + i : name, extractJvmType(type)));
}
return this;
}
@NotNull
private static String extractJvmType(@NotNull PsiType type) {
PsiClass psiClass = PsiUtil.resolveClassInType(type);
String canonicalText = type.getCanonicalText();
String jvmName = psiClass == null ? canonicalText : ClassUtil.getJVMClassName(psiClass);
return jvmName == null ? canonicalText : jvmName;
}
private static String createCatchBlocks(@NotNull List<String> exceptions) {
return StreamEx.of(exceptions).map(x -> "catch(" + x + " e) { throw new java.lang.RuntimeException(e); }").joining("\n");
}
private static class ParameterInfo {
public final String type;
public final String name;
public final String jvmTypeName;
public ParameterInfo(@NotNull String type, @NotNull String name) {
this(type, name, type);
}
public ParameterInfo(@NotNull String type, @NotNull String name, @NotNull String jvmTypeName) {
this.type = type;
this.name = name;
this.jvmTypeName = jvmTypeName;
}
}
private interface MyMemberAccessor {
String getMemberLookupExpression();
String getClassLookupExpression();
String getAccessExpression();
String getMemberType();
List<String> getPossibleExceptions();
}
private static class MyFieldAccessor implements MyMemberAccessor {
private static final List<String> EXCEPTIONS = Collections.unmodifiableList(
Collections.singletonList("java.lang.ReflectiveOperationException"));
private final String myFieldName;
private final String myClassName;
private final FieldAccessType myAccessType;
public MyFieldAccessor(@NotNull String className,
@NotNull String fieldName,
@NotNull FieldAccessType accessType) {
myFieldName = fieldName;
myClassName = className;
myAccessType = accessType;
}
@Override
public String getClassLookupExpression() {
String classForName = PsiReflectionAccessUtil.classForName(myClassName);
// emulate applySideEffectAndReturnNull().staticField expression
return "object == null ? " + classForName + " : object.getClass()";
}
@Override
public String getMemberLookupExpression() {
return "getDeclaredField(" + StringUtil.wrapWithDoubleQuote(myFieldName) + ")";
}
@Override
public String getAccessExpression() {
return FieldAccessType.GET.equals(myAccessType) ? "get(object)" : "set(object, value)";
}
@Override
public String getMemberType() {
return "java.lang.reflect.Field";
}
@Override
public List<String> getPossibleExceptions() {
return EXCEPTIONS;
}
}
private class MyMethodAccessor implements MyMemberAccessor {
private final String myClassName;
private final String myMethodName;
public MyMethodAccessor(@NotNull String className, @NotNull String methodName) {
myClassName = className;
myMethodName = methodName;
}
@Override
public String getMemberLookupExpression() {
String args = StreamEx.of(myParameters).skip(1).map(x -> PsiReflectionAccessUtil.classForName(x.jvmTypeName))
.prepend(StringUtil.wrapWithDoubleQuote(myMethodName))
.joining(", ", "(", ")");
return "getDeclaredMethod" + args;
}
@Override
public String getClassLookupExpression() {
String classForName = PsiReflectionAccessUtil.classForName(myClassName);
// emulate applySideEffectAndReturnNull().staticMethod() expression
return "object == null ? " + classForName + " : object.getClass()";
}
@Override
public String getMemberType() {
return "java.lang.reflect.Method";
}
@Override
public List<String> getPossibleExceptions() {
return Collections.unmodifiableList(Collections.singletonList("java.lang.ReflectiveOperationException"));
}
@Override
public String getAccessExpression() {
return StreamEx.of(myParameters).map(x -> x.name).joining(", ", "invoke(", ")");
}
}
private class MyConstructorAccessor implements MyMemberAccessor {
private final String myClassName;
public MyConstructorAccessor(@NotNull String className) {
myClassName = className;
}
@Override
public String getMemberLookupExpression() {
String args = StreamEx.of(myParameters).map(x -> x.jvmTypeName).map(PsiReflectionAccessUtil::classForName).joining(", ", "(", ")");
return "getDeclaredConstructor" + args;
}
@Override
public String getClassLookupExpression() {
return PsiReflectionAccessUtil.classForName(myClassName);
}
@Override
public String getAccessExpression() {
String args = StreamEx.of(myParameters).map(x -> x.name).joining(", ", "(", ")");
return "newInstance" + args;
}
@Override
public String getMemberType() {
return "java.lang.reflect.Constructor<?>";
}
@Override
public List<String> getPossibleExceptions() {
return Collections.unmodifiableList(Collections.singletonList("java.lang.ReflectiveOperationException"
));
}
}
}
@@ -0,0 +1,12 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
/**
* @author Vitaliy.Bibaev
*/
public interface ReflectionAccessor {
void accessThroughReflection(@NotNull PsiElement element);
}
@@ -0,0 +1,55 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring.extractMethodObject.reflect;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.refactoring.extractMethodObject.ItemToReplaceDescriptor;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Grants access for inaccessible members using reflection. Adds an additional method per each expression
* with inaccessible members (method calls, field references, constructor calls, etc)
*
* @author Vitaliy.Bibaev
*/
public abstract class ReflectionAccessorBase<T extends ItemToReplaceDescriptor> implements ReflectionAccessor {
private static final Logger LOG = Logger.getInstance(ReferenceReflectionAccessorBase.class);
private final PsiClass myPsiClass;
private final PsiElementFactory myElementFactory;
protected ReflectionAccessorBase(@NotNull PsiClass psiClass, @NotNull PsiElementFactory elementFactory) {
myPsiClass = psiClass;
myElementFactory = elementFactory;
}
@Override
public void accessThroughReflection(@NotNull PsiElement element) {
List<T> toReplace = findItemsToReplace(element);
for (T item : toReplace) {
grantAccess(item);
}
List<T> remaining = findItemsToReplace(element);
if (!remaining.isEmpty()) {
LOG.warn("Some inaccessible items were not replaced");
}
}
@NotNull
protected PsiElementFactory getElementFactory() {
return myElementFactory;
}
@NotNull
protected PsiClass getOuterClass() {
return myPsiClass;
}
protected abstract List<T> findItemsToReplace(@NotNull PsiElement element);
protected abstract void grantAccess(@NotNull T descriptor);
}
@@ -46,7 +46,7 @@ public class ExtractMethodObject4DebuggerTest extends LightRefactoringTestCase {
final JavaCodeFragmentFactory fragmentFactory = JavaCodeFragmentFactory.getInstance(getProject());
final JavaCodeFragment fragment = codeBlock ? fragmentFactory.createCodeBlockCodeFragment(evaluatedText, context, false) : fragmentFactory.createExpressionCodeFragment(evaluatedText, context, null, false);
final ExtractLightMethodObjectHandler.ExtractedData extractedData =
ExtractLightMethodObjectHandler.extractLightMethodObject(getProject(), context, fragment, "test");
ExtractLightMethodObjectHandler.extractLightMethodObject(getProject(), context, fragment, "test", false);
assertNotNull(extractedData);
assertEquals(expectedCallSite, extractedData.getGeneratedCallText());
final PsiClass innerClass = extractedData.getGeneratedInnerClass();
@@ -360,6 +360,7 @@ debugger.valueTooltipAutoShowOnSelection.description=Auto show tooltip when edit
debugger.mayBringFrameToFrontOnBreakpoint=true
debugger.batch.evaluation=false
debugger.compiling.evaluator=true
debugger.compiling.evaluator.magic.accessor=true
debugger.watches.in.variables=true
debugger.auto.fetch.icons=true
debugger.close.dialog.on.navigate=true
@@ -16,7 +16,6 @@ import com.intellij.debugger.streams.ui.impl.EvaluationAwareTraceWindow;
import com.intellij.debugger.streams.wrapper.StreamChain;
import com.intellij.debugger.streams.wrapper.StreamChainBuilder;
import com.intellij.internal.statistic.UsageTrigger;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
@@ -25,17 +24,11 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiEditorUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.impl.XDebuggerManagerImpl;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -91,13 +84,6 @@ public class TraceStreamAction extends AnAction {
Extensions.getExtensions(LibrarySupportProvider.EP_NAME);
final PsiElement element = session == null ? null : myPositionResolver.getNearestElementToBreakpoint(session);
if (element != null && isJdkAtLeast9(session.getProject(), element)) {
XDebuggerManagerImpl.NOTIFICATION_GROUP
.createNotification("This action does not work with JDK 9 yet", MessageType.WARNING)
.notify(session.getProject());
return;
}
if (element != null) {
final List<StreamChainWithLibrary> chains = mySupportedLibraries.stream()
.filter(library -> library.languageId.equals(element.getLanguage().getID()))
@@ -177,18 +163,6 @@ public class TraceStreamAction extends AnAction {
return project == null ? null : XDebuggerManager.getInstance(project).getCurrentSession();
}
private static boolean isJdkAtLeast9(@NotNull Project project, @NotNull PsiElement element) {
if (element.getLanguage().is(JavaLanguage.INSTANCE)) {
final Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
if (sdk != null) {
final JavaSdkVersion javaVersion = JavaSdk.getInstance().getVersion(sdk);
if (javaVersion != null) return javaVersion.isAtLeast(JavaSdkVersion.JDK_1_9);
}
}
return false;
}
private static class MyStreamChainChooser extends ElementChooserImpl<StreamChainOption> {
MyStreamChainChooser(@NotNull Editor editor) {
super(editor);
@@ -42,8 +42,18 @@ public abstract class TraceExecutionTestCase extends DebuggerTestCase {
private final DebuggerPositionResolver myPositionResolver = new DebuggerPositionResolverImpl();
@Override
protected OutputChecker initOutputChecker() {
return new OutputChecker(getTestAppPath(), getAppOutputPath());
protected final OutputChecker initOutputChecker() {
return new OutputChecker(getTestAppPath(), getAppOutputPath()) {
@Override
protected String replaceAdditionalInOutput(String str) {
return TraceExecutionTestCase.this.replaceAdditionalInOutput(super.replaceAdditionalInOutput(str));
}
};
}
@NotNull
protected String replaceAdditionalInOutput(@NotNull String str) {
return str;
}
protected LibrarySupportProvider getLibrarySupportProvider() {
@@ -1,10 +1,18 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.exec;
import org.jetbrains.annotations.NotNull;
/**
* @author Vitaliy.Bibaev
*/
public class AccessibilityFailedTest extends FailEvaluationTestCase {
@NotNull
@Override
protected String replaceAdditionalInOutput(@NotNull String str) {
// stack traces in jdk 9 include module name. The following code removes module name from the stack trace.
return super.replaceAdditionalInOutput(str).replace("at java.base/", "at ");
}
/**
* Now, evaluation of such test case is not supported. MagicAccessorImpl cannot be parent for a subclass of the class "Super"
@@ -1,7 +1,6 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.exec
import com.intellij.debugger.impl.OutputChecker
import com.intellij.debugger.streams.test.TraceExecutionTestCase
import com.intellij.execution.configurations.JavaParameters
import com.intellij.openapi.application.ApplicationManager
@@ -23,12 +22,9 @@ abstract class LibraryTraceExecutionTestCase(private val jarName: String) : Trac
}
}
override fun initOutputChecker(): OutputChecker {
return object : OutputChecker(testAppPath, appOutputPath) {
override fun replaceAdditionalInOutput(str: String): String {
return str.replaceFirst("$libraryDirectory/$jarName", "!LIBRARY_JAR!")
}
}
override fun replaceAdditionalInOutput(str: String): String {
return super.replaceAdditionalInOutput(str)
.replaceFirst("$libraryDirectory/$jarName", "!LIBRARY_JAR!")
}
override fun createJavaParameters(mainClass: String?): JavaParameters {
@@ -7,13 +7,13 @@ package com.intellij.debugger.streams.exec.streamex
class ConcatenateOperationsTest : StreamExTestCase() {
override val packageName: String = "concatenate"
fun testAppendToEmpty() = doStreamExWithResultTest()
fun testAppendNone() = doStreamExWithResultTest()
fun testAppendOne() = doStreamExWithResultTest()
fun testAppendMany() = doStreamExWithResultTest()
fun testAppendToEmpty() = doStreamExVoidTest()
fun testAppendNone() = doStreamExVoidTest()
fun testAppendOne() = doStreamExVoidTest()
fun testAppendMany() = doStreamExVoidTest()
fun testPrependToEmpty() = doStreamExWithResultTest()
fun testPrependNone() = doStreamExWithResultTest()
fun testPrependOne() = doStreamExWithResultTest()
fun testPrependMany() = doStreamExWithResultTest()
fun testPrependToEmpty() = doStreamExVoidTest()
fun testPrependNone() = doStreamExVoidTest()
fun testPrependOne() = doStreamExVoidTest()
fun testPrependMany() = doStreamExVoidTest()
}
@@ -10,15 +10,15 @@ class MappingOperationsTest : StreamExTestCase() {
fun testElements() = doStreamExWithResultTest()
fun testMapToEntry() = doStreamExWithResultTest()
fun testMapKeys() = doStreamExWithResultTest()
fun testMapToKey() = doStreamExWithResultTest()
fun testMapValues() = doStreamExWithResultTest()
fun testMapToValue() = doStreamExWithResultTest()
fun testMapKeys() = doStreamExVoidTest()
fun testMapToKey() = doStreamExVoidTest()
fun testMapValues() = doStreamExVoidTest()
fun testMapToValue() = doStreamExVoidTest()
fun testMapKeyValue() = doStreamExWithResultTest()
fun testInvert() = doStreamExWithResultTest()
fun testInvert() = doStreamExVoidTest()
fun testKeys() = doStreamExWithResultTest()
fun testKeys() = doStreamExVoidTest()
fun testValues() = doStreamExWithResultTest()
fun testJoin() = doStreamExVoidTest()
@@ -30,5 +30,5 @@ class MappingOperationsTest : StreamExTestCase() {
fun testMapFirstOrElse() = doStreamExWithResultTest()
fun testMapLastOrElse() = doStreamExWithResultTest()
fun testWithFirst() = doStreamExWithResultTest()
fun testWithFirst() = doStreamExVoidTest()
}
@@ -13,13 +13,13 @@ class MiscIntermediateOperationsTest : StreamExTestCase() {
fun testSkipOrdered() = doStreamExWithResultTest()
fun testParallel() = doStreamExWithResultTest()
fun testParallel() = doStreamExVoidTest()
fun testZipWithSameSizes() = doStreamExWithResultTest()
fun testZipWithLesser() = doStreamExWithResultTest()
fun testZipWithGreater() = doStreamExWithResultTest()
fun testZipWithSameSizes() = doStreamExVoidTest()
fun testZipWithLesser() = doStreamExVoidTest()
fun testZipWithGreater() = doStreamExVoidTest()
fun testPrefix() = doStreamExVoidTest()
fun testPrefixKeys() = doStreamExWithResultTest()
fun testPrefixValues() = doStreamExWithResultTest()
fun testPrefixKeys() = doStreamExVoidTest()
fun testPrefixValues() = doStreamExVoidTest()
}
@@ -9,12 +9,26 @@ import com.intellij.debugger.streams.lib.impl.StreamExLibrarySupportProvider
* @author Vitaliy.Bibaev
*/
abstract class StreamExTestCase : LibraryTraceExecutionTestCase("streamex-0.6.5.jar") {
abstract protected val packageName: String
private companion object {
const val STREAM_EX_REFLECTION_WARNING_MESSAGE =
"WARNING: An illegal reflective access operation has occurred\n" +
"WARNING: Illegal reflective access by one.util.streamex.StreamExInternals (file:/C:/Projects/IDEA/community/plugins/" +
"stream-debugger/lib/streamex-0.6.5.jar) to field java.util.stream.AbstractPipeline.sourceSpliterator\n" +
"WARNING: Please consider reporting this to the maintainers of one.util.streamex.StreamExInternals\n" +
"WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\n" +
"WARNING: All illegal access operations will be denied in a future release\n"
}
protected abstract val packageName: String
override fun getLibrarySupportProvider(): LibrarySupportProvider {
return StreamExLibrarySupportProvider()
}
override fun replaceAdditionalInOutput(str: String): String {
return super.replaceAdditionalInOutput(str).replace(STREAM_EX_REFLECTION_WARNING_MESSAGE, "")
}
private val className: String
get() = packageName + "." + getTestName(false)
@@ -4,13 +4,13 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
Map.java:6
Stream.of(1, 2, 3)
.map(x -> x * x)
.count()
.toArray()
map
before: 1,3,5
after: 2,4,6
count
toArray
before: 2,4,6
after: nothing
after: 7,8,9
mappings for map
direct:
1 -> 2
@@ -20,13 +20,15 @@ mappings for map
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for toArray
direct:
2 -> nothing
4 -> nothing
6 -> nothing
2 -> 7
4 -> 8
6 -> 9
reverse:
empty
2 <- 7
4 <- 8
6 <- 9
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -3,16 +3,17 @@ LineBreakpoint created at Nulls.java:6
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Nulls.java:6
Stream.of(null, null)
.count()
count
.toArray()
toArray
before: 1,2
after: nothing
mappings for count
after: 3,4
mappings for toArray
direct:
1 -> nothing
2 -> nothing
1 -> 3
2 -> 4
reverse:
empty
1 <- 3
2 <- 4
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -4,13 +4,13 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
Peek.java:6
Stream.of(1, 2, 3)
.peek(x -> {})
.count()
.toArray()
peek
before: 1,3,5
after: 2,4,6
count
toArray
before: 2,4,6
after: nothing
after: 7,8,9
mappings for peek
direct:
1 -> 2
@@ -20,13 +20,15 @@ mappings for peek
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for toArray
direct:
2 -> nothing
4 -> nothing
6 -> nothing
2 -> 7
4 -> 8
6 -> 9
reverse:
empty
2 <- 7
4 <- 8
6 <- 9
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -2,14 +2,14 @@ LineBreakpoint created at PrimitiveResultLong.java:6
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!RT_JAR! PrimitiveResultLong
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
PrimitiveResultLong.java:6
IntStream.of(1, 2)
.count()
LongStream.of(1, 2)
.sum()
Result type:long
value = 2
count
value = 3
sum
before: 1,2
after: nothing
mappings for count
mappings for sum
direct:
1 -> nothing
2 -> nothing
@@ -3,6 +3,6 @@ import java.util.stream.Stream;
public class Map {
public static void main(String[] args) {
// Breakpoint!
final long res = Stream.of(1, 2, 3).map(x -> x * x).count();
Stream.of(1, 2, 3).map(x -> x * x).toArray();
}
}
@@ -3,6 +3,6 @@ import java.util.stream.Stream;
public class Nulls {
public static void main(String[] args) {
// Breakpoint!
Stream.of(null, null).count();
Stream.of(null, null).toArray();
}
}
@@ -3,6 +3,6 @@ import java.util.stream.Stream;
public class Peek {
public static void main(String[] args) {
// Breakpoint!
final long res = Stream.of(1, 2, 3).peek(x -> {}).count();
Stream.of(1, 2, 3).peek(x -> {}).toArray();
}
}
@@ -1,8 +1,8 @@
import java.util.stream.IntStream;
import java.util.stream.LongStream;
public class PrimitiveResultLong {
public static void main(String[] args) {
// Breakpoint!
long res = IntStream.of(1, 2).count();
long res = LongStream.of(1, 2).sum();
}
}
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
AppendMany.java:10
StreamEx.of(1, 2)
.append(Stream.of(3, 4, 5))
.count()
.forEach(x -> {})
append
before: 1,3
after: 2,4,5,6,7
count
forEach
before: 2,4,5,6,7
after: nothing
mappings for append
@@ -21,7 +21,7 @@ mappings for append
nothing <- 5
nothing <- 6
nothing <- 7
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -33,4 +33,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
5
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
AppendNone.java:8
StreamEx.of(1, 2)
.append()
.count()
.forEach(x -> {})
append
before: 1,3
after: 2,4
count
forEach
before: 2,4
after: nothing
mappings for append
@@ -18,7 +18,7 @@ mappings for append
reverse:
1 <- 2
3 <- 4
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -27,4 +27,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
2
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
AppendOne.java:8
StreamEx.of(1, 2)
.append(3)
.count()
.forEach(x -> {})
append
before: 1,3
after: 2,4,5
count
forEach
before: 2,4,5
after: nothing
mappings for append
@@ -19,7 +19,7 @@ mappings for append
1 <- 2
3 <- 4
nothing <- 5
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -29,4 +29,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
AppendToEmpty.java:8
StreamEx.empty()
.append(1)
.count()
.forEach(x -> {})
append
before: nothing
after: 1
count
forEach
before: 1
after: nothing
mappings for append
@@ -16,7 +16,7 @@ mappings for append
empty
reverse:
nothing <- 1
mappings for count
mappings for forEach
direct:
1 -> nothing
reverse:
@@ -24,4 +24,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
1
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
Invert.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.invert()
.count()
.forEach(x -> {})
invert
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for invert
@@ -20,7 +20,7 @@ mappings for invert
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
Keys.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.keys()
.count()
.forEach(x -> {})
keys
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for keys
@@ -20,7 +20,7 @@ mappings for keys
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
MapKeys.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapKeys(x -> x - 1)
.count()
.forEach(x -> {})
mapKeys
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for mapKeys
@@ -20,7 +20,7 @@ mappings for mapKeys
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,13 +4,13 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
MapToEntry.java:8
StreamEx.of(1, 2, 3)
.mapToEntry(x -> x * x)
.count()
.toArray()
mapToEntry
before: 1,3,5
after: 2,4,6
count
toArray
before: 2,4,6
after: nothing
after: 7,8,9
mappings for mapToEntry
direct:
1 -> 2
@@ -20,13 +20,15 @@ mappings for mapToEntry
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for toArray
direct:
2 -> nothing
4 -> nothing
6 -> nothing
2 -> 7
4 -> 8
6 -> 9
reverse:
empty
2 <- 7
4 <- 8
6 <- 9
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
MapToKey.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapToKey((k, v) -> k + v)
.count()
.forEach(x -> {})
mapToKey
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for mapToKey
@@ -20,7 +20,7 @@ mappings for mapToKey
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
MapToValue.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapToValue((k, v) -> k + v)
.count()
.forEach(x -> {})
mapToValue
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for mapToValue
@@ -20,7 +20,7 @@ mappings for mapToValue
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
MapValues.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapValues(x -> 0)
.count()
.forEach(x -> {})
mapValues
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for mapValues
@@ -20,7 +20,7 @@ mappings for mapValues
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
Parallel.java:11
StreamEx.of(1, 2, 3)
.parallel((ForkJoinPool) Executors.newWorkStealingPool())
.count()
.forEach(x -> {})
parallel
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for parallel
@@ -20,7 +20,7 @@ mappings for parallel
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrefixKeys.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.prefixKeys((l, r) -> l + r)
.count()
.forEach(x -> {})
prefixKeys
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for prefixKeys
@@ -20,7 +20,7 @@ mappings for prefixKeys
nothing <- 2
nothing <- 4
nothing <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrefixValues.java:8
EntryStream.of(1, 1, 2, 4, 3, 9)
.prefixValues((l, r) -> l + r)
.count()
.forEach(x -> {})
prefixValues
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for prefixValues
@@ -20,7 +20,7 @@ mappings for prefixValues
nothing <- 2
nothing <- 4
nothing <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrependMany.java:10
StreamEx.of(1, 2)
.prepend(Stream.of(3, 4, 5))
.count()
.forEach(x -> {})
prepend
before: 4,6
after: 1,2,3,5,7
count
forEach
before: 1,2,3,5,7
after: nothing
mappings for prepend
@@ -21,7 +21,7 @@ mappings for prepend
nothing <- 3
4 <- 5
6 <- 7
mappings for count
mappings for forEach
direct:
1 -> nothing
2 -> nothing
@@ -33,4 +33,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
5
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrependNone.java:8
StreamEx.of(1, 2)
.prepend()
.count()
.forEach(x -> {})
prepend
before: 1,3
after: 2,4
count
forEach
before: 2,4
after: nothing
mappings for prepend
@@ -18,7 +18,7 @@ mappings for prepend
reverse:
1 <- 2
3 <- 4
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -27,4 +27,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
2
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrependOne.java:8
StreamEx.of(1, 2)
.prepend(3)
.count()
.forEach(x -> {})
prepend
before: 2,4
after: 1,3,5
count
forEach
before: 1,3,5
after: nothing
mappings for prepend
@@ -19,7 +19,7 @@ mappings for prepend
nothing <- 1
2 <- 3
4 <- 5
mappings for count
mappings for forEach
direct:
1 -> nothing
3 -> nothing
@@ -29,4 +29,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
PrependToEmpty.java:8
StreamEx.empty()
.prepend(1)
.count()
.forEach(x -> {})
prepend
before: nothing
after: 1
count
forEach
before: 1
after: nothing
mappings for prepend
@@ -16,7 +16,7 @@ mappings for prepend
empty
reverse:
nothing <- 1
mappings for count
mappings for forEach
direct:
1 -> nothing
reverse:
@@ -24,4 +24,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
1
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
WithFirst.java:8
StreamEx.of(10., 2., 3.)
.withFirst((first, other) -> first * other)
.count()
.forEach(x -> {})
withFirst
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for withFirst
@@ -20,7 +20,7 @@ mappings for withFirst
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
ZipWithGreater.java:10
StreamEx.of(1, 2, 3)
.zipWith(Stream.of(1, 3, 9, 16, 25))
.count()
.forEach(x -> {})
zipWith
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for zipWith
@@ -20,7 +20,7 @@ mappings for zipWith
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
ZipWithLesser.java:10
StreamEx.of(1, 2, 3, 4, 5)
.zipWith(Stream.of(1, 3, 9))
.count()
.forEach(x -> {})
zipWith
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for zipWith
@@ -20,7 +20,7 @@ mappings for zipWith
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -4,11 +4,11 @@ Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socke
ZipWithSameSizes.java:10
StreamEx.of(1, 2, 3)
.zipWith(Stream.of(1, 3, 9))
.count()
.forEach(x -> {})
zipWith
before: 1,3,5
after: 2,4,6
count
forEach
before: 2,4,6
after: nothing
mappings for zipWith
@@ -20,7 +20,7 @@ mappings for zipWith
1 <- 2
3 <- 4
5 <- 6
mappings for count
mappings for forEach
direct:
2 -> nothing
4 -> nothing
@@ -30,4 +30,3 @@ mappings for count
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
3
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
public class AppendMany {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).append(Stream.of(3, 4, 5)).count();
System.out.println(count);
StreamEx.of(1, 2).append(Stream.of(3, 4, 5)).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class AppendNone {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).append().count();
System.out.println(count);
StreamEx.of(1, 2).append().forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class AppendOne {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).append(3).count();
System.out.println(count);
StreamEx.of(1, 2).append(3).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class AppendToEmpty {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.empty().append(1).count();
System.out.println(count);
StreamEx.empty().append(1).forEach(x -> {});
}
}
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
public class PrependMany {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).prepend(Stream.of(3, 4, 5)).count();
System.out.println(count);
StreamEx.of(1, 2).prepend(Stream.of(3, 4, 5)).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class PrependNone {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).prepend().count();
System.out.println(count);
StreamEx.of(1, 2).prepend().forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class PrependOne {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2).prepend(3).count();
System.out.println(count);
StreamEx.of(1, 2).prepend(3).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class PrependToEmpty {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.empty().prepend(1).count();
System.out.println(count);
StreamEx.empty().prepend(1).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.EntryStream;
public class Invert {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9).invert().count();
System.out.println(count);
EntryStream.of(1, 1, 2, 4, 3, 9).invert().forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.EntryStream;
public class Keys {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9).keys().count();
System.out.println(count);
EntryStream.of(1, 1, 2, 4, 3, 9).keys().forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.EntryStream;
public class MapKeys {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9).mapKeys(x -> x - 1).count();
System.out.println(count);
EntryStream.of(1, 1, 2, 4, 3, 9).mapKeys(x -> x - 1).forEach(x -> {});
}
}
@@ -5,7 +5,7 @@ import one.util.streamex.StreamEx;
public class MapToEntry {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2, 3).mapToEntry(x -> x * x).count();
System.out.println(count);
Object[] result = StreamEx.of(1, 2, 3).mapToEntry(x -> x * x).toArray();
System.out.println(result.length);
}
}
@@ -5,9 +5,8 @@ import one.util.streamex.EntryStream;
public class MapToKey {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9)
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapToKey((k, v) -> k + v)
.count();
System.out.println(count);
.forEach(x -> {});
}
}
@@ -5,9 +5,8 @@ import one.util.streamex.EntryStream;
public class MapToValue {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9)
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapToValue((k, v) -> k + v)
.count();
System.out.println(count);
.forEach(x -> {});
}
}
@@ -5,9 +5,8 @@ import one.util.streamex.EntryStream;
public class MapValues {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9)
EntryStream.of(1, 1, 2, 4, 3, 9)
.mapValues(x -> 0)
.count();
System.out.println(count);
.forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.StreamEx;
public class WithFirst {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(10., 2., 3.).withFirst((first, other) -> first * other).count();
System.out.println(count);
StreamEx.of(10., 2., 3.).withFirst((first, other) -> first * other).forEach(x -> {});
}
}
@@ -8,7 +8,6 @@ import java.util.concurrent.ForkJoinPool;
public class Parallel {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2, 3).parallel((ForkJoinPool) Executors.newWorkStealingPool()).count();
System.out.println(count);
StreamEx.of(1, 2, 3).parallel((ForkJoinPool) Executors.newWorkStealingPool()).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.EntryStream;
public class PrefixKeys {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9).prefixKeys((l, r) -> l + r).count();
System.out.println(count);
EntryStream.of(1, 1, 2, 4, 3, 9).prefixKeys((l, r) -> l + r).forEach(x -> {});
}
}
@@ -5,7 +5,6 @@ import one.util.streamex.EntryStream;
public class PrefixValues {
public static void main(String[] args) {
// Breakpoint!
final long count = EntryStream.of(1, 1, 2, 4, 3, 9).prefixValues((l, r) -> l + r).count();
System.out.println(count);
EntryStream.of(1, 1, 2, 4, 3, 9).prefixValues((l, r) -> l + r).forEach(x -> {});
}
}
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
public class ZipWithGreater {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2, 3).zipWith(Stream.of(1, 3, 9, 16, 25)).count();
System.out.println(count);
StreamEx.of(1, 2, 3).zipWith(Stream.of(1, 3, 9, 16, 25)).forEach(x -> {});
}
}
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
public class ZipWithLesser {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2, 3, 4, 5).zipWith(Stream.of(1, 3, 9)).count();
System.out.println(count);
StreamEx.of(1, 2, 3, 4, 5).zipWith(Stream.of(1, 3, 9)).forEach(x -> {});
}
}
@@ -7,7 +7,6 @@ import java.util.stream.Stream;
public class ZipWithSameSizes {
public static void main(String[] args) {
// Breakpoint!
final long count = StreamEx.of(1, 2, 3).zipWith(Stream.of(1, 3, 9)).count();
System.out.println(count);
StreamEx.of(1, 2, 3).zipWith(Stream.of(1, 3, 9)).forEach(x -> {});
}
}