mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-19 19:42:17 +02:00
Add lint check: Use of JetBrains annotations
We have standardised on androidx annotations, this helps new users and suggests an IDE option to change to the correct library. This does appear in the IDE, so we can define it as an error, rather than a warning.
This commit is contained in:
parent
49a343230f
commit
da5968ec39
@ -7,6 +7,7 @@ import com.ichi2.anki.lint.rules.DirectSystemTimeInstantiation;
|
||||
import com.ichi2.anki.lint.rules.DirectSystemCurrentTimeMillisUsage;
|
||||
import com.ichi2.anki.lint.rules.DirectDateInstantiation;
|
||||
import com.ichi2.anki.lint.rules.DirectGregorianInstantiation;
|
||||
import com.ichi2.anki.lint.rules.InconsistentAnnotationUsage;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -23,6 +24,7 @@ public class IssueRegistry extends com.android.tools.lint.client.api.IssueRegist
|
||||
issues.add(DirectDateInstantiation.ISSUE);
|
||||
issues.add(DirectGregorianInstantiation.ISSUE);
|
||||
issues.add(DirectSystemTimeInstantiation.ISSUE);
|
||||
issues.add(InconsistentAnnotationUsage.ISSUE);
|
||||
return issues;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2020 David Allison <davidallisongithub@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 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 GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.ichi2.anki.lint.rules;
|
||||
|
||||
import com.android.annotations.NonNull;
|
||||
import com.android.tools.lint.detector.api.Implementation;
|
||||
import com.android.tools.lint.detector.api.Issue;
|
||||
import com.android.tools.lint.detector.api.JavaContext;
|
||||
import com.android.tools.lint.detector.api.Scope;
|
||||
import com.android.tools.lint.detector.api.SourceCodeScanner;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.ichi2.anki.lint.utils.Constants;
|
||||
import com.ichi2.anki.lint.utils.ImportStatementDetector;
|
||||
|
||||
import org.jetbrains.uast.UElement;
|
||||
import org.jetbrains.uast.UImportStatement;
|
||||
|
||||
public class InconsistentAnnotationUsage extends ImportStatementDetector implements SourceCodeScanner {
|
||||
@VisibleForTesting
|
||||
static final String ID = "InconsistentAnnotationUsage";
|
||||
@VisibleForTesting
|
||||
static final String DESCRIPTION = "Use androidx.annotation.NonNull and androidx.annotation.Nullable. See explanation for IDE-level fix";
|
||||
private static final String EXPLANATION = "AnkiDroid uses androidx nullability annotations over JetBrains for nullability. " +
|
||||
"The annotations library can be specified in Settings - Inspections - @NotNull/@Nullable problems";
|
||||
private static Implementation implementation = new Implementation(InconsistentAnnotationUsage.class, Scope.JAVA_FILE_SCOPE);
|
||||
public static final Issue ISSUE = Issue.create(
|
||||
ID,
|
||||
DESCRIPTION,
|
||||
EXPLANATION,
|
||||
Constants.ANKI_TIME_CATEGORY,
|
||||
Constants.ANKI_TIME_PRIORITY,
|
||||
Constants.ANKI_TIME_SEVERITY,
|
||||
implementation
|
||||
);
|
||||
|
||||
public InconsistentAnnotationUsage() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void visitImportStatement(@NonNull JavaContext context, @NonNull UImportStatement node) {
|
||||
|
||||
UElement importReference = node.getImportReference();
|
||||
if (importReference != null && isJetbrains(importReference.asRenderString())) {
|
||||
context.report(
|
||||
ISSUE,
|
||||
node,
|
||||
context.getLocation(node),
|
||||
DESCRIPTION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private boolean isJetbrains(String importReference) {
|
||||
return importReference.equals("org.jetbrains.annotations.NotNull") || importReference.equals("org.jetbrains.annotations.Nullable");
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2020 David Allison <davidallisongithub@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 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 GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.ichi2.anki.lint.utils;
|
||||
|
||||
import com.android.tools.lint.client.api.UElementHandler;
|
||||
import com.android.tools.lint.detector.api.Detector;
|
||||
import com.android.tools.lint.detector.api.JavaContext;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.uast.UElement;
|
||||
import org.jetbrains.uast.UImportStatement;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ImportStatementDetector extends Detector {
|
||||
|
||||
public abstract void visitImportStatement(@NotNull JavaContext context, @NotNull UImportStatement node);
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Class<? extends UElement>> getApplicableUastTypes() {
|
||||
return Collections.singletonList(UImportStatement.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UElementHandler createUastHandler(@NotNull JavaContext context) {
|
||||
return new UElementHandler() {
|
||||
@Override
|
||||
public void visitImportStatement(@NotNull UImportStatement node) {
|
||||
// do not call super
|
||||
ImportStatementDetector.this.visitImportStatement(context, node);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (c) 2020 David Allison <davidallisongithub@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation; either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* 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 GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.ichi2.anki.lint.rules;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.android.tools.lint.checks.infrastructure.TestFile.JavaTestFile.create;
|
||||
import static com.android.tools.lint.checks.infrastructure.TestLintTask.lint;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class InconsistentAnnotationUsageTest {
|
||||
|
||||
private final String mNotNullUsage = " \n" +
|
||||
"package java.util; \n" +
|
||||
" \n" +
|
||||
"import org.jetbrains.annotations.NotNull; \n";
|
||||
|
||||
private final String mNullable = " \n" +
|
||||
"package java.util; \n" +
|
||||
" \n" +
|
||||
"import org.jetbrains.annotations.Nullable; \n";
|
||||
|
||||
// Should be OK
|
||||
private final String mContract = " \n" +
|
||||
"package java.util; \n" +
|
||||
" \n" +
|
||||
"import org.jetbrains.annotations.Contract; \n";
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void showsErrorForNotNull() {
|
||||
lint()
|
||||
.allowMissingSdk()
|
||||
.allowCompilationErrors()
|
||||
.files(create(mNotNullUsage))
|
||||
.issues(InconsistentAnnotationUsage.ISSUE)
|
||||
.run()
|
||||
.expectErrorCount(1)
|
||||
.check(output -> {
|
||||
assertTrue(output.contains(InconsistentAnnotationUsage.ID));
|
||||
assertTrue(output.contains(InconsistentAnnotationUsage.DESCRIPTION));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showsErrorForNullable() {
|
||||
lint()
|
||||
.allowMissingSdk()
|
||||
.allowCompilationErrors()
|
||||
.files(create(mNullable))
|
||||
.issues(InconsistentAnnotationUsage.ISSUE)
|
||||
.run()
|
||||
.expectErrorCount(1)
|
||||
.check(output -> {
|
||||
assertTrue(output.contains(InconsistentAnnotationUsage.ID));
|
||||
assertTrue(output.contains(InconsistentAnnotationUsage.DESCRIPTION));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noErrorForContract() {
|
||||
lint()
|
||||
.allowMissingSdk()
|
||||
.allowCompilationErrors()
|
||||
.files(create(mContract))
|
||||
.issues(InconsistentAnnotationUsage.ISSUE)
|
||||
.run()
|
||||
.expectErrorCount(0);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user