From 65720ab41fd932638a70c40e1ff4c9dea76283ae Mon Sep 17 00:00:00 2001 From: lucica28 <57060141+lucica28@users.noreply.github.com> Date: Mon, 14 Nov 2022 13:05:19 +0200 Subject: [PATCH] replace libdparse in explicitly annotated unittests check (#44) --- .../analysis/explicitly_annotated_unittests.d | 145 +++++++----------- src/dscanner/analysis/run.d | 7 +- 2 files changed, 60 insertions(+), 92 deletions(-) diff --git a/src/dscanner/analysis/explicitly_annotated_unittests.d b/src/dscanner/analysis/explicitly_annotated_unittests.d index 7ff1f15..5770248 100644 --- a/src/dscanner/analysis/explicitly_annotated_unittests.d +++ b/src/dscanner/analysis/explicitly_annotated_unittests.d @@ -4,124 +4,93 @@ module dscanner.analysis.explicitly_annotated_unittests; -import dparse.lexer; -import dparse.ast; import dscanner.analysis.base; - -import std.stdio; +import dscanner.analysis.helpers; /** * Requires unittests to be explicitly annotated with either @safe or @system */ -final class ExplicitlyAnnotatedUnittestCheck : BaseAnalyzer +extern(C++) class ExplicitlyAnnotatedUnittestCheck(AST) : BaseAnalyzerDmd { + mixin AnalyzerInfo!"explicitly_annotated_unittests"; + alias visit = BaseAnalyzerDmd.visit; + + extern(D) this(string fileName) + { + super(fileName); + } + + override void visit(AST.UnitTestDeclaration d) + { + import dmd.astenums : STC; + + if (!(d.storage_class & STC.safe || d.storage_class & STC.system)) + addErrorMessage(cast(ulong) d.loc.linnum, cast(ulong) d.loc.charnum, + KEY, MESSAGE); + + super.visit(d); + } + +private: enum string KEY = "dscanner.style.explicitly_annotated_unittest"; enum string MESSAGE = "A unittest should be annotated with at least @safe or @system"; - mixin AnalyzerInfo!"explicitly_annotated_unittests"; - - /// - this(BaseAnalyzerArguments args) - { - super(args); - } - - override void visit(const Declaration decl) - { - if (decl.unittest_ !is null) - { - bool isSafeOrSystem; - if (decl.attributes !is null) - foreach (attribute; decl.attributes) - { - if (attribute.atAttribute !is null) - { - const token = attribute.atAttribute.identifier.text; - if (token == "safe" || token == "system") - { - isSafeOrSystem = true; - break; - } - } - } - if (!isSafeOrSystem) - { - auto token = decl.unittest_.findTokenForDisplay(tok!"unittest"); - addErrorMessage(token, KEY, MESSAGE, - [ - AutoFix.insertionBefore(token[0], "@safe ", "Mark unittest @safe"), - AutoFix.insertionBefore(token[0], "@system ", "Mark unittest @system") - ]); - } - } - decl.accept(this); - } - - alias visit = BaseAnalyzer.visit; - } unittest { - import dscanner.analysis.config : Check, disabledConfig, StaticAnalysisConfig; - import dscanner.analysis.helpers : assertAnalyzerWarnings, assertAutoFix; - import std.format : format; import std.stdio : stderr; + import std.format : format; + import dscanner.analysis.config : StaticAnalysisConfig, Check, disabledConfig; + import dscanner.analysis.helpers : assertAnalyzerWarnings; StaticAnalysisConfig sac = disabledConfig(); sac.explicitly_annotated_unittests = Check.enabled; - assertAnalyzerWarnings(q{ + assertAnalyzerWarningsDMD(q{ + + @disable foo() {} + @safe unittest {} @system unittest {} pure nothrow @system @nogc unittest {} - unittest {} /+ - ^^^^^^^^ [warn]: %s +/ - pure nothrow @nogc unittest {} /+ - ^^^^^^^^ [warn]: %s +/ - }c.format( - ExplicitlyAnnotatedUnittestCheck.MESSAGE, - ExplicitlyAnnotatedUnittestCheck.MESSAGE, - ), sac); + unittest {} // [warn]: A unittest should be annotated with at least @safe or @system + pure nothrow @nogc unittest {} // [warn]: A unittest should be annotated with at least @safe or @system + }c, sac); // nested - assertAnalyzerWarnings(q{ + assertAnalyzerWarningsDMD(q{ struct Foo { @safe unittest {} @system unittest {} - unittest {} /+ - ^^^^^^^^ [warn]: %s +/ - pure nothrow @nogc unittest {} /+ - ^^^^^^^^ [warn]: %s +/ - } - }c.format( - ExplicitlyAnnotatedUnittestCheck.MESSAGE, - ExplicitlyAnnotatedUnittestCheck.MESSAGE, - ), sac); - - - // nested - assertAutoFix(q{ - unittest {} // fix:0 - pure nothrow @nogc unittest {} // fix:0 - - struct Foo - { - unittest {} // fix:1 - pure nothrow @nogc unittest {} // fix:1 - } - }c, q{ - @safe unittest {} // fix:0 - pure nothrow @nogc @safe unittest {} // fix:0 - - struct Foo - { - @system unittest {} // fix:1 - pure nothrow @nogc @system unittest {} // fix:1 + unittest {} // [warn]: A unittest should be annotated with at least @safe or @system + pure nothrow @nogc unittest {} // [warn]: A unittest should be annotated with at least @safe or @system } }c, sac); + // TODO: Check and fix + //// nested + //assertAutoFix(q{ + //unittest {} // fix:0 + //pure nothrow @nogc unittest {} // fix:0 + + //struct Foo + //{ + //unittest {} // fix:1 + //pure nothrow @nogc unittest {} // fix:1 + //} + //}c, q{ + //@safe unittest {} // fix:0 + //pure nothrow @nogc @safe unittest {} // fix:0 + + //struct Foo + //{ + //@system unittest {} // fix:1 + //pure nothrow @nogc @system unittest {} // fix:1 + //} + //}c, sac); + stderr.writeln("Unittest for ExplicitlyAnnotatedUnittestCheck passed."); } diff --git a/src/dscanner/analysis/run.d b/src/dscanner/analysis/run.d index 05640e2..f617576 100644 --- a/src/dscanner/analysis/run.d +++ b/src/dscanner/analysis/run.d @@ -945,10 +945,6 @@ private BaseAnalyzer[] getAnalyzersForModuleAndConfig(string fileName, checks ~= new AutoFunctionChecker(args.setSkipTests( analysisConfig.auto_function_check == Check.skipTests && !ut)); - if (moduleName.shouldRun!ExplicitlyAnnotatedUnittestCheck(analysisConfig)) - checks ~= new ExplicitlyAnnotatedUnittestCheck(args.setSkipTests( - analysisConfig.explicitly_annotated_unittests == Check.skipTests && !ut)); - if (moduleName.shouldRun!ProperlyDocumentedPublicFunctions(analysisConfig)) checks ~= new ProperlyDocumentedPublicFunctions(args.setSkipTests( analysisConfig.properly_documented_public_functions == Check.skipTests && !ut)); @@ -1326,6 +1322,9 @@ MessageSet analyzeDmd(string fileName, ASTBase.Module m, const char[] moduleName if (moduleName.shouldRunDmd!(LengthSubtractionCheck!ASTBase)(config)) visitors ~= new LengthSubtractionCheck!ASTBase(fileName); + if (moduleName.shouldRunDmd!(ExplicitlyAnnotatedUnittestCheck!ASTBase)(config)) + visitors ~= new ExplicitlyAnnotatedUnittestCheck!ASTBase(fileName); + foreach (visitor; visitors) { m.accept(visitor);