我正在使用Android和Kotlin,我希望有一个注释来检查常量String
参数(对于函数或构造函数)是否与某个模式(正则表达式)匹配。我读到了Pattern Annotation,但我不确定它是否适用于我的问题以及它是否适用于Android。
所以当我有这样的代码时
fun foo(@MatchesPattern("a*b") bar: String) = println(bar)
然后
foo("aaaab")
应该编译得很好,但是
foo("bb")
不应该。
这是否可行,最好没有任何第三方库?如果是,我将如何实现这样的注释? (对不起,我不熟悉编写我自己的自定义注释)
我想将带有连字符分隔音节的单词作为参数传递,但是一个单词不应超过3个音节(这意味着每个单词最多2个连字符)。我知道我也可以使用默认的params实现这一点,但我认为注释将是一种更优雅的方式来实现这一点。
答案 0 :(得分:2)
在Android中,它不是那么简单,因为您将不得不创建一个新项目(java库),在其中可以放置注释。该过程看起来像这样(未经测试)。
使用android studio作为项目中的模块创建一个新的Java库(选择项目根目录,右键单击,新建模块)。如果您不更改其默认值,则会使用您指定的类(例如MyCustomAnnotationProcessor
)添加一个文件夹,例如 lib 。
在您的 app 目录中,转到build.gradle
并对其进行修改,以包括sourceCompatibility和targetCompatibility,如下所示:
android {
...
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
然后在 lib 的build.gradle
文件中执行几乎相同的操作(如果在第2步重建后还不存在)
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
在 lib 文件夹中,为注释(@interface
)创建一个新类,如下所示:
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.PARAMETER)
public @interface PatternMatches {
String value() default ".*";
}
修改在步骤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;
}
}