Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,37 @@ public interface LeetcodeInvoker {
* in the invoking process.
*/
Object invoke(Object object, Object... args) throws Throwable;

/**
* Returns a string describing this {@code Constructor},
* including type parameters. The string is formatted as the
* constructor access modifiers, if any, followed by an
* angle-bracketed comma separated list of the constructor's type
* parameters, if any, followed by the fully-qualified name of the
* declaring class, followed by a parenthesized, comma-separated
* list of the constructor's generic formal parameter types.
* <p>
* If this constructor was declared to take a variable number of
* arguments, instead of denoting the last parameter as
* "<tt><i>Type</i>[]</tt>", it is denoted as
* "<tt><i>Type</i>...</tt>".
* <p>
* A space is used to separate access modifiers from one another
* and from the type parameters or return type. If there are no
* type parameters, the type parameter list is elided; if the type
* parameter list is present, a space separates the list from the
* class name. If the constructor is declared to throw
* exceptions, the parameter list is followed by a space, followed
* by the word "{@code throws}" followed by a
* comma-separated list of the thrown exception types.
*
* <p>The only possible modifiers for constructors are the access
* modifiers {@code public}, {@code protected} or
* {@code private}. Only one of these may appear, or none if the
* constructor has default (package) access.
*
* @return a string describing this {@code Constructor},
* include type parameters
*/
String toGenericString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,18 @@

package io.github.jidcoo.opto.lcdb.enhancer.core;

import io.github.jidcoo.opto.lcdb.enhancer.core.parser.InputParserProcessor;
import io.github.jidcoo.opto.lcdb.enhancer.LeetcodeJavaDebugEnhancer;
import io.github.jidcoo.opto.lcdb.enhancer.core.pipeline.LeetcodeJavaDebugEnhancerPipelineProcessor;
import io.github.jidcoo.opto.lcdb.enhancer.utils.EnhancerLogUtil;
import io.github.jidcoo.opto.lcdb.enhancer.utils.ReflectUtil;
import io.github.jidcoo.opto.lcdb.enhancer.LeetcodeJavaDebugEnhancer;
import io.github.jidcoo.opto.lcdb.enhancer.base.InputProvider;
import io.github.jidcoo.opto.lcdb.enhancer.base.OutputConsumer;
import io.github.jidcoo.opto.lcdb.enhancer.core.executor.LeetcodeExecutorFactory;
import io.github.jidcoo.opto.lcdb.enhancer.core.executor.LeetcodeExecutorProcessor;
import io.github.jidcoo.opto.lcdb.enhancer.core.io.IOFactory;
import io.github.jidcoo.opto.lcdb.enhancer.core.parser.InputParserFactory;
import io.github.jidcoo.opto.lcdb.enhancer.core.printer.OutputPrinterFactory;
import io.github.jidcoo.opto.lcdb.enhancer.core.printer.OutputPrinterProcessor;

/**
* <p>LeetcodeJavaDebugEnhanceProcessor is a primary enhancer.</p>
* <p>All features of the {@link LeetcodeJavaDebugEnhancer} will
* be controlled and dominated by this processor. </p>
*
* <p>In version 1.0.1 and later, the control and support for
* all features of {@link LeetcodeJavaDebugEnhancer} have been
* moved from {@link LeetcodeJavaDebugEnhanceProcessor} to
* {@link LeetcodeJavaDebugEnhancerPipelineProcessor}.</p>
*
* <p>By the way, today is a so bad day for me. Because I
* still need coding on my day off. Can you give me
Expand All @@ -42,7 +37,7 @@
* @author Jidcoo
* @since 1.0
*/
public class LeetcodeJavaDebugEnhanceProcessor {
public final class LeetcodeJavaDebugEnhanceProcessor {

/**
* <p>Do leetcode debugging enhance process with an <tt>AT</tt> class.</p>
Expand All @@ -56,46 +51,15 @@ public static void process(Class<? extends LeetcodeJavaDebugEnhancer> AT) throws
// Setup EnhancerLog log level.
EnhancerLogUtil.setLogLevel(enhancer.getEnhancerLogLevel());

EnhancerLogUtil.logI("Starting do debugging enhance at (AT) class: %s", AT.getSimpleName());
// Create a LeetcodeExecutor from the enhancer.
Object leetcodeExecutor = LeetcodeExecutorFactory.getLeetcodeExecutor(enhancer);
// Create an OutputPrinter from the enhancer.
Object outputPrinter = OutputPrinterFactory.getOutputPrinter(enhancer);
// Create a InputParser from the enhancer.
Object inputParser = InputParserFactory.getInputParser(enhancer);
EnhancerLogUtil.logI("Start leetcode debugging enhancer at (AT) class: %s", AT.getSimpleName());

try (
// Get or create a InputProvider from the enhancer.
InputProvider inputProvider = IOFactory.getInputProvider(enhancer);
// Get or create OutputConsumer from the enhancer.
OutputConsumer outputConsumer = IOFactory.getOutputConsumer(enhancer)

) {
// Now we can happily run the io loop to perform leetcode debugging enhancements.
EnhancerLogUtil.logI("Running leetcode debugging enhancer at (AT) class: %s", AT.getSimpleName());
while (true) {
// Provide the next string input from the InputProvider.
String input = inputProvider.provideNextInput();
// We need to break this loop when the input indicates end.
if (inputProvider.isEnd(input)) {
break;
}
// Parse the string input to input object.
Object inputObject = InputParserProcessor.process(inputParser, leetcodeExecutor, input);
// Execute leetcode target and get the output object.
Object outputObject = LeetcodeExecutorProcessor.process(leetcodeExecutor, inputObject);
// Print the output object.
String output = OutputPrinterProcessor.process(outputPrinter, leetcodeExecutor, outputObject);
// Consume the next output string to the OutputConsumer.
outputConsumer.consumeNextOutput(output);
}
}
// Do process debugging enhancement pipeline with AT instance. (Since 1.0.1)
LeetcodeJavaDebugEnhancerPipelineProcessor.process(enhancer);

// Now, the enhancement work has ended here. It's time to say goodbye.
// Wishing all programmers around the world the true joy of life in Leetcode.
// May you be so powerful that you don't need debugging and have no bugs.
// Good luck!!!.
EnhancerLogUtil.logI("Stopped leetcode debugging enhancer at (AT) class: %s", AT.getSimpleName());
EnhancerLogUtil.logI("Stop leetcode debugging enhancer at (AT) class: %s", AT.getSimpleName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.util.Arrays;

/**
* <p>ConstructorLeetcodeInvoker is an invoker
Expand All @@ -42,6 +43,11 @@ final class ConstructorLeetcodeInvoker implements LeetcodeInvoker {
*/
private final Integer id;

/**
* Friendly matching mode flag.
*/
private boolean matchingFriendly;

/**
* Create a ConstructorLeetcodeInvoker instance.
*
Expand All @@ -54,6 +60,8 @@ final class ConstructorLeetcodeInvoker implements LeetcodeInvoker {
// Make accessible.
this.constructor.setAccessible(true);
this.id = id;
// Friendly-Matching-Mode is closed by default.
this.matchingFriendly = false;
}

/**
Expand All @@ -73,7 +81,11 @@ public Integer getId() {
*/
@Override
public int getParameterCount() {
return this.constructor.getParameterCount();
int parameterCount = this.constructor.getParameterCount();
if (parameterCount > 0 && matchingFriendly) {
return parameterCount - 1;
}
return parameterCount;
}

/**
Expand All @@ -83,7 +95,11 @@ public int getParameterCount() {
*/
@Override
public String getInvokerName() {
return this.constructor.getName();
String name = this.constructor.getName();
if (name.contains("$") && matchingFriendly) {
return name.substring(name.lastIndexOf('$') + 1);
}
return name;
}

/**
Expand All @@ -93,7 +109,11 @@ public String getInvokerName() {
*/
@Override
public Class<?>[] getParameterTypes() {
return this.constructor.getParameterTypes();
Class<?>[] parameterTypes = this.constructor.getParameterTypes();
if (parameterTypes.length > 0 && matchingFriendly) {
return Arrays.stream(parameterTypes).skip(1).toArray(Class[]::new);
}
return parameterTypes;
}

/**
Expand All @@ -103,7 +123,11 @@ public Class<?>[] getParameterTypes() {
*/
@Override
public Parameter[] getParameters() {
return this.constructor.getParameters();
Parameter[] parameters = this.constructor.getParameters();
if (parameters.length > 0 && matchingFriendly) {
return Arrays.stream(parameters).skip(1).toArray(Parameter[]::new);
}
return parameters;
}

/**
Expand All @@ -127,6 +151,45 @@ public Class<?> getReturnType() {
*/
@Override
public Object invoke(Object object, Object... args) throws Throwable {
return this.constructor.newInstance(object, args);
Object[] initArgsArray = new Object[args.length + 1];
initArgsArray[0] = object;
System.arraycopy(args, 0, initArgsArray, 1, args.length);
return this.constructor.newInstance(initArgsArray);
}

/**
* Returns a string describing this {@code Constructor},
* including type parameters. The string is formatted as the
* constructor access modifiers, if any, followed by an
* angle-bracketed comma separated list of the constructor's type
* parameters, if any, followed by the fully-qualified name of the
* declaring class, followed by a parenthesized, comma-separated
* list of the constructor's generic formal parameter types.
* <p>
* If this constructor was declared to take a variable number of
* arguments, instead of denoting the last parameter as
* "<tt><i>Type</i>[]</tt>", it is denoted as
* "<tt><i>Type</i>...</tt>".
* <p>
* A space is used to separate access modifiers from one another
* and from the type parameters or return type. If there are no
* type parameters, the type parameter list is elided; if the type
* parameter list is present, a space separates the list from the
* class name. If the constructor is declared to throw
* exceptions, the parameter list is followed by a space, followed
* by the word "{@code throws}" followed by a
* comma-separated list of the thrown exception types.
*
* <p>The only possible modifiers for constructors are the access
* modifiers {@code public}, {@code protected} or
* {@code private}. Only one of these may appear, or none if the
* constructor has default (package) access.
*
* @return a string describing this {@code Constructor},
* include type parameters
*/
@Override
public String toGenericString() {
return this.constructor.toGenericString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
package io.github.jidcoo.opto.lcdb.enhancer.core.executor;

import io.github.jidcoo.opto.lcdb.enhancer.base.EnhancerException;
import io.github.jidcoo.opto.lcdb.enhancer.base.LeetcodeInvoker;
import io.github.jidcoo.opto.lcdb.enhancer.utils.AssertUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
* <p>LeetcodeExecutor is an executor used to
Expand All @@ -45,30 +48,38 @@ final class LeetcodeExecutor {

/**
* The leetcode executor.
*
* @since 1.0.1
*/
private final Method executor;
private LeetcodeInvoker executor;

/**
* The leetcode invoker.
* The candidate leetcode invokers.
*
* @since 1.0.1
*/
private Method invoker;
private final List<LeetcodeInvoker> candidateInvokers;

/**
* The leetcode invoker response type.
*/
private Class invokerResponseType;
private Class<?> invokerResponseType;

/**
* Create a LeetcodeExecutor instance.
*
* @param instance the leetcode instance.
* @param executor the leetcode executor.
* @since 1.0.1
*/
LeetcodeExecutor(Object instance, Method executor) {
LeetcodeExecutor(Object instance, LeetcodeInvoker executor) {
this.instance = instance;
this.executor = executor;
// Set executor as default leetcode invoker.
this.invoker = executor;
this.candidateInvokers = new ArrayList<>();
if (Objects.nonNull(executor)) {
// Add executor to candidate leetcode invokers list.
this.candidateInvokers.add(executor);
}
}

/**
Expand All @@ -81,10 +92,9 @@ final class LeetcodeExecutor {
* or invoker error.
*/
Object execute(Object input) {
AssertUtil.nonNull(invoker, "The leetcode execute invoker cannot be null.");
AssertUtil.nonNull(executor, "The leetcode executor cannot be null.");
try {
invoker.setAccessible(true);
return invoker.invoke(instance, (Object[]) input);
return executor.invoke(instance, (Object[]) input);
} catch (InvocationTargetException exception) {
throw new EnhancerException(exception.getCause());
} catch (Throwable exception) {
Expand All @@ -106,16 +116,27 @@ Object getInstance() {
*
* @return the leetcode executor.
*/
Method getExecutor() {
LeetcodeInvoker getExecutor() {
return executor;
}

/**
* Get the leetcode invoker.
* Set the leetcode executor.
*
* @param executor the leetcode executor.
* @since 1.0.1
*/
void setExecutor(LeetcodeInvoker executor) {
this.executor = executor;
}

/**
* Get the candidate leetcode invokers list.
*
* @return the leetcode invoker.
* @return the candidate leetcode invokers list.
* @since 1.0.1
*/
Method getInvoker() {
return invoker;
List<LeetcodeInvoker> getCandidateInvokers() {
return this.candidateInvokers;
}
}
Loading