diff --git a/src/dscanner/analysis/properly_documented_public_functions.d b/src/dscanner/analysis/properly_documented_public_functions.d index aed72f5..7b1f86e 100644 --- a/src/dscanner/analysis/properly_documented_public_functions.d +++ b/src/dscanner/analysis/properly_documented_public_functions.d @@ -51,6 +51,46 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer postCheckSeenDdocParams(); } + override void visit(const UnaryExpression decl) + { + const IdentifierOrTemplateInstance iot = safeAccess(decl) + .functionCallExpression.unaryExpression.primaryExpression + .identifierOrTemplateInstance; + + Type newNamedType(N)(N name) + { + Type t = new Type; + t.type2 = new Type2; + t.type2.typeIdentifierPart = new TypeIdentifierPart; + t.type2.typeIdentifierPart.identifierOrTemplateInstance = new IdentifierOrTemplateInstance; + t.type2.typeIdentifierPart.identifierOrTemplateInstance.identifier = name; + return t; + } + + // enforce(condition); + if (iot && iot.identifier.text == "enforce") + { + thrown ~= newNamedType(Token(tok!"identifier", "Exception", 0, 0, 0)); + } + else if (iot && iot.templateInstance && iot.templateInstance.identifier.text == "enforce") + { + // enforce!Type(condition); + if (const TemplateSingleArgument tsa = safeAccess(iot.templateInstance) + .templateArguments.templateSingleArgument) + { + thrown ~= newNamedType(tsa.token); + } + // enforce!(Type)(condition); + else if (const TemplateArgumentList tal = safeAccess(iot.templateInstance) + .templateArguments.templateArgumentList) + { + if (tal.items.length && tal.items[0].type) + thrown ~= tal.items[0].type; + } + } + decl.accept(this); + } + override void visit(const Declaration decl) { import std.algorithm.searching : any; @@ -1067,6 +1107,83 @@ void bar() // [warn]: %s ), sac); } +unittest +{ + StaticAnalysisConfig sac = disabledConfig; + sac.properly_documented_public_functions = Check.enabled; + + assertAnalyzerWarnings(q{ +/++ +enforce ++/ +void bar() // [warn]: %s +{ + enforce(condition); +} + }c.format( + ProperlyDocumentedPublicFunctions.MISSING_THROW_MESSAGE.format("Exception") + ), sac); +} + +unittest +{ + StaticAnalysisConfig sac = disabledConfig; + sac.properly_documented_public_functions = Check.enabled; + + assertAnalyzerWarnings(q{ +/++ +enforce ++/ +void bar() // [warn]: %s +{ + enforce!AssertError(condition); +} + }c.format( + ProperlyDocumentedPublicFunctions.MISSING_THROW_MESSAGE.format("AssertError") + ), sac); +} + +unittest +{ + StaticAnalysisConfig sac = disabledConfig; + sac.properly_documented_public_functions = Check.enabled; + + assertAnalyzerWarnings(q{ +/++ +enforce ++/ +void bar() // [warn]: %s +{ + enforce!(AssertError)(condition); +} + }c.format( + ProperlyDocumentedPublicFunctions.MISSING_THROW_MESSAGE.format("AssertError") + ), sac); +} + +unittest +{ + StaticAnalysisConfig sac = disabledConfig; + sac.properly_documented_public_functions = Check.enabled; + + assertAnalyzerWarnings(q{ +/++ +enforce ++/ +void foo() // [warn]: %s +{ + void bar() + { + enforce!AssertError(condition); + } + bar(); +} + + }c.format( + ProperlyDocumentedPublicFunctions.MISSING_THROW_MESSAGE.format("AssertError") + ), sac); +} + // https://github.com/dlang-community/D-Scanner/issues/583 unittest {