Skip to content

Commit

Permalink
[#850] Add MixinInfo class to keep track of the @Mixin-annotated el…
Browse files Browse the repository at this point in the history
…ement
  • Loading branch information
remkop committed Nov 1, 2019
1 parent 207958a commit da63bd4
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package picocli.codegen.annotation.processing;

import picocli.CommandLine;
import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.IFactory;
Expand Down Expand Up @@ -438,19 +437,16 @@ private void buildMixin(Element element, RoundEnvironment roundEnv, Context cont
logger.fine("Built mixin: " + mixin + " from " + element);
if (EnumSet.of(ElementKind.FIELD, ElementKind.PARAMETER).contains(element.getKind())) {
VariableElement variableElement = (VariableElement) element;
String name = element.getAnnotation(Mixin.class).name();
if (name.length() == 0) {
name = variableElement.getSimpleName().toString();
}
Element targetType = element.getEnclosingElement();
CommandSpec mixee = buildCommand(targetType, context, roundEnv);
Map<CommandSpec, String> mixinInfo = context.mixinInfoMap.get(mixee);
if (mixinInfo == null) {
mixinInfo = new IdentityHashMap<CommandSpec, String>(2);
context.mixinInfoMap.put(mixee, mixinInfo);
MixinInfo mixinInfo = new MixinInfo(variableElement, mixin);

CommandSpec mixee = buildCommand(mixinInfo.enclosingElement(), context, roundEnv);
Set<MixinInfo> mixinInfos = context.mixinInfoMap.get(mixee);
if (mixinInfos == null) {
mixinInfos = new HashSet<MixinInfo>(2);
context.mixinInfoMap.put(mixee, mixinInfos);
}
mixinInfo.put(mixin, name);
logger.fine("Mixin name=" + name + ", target command=" + mixee.userObject());
mixinInfos.add(mixinInfo);
logger.fine("Mixin name=" + mixinInfo.mixinName() + ", target command=" + mixee.userObject());
}
}

Expand Down Expand Up @@ -791,7 +787,7 @@ static class Context {
Map<Element, OptionSpec.Builder> options = new LinkedHashMap<Element, OptionSpec.Builder>();
Map<Element, PositionalParamSpec.Builder> parameters = new LinkedHashMap<Element, PositionalParamSpec.Builder>();
Map<Element, ArgGroupSpec.Builder> argGroupElements = new LinkedHashMap<Element, ArgGroupSpec.Builder>();
Map<CommandSpec, Map<CommandSpec, String>> mixinInfoMap = new IdentityHashMap<CommandSpec, Map<CommandSpec, String>>();
Map<CommandSpec, Set<MixinInfo>> mixinInfoMap = new IdentityHashMap<CommandSpec, Set<MixinInfo>>();
Map<Element, IAnnotatedElement> parentCommandElements = new LinkedHashMap<Element, IAnnotatedElement>();
Map<Element, IAnnotatedElement> specElements = new LinkedHashMap<Element, IAnnotatedElement>();
Map<Element, IAnnotatedElement> unmatchedElements = new LinkedHashMap<Element, IAnnotatedElement>();
Expand All @@ -804,10 +800,10 @@ private void connectModel(AbstractCommandSpecProcessor proc) {
logger.fine(String.format("%s has CommandSpec[name=%s]", cmd.getKey(), cmd.getValue().name()));
}
logger.fine("Known mixins...");
for (Map.Entry<CommandSpec, Map<CommandSpec, String>> mixinEntry : mixinInfoMap.entrySet()) {
for (Map.Entry<CommandSpec, Set<MixinInfo>> mixinEntry : mixinInfoMap.entrySet()) {
logger.fine(String.format("mixins for %s:", mixinEntry.getKey().userObject()));
for (Map.Entry<CommandSpec, String> mixinInfo : mixinEntry.getValue().entrySet()) {
logger.fine(String.format("mixin name=%s userObj=%s:", mixinInfo.getValue(), mixinInfo.getKey().userObject()));
for (MixinInfo mixinInfo : mixinEntry.getValue()) {
logger.fine(String.format("mixin name=%s userObj=%s:", mixinInfo.mixinName(), mixinInfo.mixin().userObject()));
}
}

Expand Down Expand Up @@ -873,11 +869,11 @@ private void connectModel(AbstractCommandSpecProcessor proc) {
proc.error(entry.getKey(), "@Unmatched must be enclosed in a @Command, but was %s: %s", entry.getKey().getEnclosingElement(), entry.getKey().getEnclosingElement().getSimpleName());
}
}
for (Map.Entry<CommandSpec, Map<CommandSpec, String>> mixinEntry : mixinInfoMap.entrySet()) {
for (Map.Entry<CommandSpec, Set<MixinInfo>> mixinEntry : mixinInfoMap.entrySet()) {
CommandSpec mixee = mixinEntry.getKey();
for (Map.Entry<CommandSpec, String> mixinInfo : mixinEntry.getValue().entrySet()) {
logger.fine(String.format("Adding mixin name=%s to %s", mixinInfo.getValue(), mixee.name()));
mixee.addMixin(mixinInfo.getValue(), mixinInfo.getKey());
for (MixinInfo mixinInfo : mixinEntry.getValue()) {
logger.fine(String.format("Adding mixin name=%s to %s", mixinInfo.mixinName(), mixee.name()));
mixee.addMixin(mixinInfo.mixinName(), mixinInfo.mixin()/*, mixinInfo.annotatedElement()*/);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package picocli.codegen.annotation.processing;

import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Model.IAnnotatedElement;

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.VariableElement;
import java.util.EnumSet;
import java.util.List;

/**
* Holds information on the `@Mixin`-annotated program element.
*/
class MixinInfo {
private final String mixinName;
private final IAnnotatedElement annotatedElement;
private final VariableElement element;
private final CommandSpec mixin;

public MixinInfo(VariableElement element, CommandSpec mixin) {
this.element = element;
this.mixin = mixin;

String name = element.getAnnotation(CommandLine.Mixin.class).name();
if (name.length() == 0) {
name = element.getSimpleName().toString();
}
this.mixinName = name;
Element targetType = element.getEnclosingElement();
int position = -1;
if (EnumSet.of(ElementKind.METHOD, ElementKind.CONSTRUCTOR).contains(targetType.getKind())) {
List<? extends VariableElement> parameters = ((ExecutableElement) targetType).getParameters();
for (int i = 0; i < parameters.size(); i++) {
if (parameters.get(i).getSimpleName().contentEquals(element.getSimpleName())) {
position = i;
break;
}
}
}
annotatedElement = new TypedMember(element, position);
}

public Element enclosingElement() {
return element.getEnclosingElement();
}

public String mixinName() {
return mixinName;
}

public CommandSpec mixin() {
return mixin;
}

public IAnnotatedElement annotatedElement() {
return annotatedElement;
}

public int hashCode() {
int result = 17;
result += result * 37 + mixinName.hashCode();
result += result * 37 + element.getSimpleName().hashCode();
result += result * 37 + mixin.userObject().toString().hashCode();
return result;
}

public boolean equals(Object object) {
if (object == this) {
return true;
}
if (!(object instanceof MixinInfo)) {
return false;
}
MixinInfo other = (MixinInfo) object;
if (!mixinName.equals(other.mixinName)) {
return false;
}
if (!element.getSimpleName().equals(other.element.getSimpleName())) {
return false;
}
if (!mixin.userObject().toString().equals(other.mixin.userObject().toString())) {
return false;
}
return true;
}
}

0 comments on commit da63bd4

Please sign in to comment.