是否有用于检查字符串参数模式的android注释?

时间:2018-06-14 11:32:01

标签: java android kotlin annotations pattern-matching

问题

我正在使用Android和Kotlin,我希望有一个注释来检查常量String参数(对于函数或构造函数)是否与某个模式(正则表达式)匹配。我读到了Pattern Annotation,但我不确定它是否适用于我的问题以及它是否适用于Android。

所以当我有这样的代码时

fun foo(@MatchesPattern("a*b") bar: String) = println(bar)

然后

foo("aaaab")

应该编译得很好,但是

foo("bb")

不应该。

这是否可行,最好没有任何第三方库?如果是,我将如何实现这样的注释? (对不起,我不熟悉编写我自己的自定义注释)

背景

我想将带有连字符分隔音节的单词作为参数传递,但是一个单词不应超过3个音节(这意味着每个单词最多2个连字符)。我知道我也可以使用默认的params实现这一点,但我认为注释将是一种更优雅的方式来实现这一点。

1 个答案:

答案 0 :(得分:2)

在Android中,它不是那么简单,因为您将不得不创建一个新项目(java库),在其中可以放置注释。该过程看起来像这样(未经测试)。

  1. 使用android studio作为项目中的模块创建一个新的Java库(选择项目根目录,右键单击,新建模块)。如果您不更改其默认值,则会使用您指定的类(例如MyCustomAnnotationProcessor)添加一个文件夹,例如 lib

  2. 在您的 app 目录中,转到build.gradle并对其进行修改,以包括sourceCompatibility和targetCompatibility,如下所示:

    android {
        ...
        compileOptions {
            sourceCompatibility = JavaVersion.VERSION_1_8
            targetCompatibility = JavaVersion.VERSION_1_8
        }
    }
    
  3. 然后在 lib build.gradle文件中执行几乎相同的操作(如果在第2步重建后还不存在)

    apply plugin: 'java-library'
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
    }
    
    sourceCompatibility = "1.8"
    targetCompatibility = "1.8"
    
  4. lib 文件夹中,为注释(@interface)创建一个新类,如下所示:

    @Retention(RetentionPolicy.SOURCE)
    @Target(ElementType.PARAMETER)
    public @interface PatternMatches {
        String value() default ".*";
    }
    
  5. 修改在步骤1中创建的注释处理器。请注意,这扩展了javax.annotation.processing.AbstractProcessor,仅在这里可用,因为我们位于Java库中。

    @SupportedAnnotationTypes("your.package.PatternMatches")
    @SupportedSourceVersion(SourceVersion.RELEASE_8)
    public class MyCustomAnnotationProcessor extends AbstractProcessor {
        private ProcessingEnvironment processingEnv;
        @Override
        public synchronized void init(ProcessingEnvironment env){
            processingEnv = env;
        }
        @Override
        public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(PatternMatches.class);
            Set<VariableElement> params = ElementFilter.fieldsIn(elements);
            for (VariableElement param : params) {
                String val = param.getConstantValue();
                String regex = param.getAnnotation(PatternMatches.class).value();
                if (!val.matches(regex)) {
                    processingEnv.getMessager().printMessage(
    Diagnostic.Kind.ERROR, "Regex match failed", param);
                }
            }
            return false;
        }
    }