识别IType的所有IMethods的访问者和变更者(getter / setter)

时间:2017-01-19 09:43:45

标签: java eclipse parsing abstract-syntax-tree eclipse-jdt

我可以使用方法IType访问getMethods()的所有方法。有没有一种有效的方法来确定这样的IMethod是一个存取器还是一个mutator(getter / setter)?

检查IMethod的名称是否与带有prefix + NameOfAttribute的方案prefix ∈ {"get", "set", "is"}匹配将有助于我检测明显的名称,但是如果访问者或变异者(getter / setter)是没有这样命名,它就行不通了。

有更好的方法吗?

编辑:我只想识别直接获取/设置IType属性的getter / setter方法,而不做任何其他操作。

EDIT2 :使用的技术术语:accessor&增变

EDIT3 :阅读完所有答案后,这是我的解决方案

    private boolean isAccessor(IMethod method) throws JavaModelException {
        if (isAccessMethod("get", method) || isAccessMethod("is", method)) { // if name fits
            return method.getNumberOfParameters() == 0 && !Signature.SIG_VOID.equals(method.getReturnType());
        }
        return false;
    }

    private boolean isMutator(IMethod method) throws JavaModelException {
        if (isAccessMethod("set", method)) { // if name fits
            return method.getNumberOfParameters() == 1 && Signature.SIG_VOID.equals(method.getReturnType());
        }
        return false;
    }

    private boolean isAccessMethod(String prefix, IMethod method) throws JavaModelException {
        IType type = method.getDeclaringType();
        for (IField field : type.getFields()) { // for ever field of IType:
            if (method.getElementName().equalsIgnoreCase(prefix + field.getElementName())) {
                return true; // is access method if name scheme fits for one field
            }
        }
        return false; // is not an access method if no field fits
    }

重要提示:此解决方案符合我的要求,但忽略了一些重要案例(请参阅accepted answer。这仍然没有检查方法的功能,但它工作得很好。它检查我提出的方案的方法名称。但它也会检查参数计数以及返回类型是否为void。如果有人想改进这一点,他还可以检查getter的返回/参数类型是否与方法名称匹配的字段类型匹配。

2 个答案:

答案 0 :(得分:2)

我想没有支持在JDT核心中识别getter和setter。

JDT中只有一个公共API,它根据字段名称提供getter / setter名称生成。例如。 NamingConvention查看suggestGetterName()方法。

其他内部类如GetterSetterUtil也没有提供您想要的方法。

最后,我将自己创建一个属性访问器检测器。也许作为我可以在Collection上使用的过滤器。

  

检查IMethod的名称是否与方案前缀+ NameOfAttribute匹配,前缀为∈{“get”,“set”}

如果是布尔属性,则检查is前缀和方法的参数列表。当setter通常采用一个参数时,getters通常不接受参数。我通常说,因为JavaBeans specification也允许索引属性。 E.g。

 void setter(int index, PropertyType value); // indexed setter
 PropertyType getter(int index); // indexed getter
 void setter(PropertyType values[]); // array setter
 PropertyType[] getter(); // array getter

修改

  

我根据您的提案在我的帖子中添加了我自己的解决方案。

您的解决方案可能符合您的要求。请记住,属性可能没有直接的后备字段。属性的概念有点抽象。我的意思是,如果您有一个名为visible的属性和一个getter isVisible(),则该类可能没有字段private boolean visible

为清楚起见,您应该从rootPane查看属性JComponent。它绝对是一个属性,因为Introspector会返回它。

BeanInfo jcomponentBeanInfo = Introspector.getBeanInfo(JComponent.class);

PropertyDescriptor[] propertyDescriptors = jcomponentBeanInfo.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
  PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
  if("rootPane".equals(propertyDescriptor.getName())){
    System.out.println("Found property rootPane");
    break;
  }
}

将打印出来

Found property rootPane

但如果你看一下实现,它就不会使用直接后备字段。

public JRootPane getRootPane() {
    return SwingUtilities.getRootPane(this);
}

SwingUtilities.getRootPane

public static JRootPane getRootPane(Component c) {
    if (c instanceof RootPaneContainer) {
        return ((RootPaneContainer)c).getRootPane();
    }
    for( ; c != null; c = c.getParent()) {
        if (c instanceof JRootPane) {
            return (JRootPane)c;
        }
    }
    return null;
}

我只想更清楚地说明这一点。

答案 1 :(得分:1)

我的方法是:

for (IMethod m : iType.getMethods()) {
    if (m.getElementName().substring(0,3).equals("get")) {
        //do something
    } else if (m.getElementName().substring(0,3).equals("set")) {
        //do something else
    }
}

您可以在getFields()上使用IType,然后在每个字段使用getElementName()