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 @@ -211,21 +211,29 @@ private void collectFieldsRecursive(TypeElement element, List<VariableElement> f

private void generateProvider(TypeElement commandElement) throws IOException {
String qualifiedName = commandElement.getQualifiedName().toString();
String packageName = "";
int lastDot = qualifiedName.lastIndexOf('.');
if (lastDot > 0) {
packageName = qualifiedName.substring(0, lastDot);
String packageName = elementUtils.getPackageOf(commandElement).getQualifiedName().toString();

// For inner classes (e.g., Config.Set), we need:
// - typeRefName: "Config.Set" for use in generated code type references
// - metadataClassName: "Config_Set_AeshMetadata" to avoid clashing with enclosing class
String typeRefName;
String metadataClassName;
if (packageName.isEmpty()) {
typeRefName = qualifiedName;
metadataClassName = qualifiedName.replace('.', '_') + "_AeshMetadata";
} else {
// Strip package prefix to get e.g. "Config.Set" for inner classes or "Batch" for top-level
typeRefName = qualifiedName.substring(packageName.length() + 1);
metadataClassName = typeRefName.replace('.', '_') + "_AeshMetadata";
}
String simpleName = commandElement.getSimpleName().toString();
String metadataClassName = simpleName + "_AeshMetadata";
String fullMetadataName = packageName.isEmpty() ? metadataClassName : packageName + "." + metadataClassName;

boolean isGroup = commandElement.getAnnotation(GroupCommandDefinition.class) != null;

List<VariableElement> fields = collectFields(commandElement);

String code = CodeGenerator.generate(
packageName, simpleName, metadataClassName, qualifiedName,
packageName, typeRefName, metadataClassName, qualifiedName,
commandElement, fields, isGroup, elementUtils, typeUtils);

JavaFileObject sourceFile = filer.createSourceFile(fullMetadataName, commandElement);
Expand Down
103 changes: 87 additions & 16 deletions aesh-processor/src/main/java/org/aesh/processor/CodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ static String generate(
}

// Imports
sb.append("import java.util.Arrays;\n\n");
sb.append("import java.util.Arrays;\n");
sb.append("import java.util.function.BiConsumer;\n");
sb.append("import java.util.function.Consumer;\n\n");
sb.append("import org.aesh.command.Command;\n");
sb.append("import org.aesh.command.impl.internal.ProcessedCommand;\n");
sb.append("import org.aesh.command.impl.internal.ProcessedCommandBuilder;\n");
Expand Down Expand Up @@ -123,7 +125,7 @@ static String generate(
sb.append(" @Override\n");
sb.append(" public ProcessedCommand buildProcessedCommand(").append(simpleName).append(" instance)");
sb.append(" throws CommandLineParserException {\n");
generateBuildProcessedCommand(sb, commandElement, fields, isGroup, elementUtils, typeUtils);
generateBuildProcessedCommand(sb, simpleName, commandElement, fields, isGroup, elementUtils, typeUtils);
sb.append(" }\n");

// End class
Expand Down Expand Up @@ -172,11 +174,12 @@ private static List<String> getGroupCommandClassNames(TypeElement element, Eleme
return classNames;
}

private static void generateBuildProcessedCommand(StringBuilder sb, TypeElement commandElement,
private static void generateBuildProcessedCommand(StringBuilder sb, String simpleName, TypeElement commandElement,
List<VariableElement> fields, boolean isGroup,
Elements elementUtils, Types typeUtils) {

sb.append(" ProcessedCommand processedCommand = ProcessedCommandBuilder.builder()\n");
sb.append(
" ProcessedCommand processedCommand = ((ProcessedCommandBuilder) ProcessedCommandBuilder.builder())\n");

if (isGroup) {
GroupCommandDefinition gcd = commandElement.getAnnotation(GroupCommandDefinition.class);
Expand Down Expand Up @@ -209,7 +212,7 @@ private static void generateBuildProcessedCommand(StringBuilder sb, TypeElement

// Process fields
for (VariableElement field : fields) {
generateFieldProcessing(sb, field, elementUtils, typeUtils);
generateFieldProcessing(sb, simpleName, field, elementUtils, typeUtils);
}

sb.append(" return processedCommand;\n");
Expand Down Expand Up @@ -245,7 +248,7 @@ private static void generateCommandActivator(StringBuilder sb, TypeElement eleme
}
}

private static void generateFieldProcessing(StringBuilder sb, VariableElement field,
private static void generateFieldProcessing(StringBuilder sb, String simpleName, VariableElement field,
Elements elementUtils, Types typeUtils) {
Option o = field.getAnnotation(Option.class);
OptionList ol = field.getAnnotation(OptionList.class);
Expand All @@ -254,19 +257,19 @@ private static void generateFieldProcessing(StringBuilder sb, VariableElement fi
Argument arg = field.getAnnotation(Argument.class);

if (o != null) {
generateOption(sb, field, o, elementUtils, typeUtils);
generateOption(sb, simpleName, field, o, elementUtils, typeUtils);
} else if (ol != null) {
generateOptionList(sb, field, ol, elementUtils, typeUtils);
generateOptionList(sb, simpleName, field, ol, elementUtils, typeUtils);
} else if (og != null) {
generateOptionGroup(sb, field, og, elementUtils, typeUtils);
generateOptionGroup(sb, simpleName, field, og, elementUtils, typeUtils);
} else if (args != null) {
generateArguments(sb, field, args, elementUtils, typeUtils);
generateArguments(sb, simpleName, field, args, elementUtils, typeUtils);
} else if (arg != null) {
generateArgument(sb, field, arg, elementUtils, typeUtils);
generateArgument(sb, simpleName, field, arg, elementUtils, typeUtils);
}
}

private static void generateOption(StringBuilder sb, VariableElement field, Option o,
private static void generateOption(StringBuilder sb, String simpleName, VariableElement field, Option o,
Elements elementUtils, Types typeUtils) {
String fieldName = field.getSimpleName().toString();
String fieldType = getBoxedTypeName(field.asType(), typeUtils);
Expand Down Expand Up @@ -308,10 +311,12 @@ private static void generateOption(StringBuilder sb, VariableElement field, Opti
sb.append(" .inherited(").append(o.inherited()).append(")\n");
sb.append(" .descriptionUrl(").append(stringLiteral(o.descriptionUrl())).append(")\n");
sb.append(" .url(").append(o.url()).append(")\n");
generateFieldSetter(sb, simpleName, field, typeUtils);
generateFieldResetter(sb, simpleName, field, typeUtils);
sb.append(" .build());\n\n");
}

private static void generateOptionList(StringBuilder sb, VariableElement field, OptionList ol,
private static void generateOptionList(StringBuilder sb, String simpleName, VariableElement field, OptionList ol,
Elements elementUtils, Types typeUtils) {
String fieldName = field.getSimpleName().toString();
String elementType = getGenericTypeArgument(field.asType(), 0, typeUtils);
Expand All @@ -337,10 +342,12 @@ private static void generateOptionList(StringBuilder sb, VariableElement field,
generateOptionActivator(sb, field, "activator", elementUtils);
generateOptionRenderer(sb, field, "renderer", elementUtils);
generateOptionParser(sb, field, "parser", elementUtils);
generateFieldSetter(sb, simpleName, field, typeUtils);
generateFieldResetter(sb, simpleName, field, typeUtils);
sb.append(" .build());\n\n");
}

private static void generateOptionGroup(StringBuilder sb, VariableElement field, OptionGroup og,
private static void generateOptionGroup(StringBuilder sb, String simpleName, VariableElement field, OptionGroup og,
Elements elementUtils, Types typeUtils) {
String fieldName = field.getSimpleName().toString();
// For Map<K,V>, extract V (index 1)
Expand All @@ -366,10 +373,12 @@ private static void generateOptionGroup(StringBuilder sb, VariableElement field,
generateOptionActivator(sb, field, "activator", elementUtils);
generateOptionRenderer(sb, field, "renderer", elementUtils);
generateOptionParser(sb, field, "parser", elementUtils);
generateFieldSetter(sb, simpleName, field, typeUtils);
generateFieldResetter(sb, simpleName, field, typeUtils);
sb.append(" .build());\n\n");
}

private static void generateArguments(StringBuilder sb, VariableElement field, Arguments a,
private static void generateArguments(StringBuilder sb, String simpleName, VariableElement field, Arguments a,
Elements elementUtils, Types typeUtils) {
String fieldName = field.getSimpleName().toString();
String elementType = getGenericTypeArgument(field.asType(), 0, typeUtils);
Expand All @@ -394,10 +403,12 @@ private static void generateArguments(StringBuilder sb, VariableElement field, A
generateOptionActivator(sb, field, "activator", elementUtils);
generateOptionParser(sb, field, "parser", elementUtils);
sb.append(" .url(").append(a.url()).append(")\n");
generateFieldSetter(sb, simpleName, field, typeUtils);
generateFieldResetter(sb, simpleName, field, typeUtils);
sb.append(" .build());\n\n");
}

private static void generateArgument(StringBuilder sb, VariableElement field, Argument arg,
private static void generateArgument(StringBuilder sb, String simpleName, VariableElement field, Argument arg,
Elements elementUtils, Types typeUtils) {
String fieldName = field.getSimpleName().toString();
String fieldType = getBoxedTypeName(field.asType(), typeUtils);
Expand Down Expand Up @@ -425,6 +436,8 @@ private static void generateArgument(StringBuilder sb, VariableElement field, Ar
sb.append(" .overrideRequired(").append(arg.overrideRequired()).append(")\n");
sb.append(" .inherited(").append(arg.inherited()).append(")\n");
sb.append(" .url(").append(arg.url()).append(")\n");
generateFieldSetter(sb, simpleName, field, typeUtils);
generateFieldResetter(sb, simpleName, field, typeUtils);
sb.append(" .build());\n\n");
}

Expand Down Expand Up @@ -652,6 +665,64 @@ private static String selectorLiteral(org.aesh.selector.SelectorType selectorTyp
return "org.aesh.selector.SelectorType." + selectorType.name();
}

private static boolean isAccessibleField(VariableElement field) {
java.util.Set<javax.lang.model.element.Modifier> modifiers = field.getModifiers();
return !modifiers.contains(javax.lang.model.element.Modifier.PRIVATE);
}

private static void generateFieldSetter(StringBuilder sb, String commandSimpleName, VariableElement field,
Types typeUtils) {
if (!isAccessibleField(field))
return;
String fieldName = field.getSimpleName().toString();
String fieldType = field.asType().toString();

sb.append(" .fieldSetter((inst, val) -> ((").append(commandSimpleName).append(") inst).")
.append(fieldName).append(" = (").append(fieldType).append(") val)\n");
}

private static void generateFieldResetter(StringBuilder sb, String commandSimpleName, VariableElement field,
Types typeUtils) {
if (!isAccessibleField(field))
return;
String fieldName = field.getSimpleName().toString();
TypeMirror fieldType = field.asType();

sb.append(" .fieldResetter(inst -> ((").append(commandSimpleName).append(") inst).")
.append(fieldName).append(" = ");

switch (fieldType.getKind()) {
case BOOLEAN:
sb.append("false");
break;
case BYTE:
sb.append("(byte) 0");
break;
case SHORT:
sb.append("(short) 0");
break;
case INT:
sb.append("0");
break;
case LONG:
sb.append("0L");
break;
case FLOAT:
sb.append("0.0f");
break;
case DOUBLE:
sb.append("0.0d");
break;
case CHAR:
sb.append("'\\u0000'");
break;
default:
sb.append("null");
break;
}
sb.append(")\n");
}

private static String escapeJavaString(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,26 +135,36 @@ public List<String> getAliases() {
}

public void addOption(ProcessedOption opt) throws OptionParserException {
this.options.add(new ProcessedOption(verifyThatNamesAreUnique(opt.shortName(), opt.name()), opt.name(),
ProcessedOption copy = new ProcessedOption(verifyThatNamesAreUnique(opt.shortName(), opt.name()), opt.name(),
opt.description(), opt.getArgument(), opt.isRequired(), opt.getValueSeparator(), opt.askIfNotSet(),
opt.acceptNameWithoutDashes(), opt.selectorType(),
opt.getDefaultValues(), opt.type(), opt.getFieldName(), opt.getOptionType(), opt.converter(),
opt.completer(), opt.validator(), opt.activator(), opt.getRenderer(), opt.parser(), opt.doOverrideRequired(),
opt.isNegatable(), opt.getNegationPrefix(), opt.isInherited(),
opt.getDescriptionUrl(), opt.isUrl()));
opt.getDescriptionUrl(), opt.isUrl());
if (opt.getFieldSetter() != null)
copy.setFieldSetter(opt.getFieldSetter());
if (opt.getFieldResetter() != null)
copy.setFieldResetter(opt.getFieldResetter());
this.options.add(copy);

options.get(options.size() - 1).setParent(this);
}

private void setOptions(List<ProcessedOption> options) throws OptionParserException {
for (ProcessedOption opt : options) {
this.options.add(new ProcessedOption(verifyThatNamesAreUnique(opt.shortName(), opt.name()), opt.name(),
ProcessedOption copy = new ProcessedOption(verifyThatNamesAreUnique(opt.shortName(), opt.name()), opt.name(),
opt.description(), opt.getArgument(), opt.isRequired(), opt.getValueSeparator(), opt.askIfNotSet(),
opt.acceptNameWithoutDashes(), opt.selectorType(),
opt.getDefaultValues(), opt.type(), opt.getFieldName(), opt.getOptionType(),
opt.converter(), opt.completer(), opt.validator(), opt.activator(), opt.getRenderer(),
opt.parser(), opt.doOverrideRequired(), opt.isNegatable(), opt.getNegationPrefix(), opt.isInherited(),
opt.getDescriptionUrl(), opt.isUrl()));
opt.getDescriptionUrl(), opt.isUrl());
if (opt.getFieldSetter() != null)
copy.setFieldSetter(opt.getFieldSetter());
if (opt.getFieldResetter() != null)
copy.setFieldResetter(opt.getFieldResetter());
this.options.add(copy);

this.options.get(this.options.size() - 1).setParent(this);
}
Expand Down
Loading