Skip to content

Commit

Permalink
Add support of package/protected access
Browse files Browse the repository at this point in the history
  • Loading branch information
alexengrig committed Sep 5, 2021
1 parent 91a4bb4 commit c484281
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 56 deletions.
23 changes: 23 additions & 0 deletions src/main/java/dev/alexengrig/metter/FieldChecker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2020-2021 Alexengrig Dev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dev.alexengrig.metter;

import dev.alexengrig.metter.element.descriptor.FieldDescriptor;

public interface FieldChecker {
boolean isTarget(FieldDescriptor fieldDescriptor);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public class MethodDescriptor extends ElementDescriptor<ExecutableElement> {
* @since 0.1.1
*/
protected transient Boolean isNotPrivate;
protected transient Boolean isPublic;

/**
* Constructs with an executable element.
Expand Down Expand Up @@ -103,11 +104,18 @@ public TypeDescriptor getParent() {
*/
public boolean isNotPrivate() {
if (isNotPrivate == null) {
isNotPrivate = element.getModifiers().stream().noneMatch(Modifier.PRIVATE::equals);
isNotPrivate = !element.getModifiers().contains(Modifier.PRIVATE);
}
return isNotPrivate;
}

public boolean isPublic() {
if (isPublic == null) {
isPublic = element.getModifiers().contains(Modifier.PUBLIC);
}
return isPublic;
}

/**
* Checks if method has no parameters.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public String getPackage() {
if (lastIndexOfDot > 0) {
return qualifiedName.substring(0, lastIndexOfDot);
}
throw new IllegalStateException("No package");
return "";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package dev.alexengrig.metter.processor;

import dev.alexengrig.metter.FieldChecker;
import dev.alexengrig.metter.element.descriptor.ElementDescriptor;
import dev.alexengrig.metter.element.descriptor.FieldDescriptor;
import dev.alexengrig.metter.element.descriptor.MethodDescriptor;
Expand All @@ -32,6 +33,7 @@
import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
Expand Down Expand Up @@ -167,8 +169,9 @@ protected JavaFileObject createSourceFile(String qualifiedClassName) {
protected Map<String, String> createField2MethodMap(D descriptor) {
Map<String, String> field2Method = new HashMap<>();
Set<FieldDescriptor> fields = getFields(descriptor);
FieldChecker fieldChecker = getFieldChecker(descriptor);
for (FieldDescriptor field : fields) {
if (isTargetField(field)) {
if (fieldChecker.isTarget(field)) {
field2Method.put(field.getName(), getMethod(field));
}
}
Expand Down Expand Up @@ -202,14 +205,7 @@ protected Map<String, String> createField2MethodMap(D descriptor) {
*/
protected abstract Set<String> getExcludedFields(D descriptor);

/**
* Checks if a field descriptor is target field.
*
* @param field descriptor
* @return {@code field} is target field.
* @since 0.1.0
*/
protected abstract boolean isTargetField(FieldDescriptor field);
protected abstract FieldChecker getFieldChecker(D descriptor);

/**
* Returns a method for a field descriptor.
Expand All @@ -228,14 +224,20 @@ protected Map<String, String> createField2MethodMap(D descriptor) {
* @since 0.1.1
*/
protected boolean hasGetterMethod(FieldDescriptor field) {
String getter = getGetterMethod(field);
return getGetter(field).isPresent();
}

protected Optional<MethodDescriptor> getGetter(FieldDescriptor field) {
String getter = getGetterMethodName(field);
TypeDescriptor type = field.getParent();
if (type.hasMethod(getter)) {
Set<MethodDescriptor> methods = type.getMethods(getter);
return methods.stream().anyMatch(method -> method.isNotPrivate() && method.hasNoParameters()
&& field.getTypeName().equals(method.getTypeName()));
if (!type.hasMethod(getter)) {
return Optional.empty();
}
return false;
Set<MethodDescriptor> methods = type.getMethods(getter);
return methods.stream()
.filter(method -> method.isNotPrivate() && method.hasNoParameters()
&& field.getTypeName().equals(method.getTypeName()))
.findFirst();
}

/**
Expand All @@ -245,7 +247,7 @@ protected boolean hasGetterMethod(FieldDescriptor field) {
* @return getter-method for {@code field}
* @since 0.1.1
*/
protected String getGetterMethod(FieldDescriptor field) {
protected String getGetterMethodName(FieldDescriptor field) {
String methodNamePrefix = "boolean".equals(field.getTypeName()) ? "is" : "get";
String name = field.getName();
return methodNamePrefix + Strings.capitalize(name);
Expand All @@ -260,7 +262,7 @@ protected String getGetterMethod(FieldDescriptor field) {
* @since 0.1.1
*/
protected boolean hasSetterMethod(FieldDescriptor field) {
String methodName = getSetterMethod(field);
String methodName = getSetterMethodName(field);
TypeDescriptor type = field.getParent();
if (type.hasMethod(methodName)) {
Set<MethodDescriptor> methods = type.getMethods(methodName);
Expand All @@ -270,14 +272,27 @@ protected boolean hasSetterMethod(FieldDescriptor field) {
return false;
}

protected Optional<MethodDescriptor> getSetter(FieldDescriptor field) {
String methodName = getSetterMethodName(field);
TypeDescriptor type = field.getParent();
if (!type.hasMethod(methodName)) {
return Optional.empty();
}
Set<MethodDescriptor> methods = type.getMethods(methodName);
return methods.stream()
.filter(method -> method.isNotPrivate() && "void".equals(method.getTypeName())
&& method.hasOnlyOneParameter(field.getTypeName()))
.findFirst();
}

/**
* Returns a setter-method for a field descriptor.
*
* @param field descriptor
* @return setter-method for {@code field}
* @since 0.1.1
*/
protected String getSetterMethod(FieldDescriptor field) {
protected String getSetterMethodName(FieldDescriptor field) {
String name = field.getName();
return "set" + Strings.capitalize(name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package dev.alexengrig.metter.processor;

import com.google.auto.service.AutoService;
import dev.alexengrig.metter.FieldChecker;
import dev.alexengrig.metter.annotation.GetterSupplier;
import dev.alexengrig.metter.annotation.GetterSupplierFactory;
import dev.alexengrig.metter.element.descriptor.FieldDescriptor;
Expand All @@ -32,6 +33,7 @@
import javax.annotation.processing.Processor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

@AutoService(Processor.class)
Expand Down Expand Up @@ -74,25 +76,44 @@ protected Set<String> getExcludedFields(MethodDescriptor descriptor) {
}

@Override
protected boolean isTargetField(FieldDescriptor field) {
if (field.hasAnnotation(Getter.class)) {
return !field.getAnnotation(Getter.class)
.map(Getter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
protected FieldChecker getFieldChecker(MethodDescriptor descriptor) {
String methodPackage;
if (descriptor.getParent().hasPackage()) {
methodPackage = descriptor.getParent().getPackage();
} else {
methodPackage = "";
}
TypeDescriptor type = field.getParent();
if (type.hasAnnotation(Getter.class)) {
return !type.getAnnotation(Getter.class)
.map(Getter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
return type.hasAnnotation(Data.class) || hasGetterMethod(field);
return field -> {
if (field.hasAnnotation(Getter.class)) {
return !field.getAnnotation(Getter.class)
.map(Getter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
TypeDescriptor type = field.getParent();
if (type.hasAnnotation(Getter.class)) {
return !type.getAnnotation(Getter.class)
.map(Getter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
if (type.hasAnnotation(Data.class)) {
return true;
}
Optional<MethodDescriptor> getterOptional = getGetter(field);
if (!getterOptional.isPresent()) {
return false;
}
MethodDescriptor method = getterOptional.get();
if (method.isPublic()) {
return true;
}
return methodPackage.equals(field.getParent().getPackage());
};
}

@Override
protected String getMethod(FieldDescriptor field) {
return field.getParent().getQualifiedName() + "::" + getGetterMethod(field);
return field.getParent().getQualifiedName() + "::" + getGetterMethodName(field);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package dev.alexengrig.metter.processor;

import com.google.auto.service.AutoService;
import dev.alexengrig.metter.FieldChecker;
import dev.alexengrig.metter.annotation.GetterSupplier;
import dev.alexengrig.metter.element.descriptor.FieldDescriptor;
import dev.alexengrig.metter.element.descriptor.TypeDescriptor;
Expand Down Expand Up @@ -107,6 +108,11 @@ protected Set<String> getExcludedFields(TypeDescriptor descriptor) {
.orElseThrow(() -> new MetterException("Type " + descriptor + " has no annotation: " + annotationClass));
}

@Override
protected FieldChecker getFieldChecker(TypeDescriptor descriptor) {
return this::isTargetField;
}

/**
* Checks if a field descriptor has {@link lombok.Getter} (not private) annotation
* or a type descriptor of field descriptor has {@link lombok.Getter} (not private) annotation
Expand All @@ -120,8 +126,7 @@ protected Set<String> getExcludedFields(TypeDescriptor descriptor) {
* or type descriptor of {@code descriptor} has a getter method
* @since 0.1.1
*/
@Override
protected boolean isTargetField(FieldDescriptor field) {
private boolean isTargetField(FieldDescriptor field) {
if (field.hasAnnotation(Getter.class)) {
return !field.getAnnotation(Getter.class)
.map(Getter::value)
Expand All @@ -147,6 +152,6 @@ protected boolean isTargetField(FieldDescriptor field) {
*/
@Override
protected String getMethod(FieldDescriptor field) {
return field.getParent().getQualifiedName() + "::" + getGetterMethod(field);
return field.getParent().getQualifiedName() + "::" + getGetterMethodName(field);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package dev.alexengrig.metter.processor;

import com.google.auto.service.AutoService;
import dev.alexengrig.metter.FieldChecker;
import dev.alexengrig.metter.annotation.SetterSupplier;
import dev.alexengrig.metter.annotation.SetterSupplierFactory;
import dev.alexengrig.metter.element.descriptor.FieldDescriptor;
Expand All @@ -32,6 +33,7 @@
import javax.annotation.processing.Processor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

@AutoService(Processor.class)
Expand Down Expand Up @@ -74,25 +76,44 @@ protected Set<String> getExcludedFields(MethodDescriptor descriptor) {
}

@Override
protected boolean isTargetField(FieldDescriptor field) {
if (field.hasAnnotation(Setter.class)) {
return !field.getAnnotation(Setter.class)
.map(Setter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
protected FieldChecker getFieldChecker(MethodDescriptor descriptor) {
String methodPackage;
if (descriptor.getParent().hasPackage()) {
methodPackage = descriptor.getParent().getPackage();
} else {
methodPackage = "";
}
TypeDescriptor type = field.getParent();
if (type.hasAnnotation(Setter.class)) {
return !type.getAnnotation(Setter.class)
.map(Setter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
return type.hasAnnotation(Data.class) || hasSetterMethod(field);
return field -> {
if (field.hasAnnotation(Setter.class)) {
return !field.getAnnotation(Setter.class)
.map(Setter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
TypeDescriptor type = field.getParent();
if (type.hasAnnotation(Setter.class)) {
return !type.getAnnotation(Setter.class)
.map(Setter::value)
.filter(AccessLevel.PRIVATE::equals)
.isPresent();
}
if (type.hasAnnotation(Data.class)) {
return true;
}
Optional<MethodDescriptor> setterOptional = getSetter(field);
if (!setterOptional.isPresent()) {
return false;
}
MethodDescriptor method = setterOptional.get();
if (method.isPublic()) {
return true;
}
return methodPackage.equals(field.getParent().getPackage());
};
}

@Override
protected String getMethod(FieldDescriptor field) {
return "(instance, value) -> instance." + getSetterMethod(field) + "((" + field.getTypeName() + ") value)";
return "(instance, value) -> instance." + getSetterMethodName(field) + "((" + field.getTypeName() + ") value)";
}
}
Loading

0 comments on commit c484281

Please sign in to comment.