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
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ targetCompatibility = JavaVersion.VERSION_11
repositories {
mavenCentral()
}

test {
useJUnitPlatform()
}
def encoding = 'UTF-8'
def vendor = 'TigerSoft'

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
34 changes: 18 additions & 16 deletions src/main/java/pl/tigersoft/intellij/faker/FakerNotifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,26 @@

public class FakerNotifier {

public static final String NOTIFICATION_GROUP = "FakerEvents";
public static final String NOTIFICATION_GROUP = "FakerEvents";
private FakerNotifier() {
}

public static void info(Project project, String content) {
notify(content, NotificationType.INFORMATION, project);
}
public static void info(Project project, String content) {
notify(content, NotificationType.INFORMATION, project);
}

public static void warn(Project project, String content) {
notify(content, NotificationType.WARNING, project);
}
public static void warn(Project project, String content) {
notify(content, NotificationType.WARNING, project);
}

public static void error(Project project, String content) {
notify(content, NotificationType.ERROR, project);
}
public static void error(Project project, String content) {
notify(content, NotificationType.ERROR, project);
}

public static void notify(String content, NotificationType notificationType, Project project) {
NotificationGroupManager.getInstance()
.getNotificationGroup(NOTIFICATION_GROUP)
.createNotification("Faker", content, notificationType)
.notify(project);
}
public static void notify(String content, NotificationType notificationType, Project project) {
NotificationGroupManager.getInstance()
.getNotificationGroup(NOTIFICATION_GROUP)
.createNotification("Faker", content, notificationType)
.notify(project);
}
}
175 changes: 72 additions & 103 deletions src/main/java/pl/tigersoft/intellij/faker/actions/FakerActionGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,129 +5,98 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

import net.datafaker.Faker;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import pl.tigersoft.intellij.faker.FakerNotifier;
import pl.tigersoft.intellij.faker.actions.utils.MethodWrapper;
import pl.tigersoft.intellij.faker.actions.utils.ReflectionUtils;

public class FakerActionGroup extends ActionGroup {

private static final Logger log = Logger.getInstance(FakerActionGroup.class);

private static final List<String> excludedClasses = Arrays.asList("Options", "Number", "CreditCardType", "Faker");

private static final List<String> excludedMethods = Arrays.asList("wait", "notify", "notifyAll", "toString", "locality");

private static final Comparator<Method> methodComparator = (method1, method2) ->
method1.getName().compareToIgnoreCase(method2.getName());
@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent eventIgnore) {
Faker faker = new Faker();
return ReflectionUtils.createCategoryList(Faker.class)
.map(method -> UiHelper.buildRootActionGroup(method, faker))
.toArray(AnAction[]::new);
}

@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent event) {
Faker faker = new Faker();
return Arrays.stream(faker.getClass().getMethods())
.filter(categoryFilter())
.sorted(methodComparator)
.map(method -> buildActionGroup(method, faker))
.toArray(AnAction[]::new);
}

@NotNull
private ActionGroup buildActionGroup(Method method, Faker faker) {
return new ActionGroup(prettyName(method.getName()), true) {

@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent event) {
return invokeMethod(method, faker, event)
.map(object -> Arrays.stream(object.getClass().getDeclaredMethods())
.filter(subcategoryFilter())
.sorted(methodComparator)
.map(method -> getAction(method, object))
.toArray(AnAction[]::new))
.orElse(new AnAction[0]);
}
};
}

@NotNull
private AnAction getAction(Method method, Object object) {
return new AnAction(prettyName(method.getName())) {

@Override
public void actionPerformed(@NotNull AnActionEvent event) {
invokeMethod(method, object, event).ifPresent(fake -> insertFake(event, fake));
}

@Override
public void update(@NotNull final AnActionEvent event) {
final Project project = event.getProject();
final Editor editor = event.getData(CommonDataKeys.EDITOR);

event.getPresentation().setEnabledAndVisible(project != null && editor != null);
private static class UiHelper {
@NotNull
private static ActionGroup buildRootActionGroup(Method method, Faker faker) {
var wrapper = new MethodWrapper(method);
return new ActionGroup(wrapper.prettyName, true) {

@NotNull
@Override
public AnAction[] getChildren(@Nullable AnActionEvent event) {
return wrapper.invokeMethodOnEvent( faker, event)
.map(subcategory -> ReflectionUtils.createSubcategoryList(subcategory.getClass())
.map(method -> buildAction(method, subcategory))
.toArray(AnAction[]::new))
.orElse(new AnAction[0]);
}
};
}

@NotNull
private static AnAction buildAction(Method method, Object object) {
var wrapper = new MethodWrapper(method);
return new AnAction(wrapper.prettyName) {

@Override
public void actionPerformed(@NotNull AnActionEvent event) {
wrapper.invokeMethodOnEvent(object, event).ifPresent(
fakeText -> new UiUpdater(event).insertFakeText(fakeText));
}

@Override
public void update(@NotNull final AnActionEvent event) {
event.getPresentation().setEnabledAndVisible(isVisible(event));
}

private boolean isVisible(AnActionEvent event) {
final Project project = event.getProject();
final Editor editor = event.getData(CommonDataKeys.EDITOR);
return project != null && editor != null;
}
};
}
private static class UiUpdater {
private final AnActionEvent event;
UiUpdater(AnActionEvent event) {
this.event = event;
}
};
}

private void insertFake(AnActionEvent event, Object fake) {
String text = String.valueOf(fake);
final Editor editor = event.getRequiredData(CommonDataKeys.EDITOR);
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
final Document document = editor.getDocument();

Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
int start = primaryCaret.getSelectionStart();
int end = primaryCaret.getSelectionEnd();

WriteCommandAction.runWriteCommandAction(project, () -> document.replaceString(start, end, text));
primaryCaret.moveToOffset(start + text.length());
primaryCaret.removeSelection();
void insertFakeText(Object fakeTextInput) {
String text = String.valueOf(fakeTextInput);
final Editor editor = event.getRequiredData(CommonDataKeys.EDITOR);
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
final Document document = editor.getDocument();

Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
int start = primaryCaret.getSelectionStart();
int end = primaryCaret.getSelectionEnd();

WriteCommandAction.runWriteCommandAction(project, () -> document.replaceString(start, end, text));
primaryCaret.moveToOffset(start + text.length());
primaryCaret.removeSelection();
}
}
}

private static Optional<Object> invokeMethod(Method method, Object object, AnActionEvent event) {
if (method == null || object == null) {
return Optional.empty();
}
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
try {
return Optional.ofNullable(method.invoke(object));
} catch (IllegalAccessException | InvocationTargetException e) {
String msg = String.format("Unable to invoke method '%s()' on object '%s'",
method.getName(), object.getClass().getSimpleName());
log.error(msg);
FakerNotifier.error(project, msg);
}
return Optional.empty();
}

private static String prettyName(String name) {
return StringUtils
.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(name), StringUtils.SPACE));
}

private static Predicate<Method> categoryFilter() {
return subcategoryFilter()
.and(method -> !excludedClasses.contains(method.getReturnType().getSimpleName()))
.and(method -> !excludedMethods.contains(method.getName()));
}

private static Predicate<Method> subcategoryFilter() {
return method -> method.getParameters().length == 0
&& Modifier.isPublic(method.getModifiers());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package pl.tigersoft.intellij.faker.actions.utils;

import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import org.apache.commons.lang3.StringUtils;
import pl.tigersoft.intellij.faker.FakerNotifier;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Optional;

public class MethodWrapper {
private static final Logger log = Logger.getInstance(MethodWrapper.class);
private final Method method;
public final String prettyName;

public MethodWrapper(Method method) {
this.method = method;
prettyName = createPrettyName(method.getName());
}

static String createPrettyName(String name) {
return StringUtils
.capitalize(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(name), StringUtils.SPACE));
}

public Optional<Object> invokeMethodOnEvent(Object object, AnActionEvent event) {
return invokeMethod(method, object, event);
}

private static Optional<Object> invokeMethod(Method method, Object object, AnActionEvent event) {
if (method == null || object == null) {
return Optional.empty();
}
final Project project = event.getRequiredData(CommonDataKeys.PROJECT);
try {
return Optional.ofNullable(method.invoke(object));
} catch (IllegalAccessException | InvocationTargetException e) {
String msg = String.format("Unable to invoke method '%s()' on object '%s'",
method.getName(), object.getClass().getSimpleName());
log.error(msg);
FakerNotifier.error(project, msg);
}
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package pl.tigersoft.intellij.faker.actions.utils;


import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class ReflectionUtils {
private static final List<String> excludedClasses = Arrays.asList("Options", "Number", "CreditCardType", "Faker");

private static final List<String> excludedMethods = Arrays.asList("wait", "notify", "notifyAll", "toString", "locality");

public static final Comparator<Method> methodComparator = (method1, method2) ->
method1.getName().compareToIgnoreCase(method2.getName());

private ReflectionUtils() {

}

public static Stream<Method> createCategoryList(Class<?> clazz) {
Method[] methods = clazz.getMethods();
return Arrays.stream(methods)
.filter(ReflectionUtils.categoryFilter())
.sorted(methodComparator);
}


private static Predicate<Method> categoryFilter() {
return subcategoryFilter()
.and(method -> !excludedClasses.contains(method.getReturnType().getSimpleName()))
.and(method -> !excludedMethods.contains(method.getName()));
}

private static Predicate<Method> subcategoryFilter() {
return method -> method.getParameters().length == 0
&& Modifier.isPublic(method.getModifiers());
}

public static Stream<Method> createSubcategoryList(Class<?> clazz) {
return Arrays.stream(clazz.getDeclaredMethods())
.filter(ReflectionUtils.subcategoryFilter())
.sorted(ReflectionUtils.methodComparator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pl.tigersoft.intellij.faker.actions.utils;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;

class MethodWrapperTest {

@ParameterizedTest
@MethodSource("provideInputAndOutput")
void validatePrettyName(String input, String output) {
String prettyName1 = MethodWrapper.createPrettyName(input);

assertThat(prettyName1).isEqualTo(output);
}

private static Stream<Arguments> provideInputAndOutput() {
return Stream.of(
Arguments.of("battlefield1", "Battlefield 1"),
Arguments.of("backToTheFuture", "Back To The Future")
);
}
}
Loading