diff --git a/src/test/java/spoon/generating/RoleHandlersGenerator.java b/src/test/java/spoon/generating/RoleHandlersGenerator.java index 80b1997ebe4..78cf866cbcb 100644 --- a/src/test/java/spoon/generating/RoleHandlersGenerator.java +++ b/src/test/java/spoon/generating/RoleHandlersGenerator.java @@ -39,7 +39,7 @@ import spoon.reflect.reference.CtWildcardReference; import spoon.reflect.visitor.PrinterHelper; import spoon.template.Substitution; -import spoon.test.metamodel.MMField; +import spoon.test.metamodel.MetamodelProperty; import spoon.test.metamodel.MMMethod; import spoon.test.metamodel.MMMethodKind; import spoon.test.metamodel.SpoonMetaModel; @@ -49,17 +49,17 @@ public class RoleHandlersGenerator extends AbstractManualProcessor { // Class[] helperIfaces = new Class[]{CtBodyHolder.class, // CtTypeInformation.class, CtNamedElement.class}; - Map methodsByTypeRoleHandler = new HashMap<>(); + Map methodsByTypeRoleHandler = new HashMap<>(); @Override public void process() { SpoonMetaModel metaModel = new SpoonMetaModel(getFactory()); //all root super MMFields - List superFields = new ArrayList<>(); + List superFields = new ArrayList<>(); - metaModel.getMMTypes().forEach(mmType -> { - mmType.getRole2field().forEach((role, rim) -> { + metaModel.getConcepts().forEach(mmConcept -> { + mmConcept.getRoleToProperty().forEach((role, rim) -> { addUniqueObject(superFields, rim.getRootSuperField()); }); }); @@ -69,11 +69,11 @@ public void process() { if (d != 0) { return d; } - return a.getOwnerType().getName().compareTo(b.getOwnerType().getName()); + return a.getOwnerConcept().getName().compareTo(b.getOwnerConcept().getName()); }); PrinterHelper concept = new PrinterHelper(getFactory().getEnvironment()); superFields.forEach(mmField -> { - concept.write(mmField.getOwnerType().getName() + " CtRole." + mmField.getRole().name()).writeln().incTab() + concept.write(mmField.getOwnerConcept().getName() + " CtRole." + mmField.getRole().name()).writeln().incTab() .write("ItemType: ").write(mmField.getValueType().toString()).writeln(); for (MMMethodKind mk : MMMethodKind.values()) { MMMethod mmMethod = mmField.getMethod(mk); @@ -105,10 +105,10 @@ public void process() { } params.put("$Role$", getFactory().Type().createReference(CtRole.class)); params.put("ROLE", rim.getRole().name()); - params.put("$TargetType$", rim.getOwnerType().getModelInterface().getReference()); + params.put("$TargetType$", rim.getOwnerConcept().getModelInterface().getReference()); // params.put("AbstractHandler", getFactory().Type().createReference("spoon.reflect.meta.impl.AbstractRoleHandler")); params.put("AbstractHandler", getRoleHandlerSuperTypeQName(rim)); - params.put("Node", rim.getOwnerType().getModelInterface().getReference()); + params.put("Node", rim.getOwnerConcept().getModelInterface().getReference()); params.put("ValueType", fixMainValueType(getRoleHandlerSuperTypeQName(rim).endsWith("SingleHandler") ? rim.getValueType() : rim.getItemValueType())); CtClass modelRoleHandlerClass = Substitution.createTypeFromTemplate( getHandlerName(rim), @@ -184,12 +184,12 @@ private boolean addUniqueObject(Collection col, T o) { return true; } - String getHandlerName(MMField field) { - String typeName = field.getOwnerType().getName(); + String getHandlerName(MetamodelProperty field) { + String typeName = field.getOwnerConcept().getName(); return typeName + "_" + field.getRole().name() + "_RoleHandler"; } - public String getRoleHandlerSuperTypeQName(MMField field) { + public String getRoleHandlerSuperTypeQName(MetamodelProperty field) { switch (field.getValueContainerType()) { case LIST: return "spoon.reflect.meta.impl.ListHandler"; diff --git a/src/test/java/spoon/reflect/visitor/CtScannerTest.java b/src/test/java/spoon/reflect/visitor/CtScannerTest.java index be2bde31eb9..0b54db51c59 100644 --- a/src/test/java/spoon/reflect/visitor/CtScannerTest.java +++ b/src/test/java/spoon/reflect/visitor/CtScannerTest.java @@ -37,7 +37,7 @@ import spoon.reflect.visitor.processors.CheckScannerTestProcessor; import spoon.test.metamodel.MMMethod; import spoon.test.metamodel.MMMethodKind; -import spoon.test.metamodel.MMType; +import spoon.test.metamodel.MetamodelConcept; import spoon.test.metamodel.MMTypeKind; import spoon.test.metamodel.SpoonMetaModel; @@ -140,20 +140,20 @@ public void testScannerCallsAllProperties() throws Exception { class Counter { int nbChecks = 0; } Counter c = new Counter(); - for (MMType leafMmType : metaModel.getMMTypes()) { + for (MetamodelConcept leafConcept : metaModel.getConcepts()) { // we only consider leaf, actual classes of the metamodel (eg CtInvocation) and not abstract ones (eg CtModifiable) - if (leafMmType.getKind() != MMTypeKind.LEAF) { + if (leafConcept.getKind() != MMTypeKind.LEAF) { continue; } - CtMethod visitMethod = scannerVisitMethodsByName.remove("visit"+leafMmType.getName()); - assertNotNull("CtScanner#" + "visit"+leafMmType.getName() + "(...) not found", visitMethod); + CtMethod visitMethod = scannerVisitMethodsByName.remove("visit"+leafConcept.getName()); + assertNotNull("CtScanner#" + "visit"+leafConcept.getName() + "(...) not found", visitMethod); Set calledMethods = new HashSet<>(); Set checkedMethods = new HashSet<>(); // go over the roles and the corresponding fields of this type - leafMmType.getRole2field().forEach((role, mmField) -> { + leafConcept.getRoleToProperty().forEach((role, mmField) -> { if (mmField.isDerived()) { //ignore derived fields @@ -181,7 +181,7 @@ public boolean matches(CtInvocation element) { } }).first(); - if(getter.getName().equals("getComments") && leafMmType.getModelInterface().isSubtypeOf(ctRefRef)) { + if(getter.getName().equals("getComments") && leafConcept.getModelInterface().isSubtypeOf(ctRefRef)) { //one cannot set comments on references see the @UnsettableProperty of CtReference#setComments return; } diff --git a/src/test/java/spoon/test/architecture/SpoonArchitectureEnforcerTest.java b/src/test/java/spoon/test/architecture/SpoonArchitectureEnforcerTest.java index 804b4f42ed1..267202ce423 100644 --- a/src/test/java/spoon/test/architecture/SpoonArchitectureEnforcerTest.java +++ b/src/test/java/spoon/test/architecture/SpoonArchitectureEnforcerTest.java @@ -284,9 +284,9 @@ public void testInterfacesAreCtScannable() { List missingMethods = new ArrayList<>(); - new SpoonMetaModel(interfaces.getFactory()).getMMTypes().forEach(mmType -> { - if (mmType.getKind() == ABSTRACT && mmType.getModelInterface() != null) { - CtInterface abstractIface = mmType.getModelInterface(); + new SpoonMetaModel(interfaces.getFactory()).getConcepts().forEach(mmConcept -> { + if (mmConcept.getKind() == ABSTRACT && mmConcept.getModelInterface() != null) { + CtInterface abstractIface = mmConcept.getModelInterface(); String methodName = "scan" + abstractIface.getSimpleName(); if (ctScanner.getMethodsByName(methodName).isEmpty()) { missingMethods.add(methodName); diff --git a/src/test/java/spoon/test/metamodel/MMContainerType.java b/src/test/java/spoon/test/metamodel/MMContainerType.java deleted file mode 100644 index f56c1afe621..00000000000 --- a/src/test/java/spoon/test/metamodel/MMContainerType.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2006-2017 INRIA and contributors - * Spoon - http://spoon.gforge.inria.fr/ - * - * This software is governed by the CeCILL-C License under French law and - * abiding by the rules of distribution of free software. You can use, modify - * and/or redistribute the software under the terms of the CeCILL-C license as - * circulated by CEA, CNRS and INRIA at http://www.cecill.info. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. - */ -package spoon.test.metamodel; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Represents type of container used for field value. - */ -public enum MMContainerType { - /** - * it is a single value field - * Example: CtClassImpl.simpleName - */ - SINGLE, - /** - * It is a list of values - * Example: CtClassImpl.typeMembers - */ - LIST, - /** - * It is a set of values - * Example: CtPackageImpl.types - */ - SET, - /** - * It is a map<String, T> of values - * Example: CtAnnotationImpl.elementValues - */ - MAP; - - public static MMContainerType valueOf(Class valueClass) { - if (List.class.isAssignableFrom(valueClass)) { - return LIST; - } - if (Map.class.isAssignableFrom(valueClass)) { - return MAP; - } - if (Set.class.isAssignableFrom(valueClass)) { - return SET; - } - return SINGLE; - } -} diff --git a/src/test/java/spoon/test/metamodel/MMMethod.java b/src/test/java/spoon/test/metamodel/MMMethod.java index fbde851e353..7b997be51b7 100644 --- a/src/test/java/spoon/test/metamodel/MMMethod.java +++ b/src/test/java/spoon/test/metamodel/MMMethod.java @@ -28,11 +28,11 @@ import spoon.support.visitor.MethodTypingContext; /** - * Represents a method of a {@link MMField} of a {@link MMType}. + * Represents a method of a {@link MetamodelProperty} of a {@link MetamodelConcept}. * Each MMMethod belongs to one MMField */ public class MMMethod { - private final MMField ownerField; + private final MetamodelProperty ownerField; private final CtMethod method; private final List> ownMethods = new ArrayList<>(); private final List superMethods = new ArrayList<>(); @@ -40,14 +40,14 @@ public class MMMethod { private final MMMethodKind methodKind; /** - * Creates a {@link MMMethod} of a {@link MMField} + * Creates a {@link MMMethod} of a {@link MetamodelProperty} * @param field a owner field * @param method a method from ownerType or nearest super type */ - MMMethod(MMField field, CtMethod method) { + MMMethod(MetamodelProperty field, CtMethod method) { this.ownerField = field; //adapt method to scope of field.ownType - MethodTypingContext mtc = new MethodTypingContext().setClassTypingContext(field.getOwnerType().getTypeContext()).setMethod(method); + MethodTypingContext mtc = new MethodTypingContext().setClassTypingContext(field.getOwnerConcept().getTypeContext()).setMethod(method); this.method = (CtMethod) mtc.getAdaptationScope(); signature = this.method.getSignature(); methodKind = MMMethodKind.valueOf(this.method); @@ -84,7 +84,7 @@ public MMMethodKind getMethodKind() { /** * @return first own method in super type hierarchy of `targetType` */ - public CtMethod getFirstOwnMethod(MMType targetType) { + public CtMethod getFirstOwnMethod(MetamodelConcept targetType) { for (CtMethod ctMethod : ownMethods) { if (targetType.getTypeContext().isSubtypeOf(ctMethod.getDeclaringType().getReference())) { return ctMethod; @@ -104,7 +104,7 @@ public CtMethod getFirstOwnMethod(MMType targetType) { * @return true of this {@link MMMethod} overrides `method`. In different words, if it represents the same method */ public boolean overrides(CtMethod method) { - return ownerField.getOwnerType().getTypeContext().isOverriding(this.method, method); + return ownerField.getOwnerConcept().getTypeContext().isOverriding(this.method, method); } /** @@ -116,17 +116,17 @@ void addSuperMethod(MMMethod mmMethod) { } /** - * @return {@link MMField} which owns this {@link MMMethod} + * @return {@link MetamodelProperty} which owns this {@link MMMethod} */ - public MMField getOwnerField() { + public MetamodelProperty getOwnerField() { return ownerField; } /** - * @return {@link MMType} where this {@link MMMethod} belongs to + * @return {@link MetamodelConcept} where this {@link MMMethod} belongs to */ - public MMType getOwnerType() { - return getOwnerField().getOwnerType(); + public MetamodelConcept getOwnerType() { + return getOwnerField().getOwnerConcept(); } /** diff --git a/src/test/java/spoon/test/metamodel/MMType.java b/src/test/java/spoon/test/metamodel/MetamodelConcept.java similarity index 58% rename from src/test/java/spoon/test/metamodel/MMType.java rename to src/test/java/spoon/test/metamodel/MetamodelConcept.java index 90d804fee1f..0a236c208e9 100644 --- a/src/test/java/spoon/test/metamodel/MMType.java +++ b/src/test/java/spoon/test/metamodel/MetamodelConcept.java @@ -28,63 +28,61 @@ import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtInterface; import spoon.reflect.declaration.CtMethod; -import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.ModifierKind; import spoon.reflect.path.CtRole; -import spoon.support.reflect.CtExtendedModifier; import spoon.support.visitor.ClassTypingContext; /** - * Represents a type of Spoon model AST node + * Represents a concept of Spoon model AST node */ -public class MMType { +public class MetamodelConcept { /** - * Kind of this type + * Kind of this concept */ MMTypeKind kind; /** - * Name of the type + * Name of the concept */ String name; /** - * List of fields ordered same like CtScanner scans them + * Map of {@link CtRole} to {@link MetamodelProperty}s with values ordered same like CtScanner scans these properties when visiting this {@link MetamodelConcept} */ - final Map role2field = new LinkedHashMap<>(); + final Map role2Property = new LinkedHashMap<>(); /** - * List of super types of this type + * List of super concepts of this concept */ - private final List superTypes = new ArrayList<>(); + private final List superConcepts = new ArrayList<>(); /** - * List of sub types of this type + * List of sub concepts of this concept */ - private final List subTypes = new ArrayList<>(); + private final List subConcepts = new ArrayList<>(); /** - * The {@link CtClass} linked to this {@link MMType}. Is null in case of class without interface + * The {@link CtClass} linked to this {@link MetamodelConcept}. Is null in case of class without interface */ private CtClass modelClass; /** - * The {@link CtInterface} linked to this {@link MMType}. Is null in case of interface without class + * The {@link CtInterface} linked to this {@link MetamodelConcept}. Is null in case of interface without class */ private CtInterface modelInterface; /** - * {@link ClassTypingContext} of this type used to adapt methods from super type implementations to this {@link MMType} + * {@link ClassTypingContext} of this concept used to adapt methods from super type implementations to this {@link MetamodelConcept} */ private ClassTypingContext typeContext; /** - * own methods of MMType, which does not belong to any role + * own methods of {@link MetamodelConcept}, which does not belong to any role */ final List> otherMethods = new ArrayList<>(); - MMType() { + MetamodelConcept() { super(); } /** - * @return interface name of {@link MMType}. For example CtClass, CtForEach, ... + * @return interface name of {@link MetamodelConcept}. For example CtClass, CtForEach, ... * It is never followed by xxxImpl */ public String getName() { @@ -92,12 +90,12 @@ public String getName() { } - MMField getOrCreateMMField(CtRole role) { - return SpoonMetaModel.getOrCreate(role2field, role, () -> new MMField(role.getCamelCaseName(), role, this)); + MetamodelProperty getOrCreateMMField(CtRole role) { + return SpoonMetaModel.getOrCreate(role2Property, role, () -> new MetamodelProperty(role.getCamelCaseName(), role, this)); } /** - * @return kind of this {@link MMType}. Is it helper type or type of real AST node? + * @return kind of this {@link MetamodelConcept}. Is it abstract concept or concept of leaf AST node? */ public MMTypeKind getKind() { if (kind == null) { @@ -120,34 +118,34 @@ public MMTypeKind getKind() { } /** - * @return map of {@link MMField}s by their {@link CtRole} + * @return map of {@link MetamodelProperty}s by their {@link CtRole} */ - public Map getRole2field() { - return Collections.unmodifiableMap(role2field); + public Map getRoleToProperty() { + return Collections.unmodifiableMap(role2Property); } /** * @return super types */ - public List getSuperTypes() { - return superTypes; + public List getSuperConcepts() { + return superConcepts; } - void addSuperType(MMType superType) { + void addSuperConcept(MetamodelConcept superType) { if (superType == this) { throw new SpoonException("Cannot add supertype to itself"); } - if (addUniqueObject(superTypes, superType)) { - superType.subTypes.add(this); - superType.role2field.forEach((role, superMMField) -> { - MMField mmField = getOrCreateMMField(role); + if (addUniqueObject(superConcepts, superType)) { + superType.subConcepts.add(this); + superType.role2Property.forEach((role, superMMField) -> { + MetamodelProperty mmField = getOrCreateMMField(role); mmField.addSuperField(superMMField); }); } } /** - * @return {@link CtClass} which represents this {@link MMType} + * @return {@link CtClass} which represents this {@link MetamodelConcept} */ public CtClass getModelClass() { return modelClass; @@ -158,7 +156,7 @@ void setModelClass(CtClass modelClass) { } /** - * @return {@link CtInterface} which represents this {@link MMType} + * @return {@link CtInterface} which represents this {@link MetamodelConcept} */ public CtInterface getModelInterface() { return modelInterface; @@ -169,7 +167,7 @@ void setModelInterface(CtInterface modelInterface) { } /** - * @return {@link ClassTypingContext}, which can be used to adapt super type methods to this {@link MMType} + * @return {@link ClassTypingContext}, which can be used to adapt super type methods to this {@link MetamodelConcept} */ public ClassTypingContext getTypeContext() { if (typeContext == null) { diff --git a/src/test/java/spoon/test/metamodel/MMField.java b/src/test/java/spoon/test/metamodel/MetamodelProperty.java similarity index 84% rename from src/test/java/spoon/test/metamodel/MMField.java rename to src/test/java/spoon/test/metamodel/MetamodelProperty.java index a5570765a6d..0923b5cfb8e 100644 --- a/src/test/java/spoon/test/metamodel/MMField.java +++ b/src/test/java/spoon/test/metamodel/MetamodelProperty.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -31,6 +30,7 @@ import spoon.SpoonException; import spoon.reflect.declaration.CtMethod; import spoon.reflect.factory.Factory; +import spoon.reflect.meta.ContainerKind; import spoon.reflect.path.CtRole; import spoon.reflect.reference.CtTypeParameterReference; import spoon.reflect.reference.CtTypeReference; @@ -38,10 +38,10 @@ import spoon.support.UnsettableProperty; /** - * Represents a field of Spoon model type. - * Each MMField belongs to one MMType + * Represents a property of Spoon model concept. + * Each {@link MetamodelProperty} belongs to one {@link MetamodelConcept} */ -public class MMField { +public class MetamodelProperty { /** * Name of the field */ @@ -51,19 +51,19 @@ public class MMField { */ private final CtRole role; /** - * The list of {@link MMType}s which contains this field + * The list of {@link MetamodelConcept}s which contains this field */ - private final MMType ownerType; + private final MetamodelConcept ownerConcept; /** * Type of value container [single, list, set, map] */ - private MMContainerType valueContainerType; + private ContainerKind valueContainerType; /** - * The type of value of this field - can be Set, List, Map or any non collection type + * The type of value of this property - can be Set, List, Map or any non collection type */ private CtTypeReference valueType; /** - * The item type of value of this field - can be non collection type + * The item type of value of this property - can be non collection type */ private CtTypeReference itemValueType; @@ -74,28 +74,27 @@ public class MMField { /** * methods of this field defined directly on ownerType. - * There is PropertyGetter or PropertySetter annotation with `role` of this {@link MMField} + * There is PropertyGetter or PropertySetter annotation with `role` of this {@link MetamodelProperty} */ private final List roleMethods = new ArrayList<>(); /** * methods of this field grouped by signature defined directly on ownerType. - * There is PropertyGetter or PropertySetter annotation with `role` of this {@link MMField} + * There is PropertyGetter or PropertySetter annotation with `role` of this {@link MetamodelProperty} * note: There can be up to 2 methods in this list. 1) declaration from interface, 2) implementation from class */ private final Map roleMethodsBySignature = new HashMap<>(); /** - * List of fields with same `role`, from super type of `ownerType` {@link MMType} + * List of {@link MetamodelProperty} with same `role`, from super type of `ownerConcept` {@link MetamodelConcept} */ - private final List superFields = new ArrayList<>(); + private final List superProperties = new ArrayList<>(); private List ambiguousMethodKinds = new ArrayList<>(); - - MMField(String name, CtRole role, MMType ownerType) { + MetamodelProperty(String name, CtRole role, MetamodelConcept ownerConcept) { super(); this.name = name; this.role = role; - this.ownerType = ownerType; + this.ownerConcept = ownerConcept; } void addMethod(CtMethod method) { @@ -120,17 +119,17 @@ MMMethod getOwnMethod(CtMethod method, boolean createIfNotExist) { getOrCreate(methodsByKind, mmMethod.getMethodKind(), () -> new ArrayList<>()).add(mmMethod); MMMethod conflict = roleMethodsBySignature.put(mmMethod.getSignature(), mmMethod); if (conflict != null) { - throw new SpoonException("Conflict on " + getOwnerType().getName() + "." + name + " method signature: " + mmMethod.getSignature()); + throw new SpoonException("Conflict on " + getOwnerConcept().getName() + "." + name + " method signature: " + mmMethod.getSignature()); } return mmMethod; } return null; } - void addSuperField(MMField superMMField) { - if (addUniqueObject(superFields, superMMField)) { + void addSuperField(MetamodelProperty superMMField) { + if (addUniqueObject(superProperties, superMMField)) { for (MMMethod superMethod : superMMField.getRoleMethods()) { - getOwnMethod(superMethod.getFirstOwnMethod(getOwnerType()), true).addSuperMethod(superMethod); + getOwnMethod(superMethod.getFirstOwnMethod(getOwnerConcept()), true).addSuperMethod(superMethod); } } } @@ -143,11 +142,11 @@ public CtRole getRole() { return role; } - public MMType getOwnerType() { - return ownerType; + public MetamodelConcept getOwnerConcept() { + return ownerConcept; } - public MMContainerType getValueContainerType() { + public ContainerKind getValueContainerType() { return valueContainerType; } @@ -161,7 +160,7 @@ public CtTypeReference getValueType() { CtTypeReference detectValueType() { MMMethod mmGetMethod = getMethod(MMMethodKind.GET); if (mmGetMethod == null) { - throw new SpoonException("No getter exists for " + getOwnerType().getName() + "." + getName()); + throw new SpoonException("No getter exists for " + getOwnerConcept().getName() + "." + getName()); } MMMethod mmSetMethod = getMethod(MMMethodKind.SET); if (mmSetMethod == null) { @@ -172,7 +171,7 @@ CtTypeReference detectValueType() { if (getterValueType.equals(setterValueType)) { return mmGetMethod.getReturnType(); } - if (MMContainerType.valueOf(getterValueType.getActualClass()) != MMContainerType.SINGLE) { + if (containerKindOf(getterValueType.getActualClass()) != ContainerKind.SINGLE) { getterValueType = getItemValueType(getterValueType); setterValueType = getItemValueType(setterValueType); } @@ -190,7 +189,7 @@ CtTypeReference detectValueType() { */ return mmSetMethod.getValueType(); } - throw new SpoonException("Incompatible getter and setter for " + getOwnerType().getName() + "." + getName()); + throw new SpoonException("Incompatible getter and setter for " + getOwnerConcept().getName() + "." + getName()); } void setValueType(CtTypeReference valueType) { @@ -207,8 +206,8 @@ void setValueType(CtTypeReference valueType) { valueType.setImplicit(false); } this.valueType = valueType; - this.valueContainerType = MMContainerType.valueOf(valueType.getActualClass()); - if (valueContainerType != MMContainerType.SINGLE) { + this.valueContainerType = containerKindOf(valueType.getActualClass()); + if (valueContainerType != ContainerKind.SINGLE) { itemValueType = getItemValueType(valueType); } else { itemValueType = valueType; @@ -371,12 +370,12 @@ private int getIdxOfBestMatchByInputParameter(List methods, MMMethodKi } private static CtTypeReference getItemValueType(CtTypeReference valueType) { - MMContainerType valueContainerType = MMContainerType.valueOf(valueType.getActualClass()); - if (valueContainerType == MMContainerType.SINGLE) { + ContainerKind valueContainerType = containerKindOf(valueType.getActualClass()); + if (valueContainerType == ContainerKind.SINGLE) { return null; } CtTypeReference itemValueType; - if (valueContainerType == MMContainerType.MAP) { + if (valueContainerType == ContainerKind.MAP) { if (String.class.getName().equals(valueType.getActualTypeArguments().get(0).getQualifiedName()) == false) { throw new SpoonException("Unexpected container of type: " + valueType.toString()); } @@ -440,6 +439,9 @@ private CtTypeReference getMapValueType(CtTypeReference valueType) { return null; } + /** + * @return true if this {@link MetamodelProperty} is derived in owner concept + */ public boolean isDerived() { if (derived == null) { //if DerivedProperty is found on any getter of this type, then this field is derived @@ -466,7 +468,7 @@ public boolean isDerived() { //if DerivedProperty annotation is not found on any get method, then it is not derived derived = Boolean.FALSE; //check all super fields. If any of them is derived then this field is derived too - for (MMField superField : superFields) { + for (MetamodelProperty superField : superProperties) { if (superField.isDerived()) { derived = Boolean.TRUE; break; @@ -476,6 +478,9 @@ public boolean isDerived() { return derived; } + /** + * @return true if this {@link MetamodelProperty} is unsettable in owner concept + */ public boolean isUnsettable() { if (unsettable == null) { //if UnsettablePropertyis found on any setter of this type, then this field is unsettable @@ -503,7 +508,7 @@ public boolean isUnsettable() { //if UnsettableProperty annotation is not found on any set method, then it is settable unsettable = Boolean.FALSE; //check all super fields. If any of them is derived then this field is derived too - for (MMField superField : superFields) { + for (MetamodelProperty superField : superProperties) { if (superField.isUnsettable()) { unsettable = Boolean.TRUE; break; @@ -521,24 +526,24 @@ public Map getRoleMethodsBySignature() { return Collections.unmodifiableMap(roleMethodsBySignature); } - public List getSuperFields() { - return Collections.unmodifiableList(superFields); + public List getSuperFields() { + return Collections.unmodifiableList(superProperties); } @Override public String toString() { - return ownerType.getName() + "#" + getName() + "<" + valueType + ">"; + return ownerConcept.getName() + "#" + getName() + "<" + valueType + ">"; } /** * @return the super MMField which has same valueType and which is in root of the most implementations */ - public MMField getRootSuperField() { - List potentialRootSuperFields = new ArrayList<>(); + public MetamodelProperty getRootSuperField() { + List potentialRootSuperFields = new ArrayList<>(); if (roleMethods.size() > 0) { potentialRootSuperFields.add(this); } - superFields.forEach(superField -> { + superProperties.forEach(superField -> { addUniqueObject(potentialRootSuperFields, superField.getRootSuperField()); }); int idx = 0; @@ -546,7 +551,7 @@ public MMField getRootSuperField() { boolean needsSetter = getMethod(MMMethodKind.SET) != null; CtTypeReference expectedValueType = this.getValueType().getTypeErasure(); for (int i = 1; i < potentialRootSuperFields.size(); i++) { - MMField superField = potentialRootSuperFields.get(i); + MetamodelProperty superField = potentialRootSuperFields.get(i); if (superField.getValueType().getTypeErasure().equals(expectedValueType) == false) { break; } @@ -559,4 +564,18 @@ public MMField getRootSuperField() { } return potentialRootSuperFields.get(idx); } + + private static ContainerKind containerKindOf(Class valueClass) { + if (List.class.isAssignableFrom(valueClass)) { + return ContainerKind.LIST; + } + if (Map.class.isAssignableFrom(valueClass)) { + return ContainerKind.MAP; + } + if (Set.class.isAssignableFrom(valueClass)) { + return ContainerKind.SET; + } + return ContainerKind.SINGLE; + } + } diff --git a/src/test/java/spoon/test/metamodel/SpoonMetaModel.java b/src/test/java/spoon/test/metamodel/SpoonMetaModel.java index e763e8c1a4d..eea6a28d179 100644 --- a/src/test/java/spoon/test/metamodel/SpoonMetaModel.java +++ b/src/test/java/spoon/test/metamodel/SpoonMetaModel.java @@ -65,9 +65,9 @@ public class SpoonMetaModel { private final Factory factory; /** - * {@link MMType}s by name + * {@link MetamodelConcept}s by name */ - private final Map name2mmType = new HashMap<>(); + private final Map nameToConcept = new HashMap<>(); /** * Parses spoon sources and creates factory with spoon model. @@ -95,27 +95,27 @@ public SpoonMetaModel(Factory factory) { } } - //search for all interfaces of spoon model and create MMTypes for them + //search for all interfaces of spoon model and create MetamodelConcepts for them factory.getModel().filterChildren(new TypeFilter<>(CtInterface.class)) .forEach((CtInterface iface) -> { if (MODEL_IFACE_PACKAGES.contains(iface.getPackage().getQualifiedName())) { - getOrCreateMMType(iface); + getOrCreateConcept(iface); } }); } /** - * @return all {@link MMType}s of spoon meta model + * @return all {@link MetamodelConcept}s of spoon meta model */ - public Collection getMMTypes() { - return Collections.unmodifiableCollection(name2mmType.values()); + public Collection getConcepts() { + return Collections.unmodifiableCollection(nameToConcept.values()); } /** - * @param type a spoon model type - * @return name of {@link MMType}, which represents Spoon model {@link CtType} + * @param type a spoon model class or interface, whose concept name has to be returned + * @return name of {@link MetamodelConcept}, which represents Spoon model {@link CtType} */ - public static String getMMTypeIntefaceName(CtType type) { + public static String getConceptName(CtType type) { String name = type.getSimpleName(); if (name.endsWith(CLASS_SUFFIX)) { name = name.substring(0, name.length() - CLASS_SUFFIX.length()); @@ -175,48 +175,48 @@ private static Factory createFactory(File spoonJavaSourcesDirectory) { /** * @param type can be class or interface of Spoon model element - * @return existing or creates and initializes new {@link MMType} which represents `type`, which + * @return existing or creates and initializes new {@link MetamodelConcept} which represents the `type` */ - private MMType getOrCreateMMType(CtType type) { - String mmTypeName = getMMTypeIntefaceName(type); - MMType mmType = getOrCreate(name2mmType, mmTypeName, () -> new MMType()); - if (mmType.name == null) { - mmType.name = mmTypeName; - initializeMMType(type, mmType); + private MetamodelConcept getOrCreateConcept(CtType type) { + String conceptName = getConceptName(type); + MetamodelConcept mmConcept = getOrCreate(nameToConcept, conceptName, () -> new MetamodelConcept()); + if (mmConcept.name == null) { + mmConcept.name = conceptName; + initializeConcept(type, mmConcept); } - return mmType; + return mmConcept; } /** - * is called once for each MMType, to initialize it. + * is called once for each {@link MetamodelConcept}, to initialize it. * @param type a class or inteface of the spoon model element - * @param mmType to be initialize MMType + * @param mmConcept to be initialize {@link MetamodelConcept} */ - private void initializeMMType(CtType type, MMType mmType) { + private void initializeConcept(CtType type, MetamodelConcept mmConcept) { //it is not initialized yet. Do it now if (type instanceof CtInterface) { CtInterface iface = (CtInterface) type; - mmType.setModelClass(getImplementationOfInterface(iface)); - mmType.setModelInterface(iface); + mmConcept.setModelClass(getImplementationOfInterface(iface)); + mmConcept.setModelInterface(iface); } else if (type instanceof CtClass) { CtClass clazz = (CtClass) type; - mmType.setModelClass(clazz); - mmType.setModelInterface(getInterfaceOfImplementation(clazz)); + mmConcept.setModelClass(clazz); + mmConcept.setModelInterface(getInterfaceOfImplementation(clazz)); } else { throw new SpoonException("Unexpected spoon model type: " + type.getQualifiedName()); } //add fields of class - if (mmType.getModelClass() != null) { - addFieldsOfType(mmType, mmType.getModelClass()); + if (mmConcept.getModelClass() != null) { + addFieldsOfType(mmConcept, mmConcept.getModelClass()); } //add fields of interface - if (mmType.getModelInterface() != null) { - //add fields of interface too. They are not added by above call of addFieldsOfType, because the MMType already exists in name2mmType - addFieldsOfType(mmType, mmType.getModelInterface()); + if (mmConcept.getModelInterface() != null) { + //add fields of interface too. They are not added by above call of addFieldsOfType, because the MetamodelConcept already exists in nameToConcept + addFieldsOfType(mmConcept, mmConcept.getModelInterface()); } //initialize all fields - mmType.getRole2field().forEach((role, mmField) -> { + mmConcept.getRoleToProperty().forEach((role, mmField) -> { //if there are more methods for the same field then choose the one which best matches the field type mmField.sortByBestMatch(); //finally initialize value type of this field @@ -225,25 +225,25 @@ private void initializeMMType(CtType type, MMType mmType) { } /** - * adds all {@link MMField}s of `ctType` - * @param mmType the owner of to be created fields + * adds all {@link MetamodelProperty}s of `ctType` + * @param mmConcept the owner of to be created fields * @param ctType to be scanned {@link CtType} */ - private void addFieldsOfType(MMType mmType, CtType ctType) { + private void addFieldsOfType(MetamodelConcept mmConcept, CtType ctType) { ctType.getTypeMembers().forEach(typeMember -> { if (typeMember instanceof CtMethod) { CtMethod method = (CtMethod) typeMember; CtRole role = getRoleOfMethod(method); if (role != null) { - MMField field = mmType.getOrCreateMMField(role); + MetamodelProperty field = mmConcept.getOrCreateMMField(role); field.addMethod(method); } else { - mmType.otherMethods.add(method); + mmConcept.otherMethods.add(method); } } }); - addFieldsOfSuperType(mmType, ctType.getSuperclass()); - ctType.getSuperInterfaces().forEach(superIfaceRef -> addFieldsOfSuperType(mmType, superIfaceRef)); + addFieldsOfSuperType(mmConcept, ctType.getSuperclass()); + ctType.getSuperInterfaces().forEach(superIfaceRef -> addFieldsOfSuperType(mmConcept, superIfaceRef)); } private static Set EXPECTED_TYPES_NOT_IN_CLASSPATH = new HashSet<>(Arrays.asList( @@ -257,11 +257,11 @@ private void addFieldsOfType(MMType mmType, CtType ctType) { /** - * add all fields of `superTypeRef` into `mmType` - * @param mmType sub type + * add all fields of `superTypeRef` into `mmConcept` + * @param concept sub type * @param superTypeRef super type */ - private void addFieldsOfSuperType(MMType mmType, CtTypeReference superTypeRef) { + private void addFieldsOfSuperType(MetamodelConcept concept, CtTypeReference superTypeRef) { if (superTypeRef == null) { return; } @@ -272,10 +272,10 @@ private void addFieldsOfSuperType(MMType mmType, CtTypeReference superTypeRef } return; } - //call getOrCreateMMType recursively for super types - MMType superMMType = getOrCreateMMType(superType); - if (superMMType != mmType) { - mmType.addSuperType(superMMType); + //call getOrCreateConcept recursively for super concepts + MetamodelConcept superConcept = getOrCreateConcept(superType); + if (superConcept != concept) { + concept.addSuperConcept(superConcept); } } diff --git a/src/test/java/spoon/test/reflect/meta/MetaModelTest.java b/src/test/java/spoon/test/reflect/meta/MetaModelTest.java index a8aa5a20731..919ba0c9e05 100644 --- a/src/test/java/spoon/test/reflect/meta/MetaModelTest.java +++ b/src/test/java/spoon/test/reflect/meta/MetaModelTest.java @@ -50,17 +50,17 @@ public void spoonMetaModelTest() { //detect unused CtRoles Set unhandledRoles = new HashSet<>(Arrays.asList(CtRole.values())); - mm.getMMTypes().forEach(mmType -> { - mmType.getRole2field().forEach((role, mmField) -> { + mm.getConcepts().forEach(mmConcept -> { + mmConcept.getRoleToProperty().forEach((role, mmField) -> { unhandledRoles.remove(role); if (mmField.getMethod(MMMethodKind.GET) == null) { - problems.add("Missing getter for " + mmField.getOwnerType().getName() + " and CtRole." + mmField.getRole()); + problems.add("Missing getter for " + mmField.getOwnerConcept().getName() + " and CtRole." + mmField.getRole()); } if (mmField.getMethod(MMMethodKind.SET) == null) { - if (mmType.getTypeContext().isSubtypeOf(mm.getFactory().Type().createReference(CtReference.class)) == false - && mmType.getName().equals("CtTypeInformation") == false) { + if (mmConcept.getTypeContext().isSubtypeOf(mm.getFactory().Type().createReference(CtReference.class)) == false + && mmConcept.getName().equals("CtTypeInformation") == false) { //only NON references needs a setter - problems.add("Missing setter for " + mmField.getOwnerType().getName() + " and CtRole." + mmField.getRole()); + problems.add("Missing setter for " + mmField.getOwnerConcept().getName() + " and CtRole." + mmField.getRole()); } } //contract: type of field value is never implicit diff --git a/src/test/java/spoon/test/replace/ReplaceParametrizedTest.java b/src/test/java/spoon/test/replace/ReplaceParametrizedTest.java index 659baa6c2b2..af02e879f65 100644 --- a/src/test/java/spoon/test/replace/ReplaceParametrizedTest.java +++ b/src/test/java/spoon/test/replace/ReplaceParametrizedTest.java @@ -32,8 +32,8 @@ import spoon.reflect.visitor.CtScanner; import spoon.reflect.visitor.CtVisitable; import spoon.reflect.visitor.Filter; -import spoon.test.metamodel.MMField; -import spoon.test.metamodel.MMType; +import spoon.test.metamodel.MetamodelProperty; +import spoon.test.metamodel.MetamodelConcept; import spoon.test.metamodel.MMTypeKind; import spoon.test.metamodel.SpoonMetaModel; @@ -49,7 +49,7 @@ public static Collection data() throws Exception { factory = metaModel.getFactory(); List values = new ArrayList<>(); - for (MMType t : metaModel.getMMTypes()) { + for (MetamodelConcept t : metaModel.getConcepts()) { if(t.getKind()==MMTypeKind.LEAF) { values.add(new Object[] { t }); } @@ -58,7 +58,7 @@ public static Collection data() throws Exception { } @Parameterized.Parameter(0) - public MMType typeToTest; + public MetamodelConcept typeToTest; @Test @@ -69,7 +69,7 @@ public void testContract() throws Throwable { // this test puts them at all possible locations CtType toTest = typeToTest.getModelInterface(); CtElement o = factory.Core().create((Class) toTest.getActualClass()); - for (MMField mmField : typeToTest.getRole2field().values()) { + for (MetamodelProperty mmField : typeToTest.getRoleToProperty().values()) { Class argType = mmField.getItemValueType().getActualClass(); if (!CtElement.class.isAssignableFrom(argType)) {