From aa7bdf81c614116a075d450c074bfc9dfc191fb4 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Thu, 24 May 2018 19:38:30 +0200 Subject: [PATCH 1/2] fix #635 - Check for documented `throw` could also detect calls to `enforce` --- .../properly_documented_public_functions.d | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/src/dscanner/analysis/properly_documented_public_functions.d b/src/dscanner/analysis/properly_documented_public_functions.d index aed72f5..c1b0397 100644 --- a/src/dscanner/analysis/properly_documented_public_functions.d +++ b/src/dscanner/analysis/properly_documented_public_functions.d @@ -51,6 +51,50 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer postCheckSeenDdocParams(); } + override void visit(const UnaryExpression decl) + { + const IdentifierOrTemplateInstance iot = safeAccess(decl) + .functionCallExpression.unaryExpression.primaryExpression + .identifierOrTemplateInstance; + + // enforce(condition); + if (iot && iot.identifier.text == "enforce") + { + Type tt = new Type; + tt.type2 = new Type2; + tt.type2.typeIdentifierPart = new TypeIdentifierPart; + tt.type2.typeIdentifierPart.identifierOrTemplateInstance = + new IdentifierOrTemplateInstance; + tt.type2.typeIdentifierPart.identifierOrTemplateInstance.identifier = + Token(tok!"identifier", "Exception", 0, 0, 0); + thrown ~= tt; + } + else if (iot && iot.templateInstance && iot.templateInstance.identifier.text == "enforce") + { + // enforce!Type(condition); + if (const TemplateSingleArgument tsa = safeAccess(iot.templateInstance) + .templateArguments.templateSingleArgument) + { + Type tt = new Type; + tt.type2 = new Type2; + tt.type2.typeIdentifierPart = new TypeIdentifierPart; + tt.type2.typeIdentifierPart.identifierOrTemplateInstance = + new IdentifierOrTemplateInstance; + tt.type2.typeIdentifierPart.identifierOrTemplateInstance.identifier = + tsa.token; + thrown ~= tt; + } + // 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 +1111,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 { From a0010d6a8a80fc53e89bdc4407a0aed54957a98a Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Fri, 25 May 2018 23:36:02 +0200 Subject: [PATCH 2/2] fix tab and create routine for gen exception type --- .../properly_documented_public_functions.d | 80 +++++++++---------- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/src/dscanner/analysis/properly_documented_public_functions.d b/src/dscanner/analysis/properly_documented_public_functions.d index c1b0397..7b1f86e 100644 --- a/src/dscanner/analysis/properly_documented_public_functions.d +++ b/src/dscanner/analysis/properly_documented_public_functions.d @@ -51,49 +51,45 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer postCheckSeenDdocParams(); } - override void visit(const UnaryExpression decl) - { - const IdentifierOrTemplateInstance iot = safeAccess(decl) - .functionCallExpression.unaryExpression.primaryExpression - .identifierOrTemplateInstance; + override void visit(const UnaryExpression decl) + { + const IdentifierOrTemplateInstance iot = safeAccess(decl) + .functionCallExpression.unaryExpression.primaryExpression + .identifierOrTemplateInstance; - // enforce(condition); - if (iot && iot.identifier.text == "enforce") - { - Type tt = new Type; - tt.type2 = new Type2; - tt.type2.typeIdentifierPart = new TypeIdentifierPart; - tt.type2.typeIdentifierPart.identifierOrTemplateInstance = - new IdentifierOrTemplateInstance; - tt.type2.typeIdentifierPart.identifierOrTemplateInstance.identifier = - Token(tok!"identifier", "Exception", 0, 0, 0); - thrown ~= tt; - } - else if (iot && iot.templateInstance && iot.templateInstance.identifier.text == "enforce") - { - // enforce!Type(condition); - if (const TemplateSingleArgument tsa = safeAccess(iot.templateInstance) - .templateArguments.templateSingleArgument) - { - Type tt = new Type; - tt.type2 = new Type2; - tt.type2.typeIdentifierPart = new TypeIdentifierPart; - tt.type2.typeIdentifierPart.identifierOrTemplateInstance = - new IdentifierOrTemplateInstance; - tt.type2.typeIdentifierPart.identifierOrTemplateInstance.identifier = - tsa.token; - thrown ~= tt; - } - // 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); - } + 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) {