diff --git a/src/dscanner/analysis/incorrect_infinite_range.d b/src/dscanner/analysis/incorrect_infinite_range.d index 1df6b3e..ce3e339 100644 --- a/src/dscanner/analysis/incorrect_infinite_range.d +++ b/src/dscanner/analysis/incorrect_infinite_range.d @@ -46,6 +46,8 @@ final class IncorrectInfiniteRangeCheck : BaseAnalyzer { if (fb.specifiedFunctionBody && fb.specifiedFunctionBody.blockStatement !is null) visit(fb.specifiedFunctionBody.blockStatement); + else if (fb.shortenedFunctionBody && fb.shortenedFunctionBody.expression !is null) + visitReturnExpression(fb.shortenedFunctionBody.expression); } override void visit(const BlockStatement bs) @@ -63,9 +65,14 @@ final class IncorrectInfiniteRangeCheck : BaseAnalyzer { if (inStruct == 0 || line == size_t.max) // not within a struct yet return; - if (!rs.expression || rs.expression.items.length != 1) + visitReturnExpression(rs.expression); + } + + void visitReturnExpression(const Expression expression) + { + if (!expression || expression.items.length != 1) return; - UnaryExpression unary = cast(UnaryExpression) rs.expression.items[0]; + UnaryExpression unary = cast(UnaryExpression) expression.items[0]; if (unary is null) return; if (unary.primaryExpression is null) diff --git a/src/dscanner/analysis/properly_documented_public_functions.d b/src/dscanner/analysis/properly_documented_public_functions.d index 70c2d2a..a27f313 100644 --- a/src/dscanner/analysis/properly_documented_public_functions.d +++ b/src/dscanner/analysis/properly_documented_public_functions.d @@ -55,6 +55,8 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer override void visit(const UnaryExpression decl) { + import std.algorithm.searching : canFind; + const IdentifierOrTemplateInstance iot = safeAccess(decl) .functionCallExpression.unaryExpression.primaryExpression .identifierOrTemplateInstance; @@ -69,6 +71,12 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer return t; } + if (inThrowExpression && decl.newExpression && decl.newExpression.type && + !thrown.canFind!(a => a == decl.newExpression.type)) + { + thrown ~= decl.newExpression.type; + } + // enforce(condition); if (iot && iot.identifier.text == "enforce") { @@ -187,7 +195,7 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer if (nestedFuncs == 1) thrown.length = 0; - // detect ThrowStatement only if not nothrow + // detect ThrowExpression only if not nothrow if (!decl.attributes.any!(a => a.attribute.text == "nothrow")) { decl.accept(this); @@ -228,20 +236,14 @@ final class ProperlyDocumentedPublicFunctions : BaseAnalyzer .array; } - override void visit(const ThrowStatement ts) + override void visit(const ThrowExpression ts) { - import std.algorithm.searching : canFind; - + const wasInThrowExpression = inThrowExpression; + inThrowExpression = true; + scope (exit) + inThrowExpression = wasInThrowExpression; ts.accept(this); - if (ts.expression && ts.expression.items.length == 1) - if (const UnaryExpression ue = cast(UnaryExpression) ts.expression.items[0]) - { - if (ue.newExpression && ue.newExpression.type && - !thrown.canFind!(a => a == ue.newExpression.type)) - { - thrown ~= ue.newExpression.type; - } - } + inThrowExpression = false; } alias visit = BaseAnalyzer.visit; @@ -260,6 +262,7 @@ private: } Function lastSeenFun; + bool inThrowExpression; const(Type)[] thrown; // find invalid ddoc parameters (i.e. they don't occur in a function declaration) diff --git a/src/dscanner/analysis/unused.d b/src/dscanner/analysis/unused.d index f1d00b6..890a764 100644 --- a/src/dscanner/analysis/unused.d +++ b/src/dscanner/analysis/unused.d @@ -48,7 +48,9 @@ abstract class UnusedIdentifierCheck : BaseAnalyzer override void visit(const FunctionDeclaration functionDec) { pushScope(); - if (functionDec.functionBody && functionDec.functionBody.specifiedFunctionBody) + if (functionDec.functionBody + && (functionDec.functionBody.specifiedFunctionBody + || functionDec.functionBody.shortenedFunctionBody)) { immutable bool ias = inAggregateScope; inAggregateScope = false; @@ -74,7 +76,7 @@ abstract class UnusedIdentifierCheck : BaseAnalyzer mixin PartsUseVariables!StaticIfCondition; mixin PartsUseVariables!StructDeclaration; mixin PartsUseVariables!TemplateArgumentList; - mixin PartsUseVariables!ThrowStatement; + mixin PartsUseVariables!ThrowExpression; mixin PartsUseVariables!CastExpression; override void visit(const SwitchStatement switchStatement) diff --git a/src/dscanner/astprinter.d b/src/dscanner/astprinter.d index 020e083..50bff99 100644 --- a/src/dscanner/astprinter.d +++ b/src/dscanner/astprinter.d @@ -1146,7 +1146,7 @@ class XMLPrinter : ASTVisitor override void visit(const TemplateValueParameter templateValueParameter) { mixin (tagAndAccept!"templateValueParameter"); } override void visit(const TernaryExpression ternaryExpression) { mixin (tagAndAccept!"ternaryExpression"); } override void visit(const TypeIdentifierPart typeIdentifierPart) { mixin (tagAndAccept!"typeIdentifierPart"); } - override void visit(const ThrowStatement throwStatement) { mixin (tagAndAccept!"throwStatement"); } + override void visit(const ThrowExpression throwExpression) { mixin (tagAndAccept!"throwExpression"); } override void visit(const TryStatement tryStatement) { mixin (tagAndAccept!"tryStatement"); } override void visit(const TemplateInstance templateInstance) { mixin (tagAndAccept!"templateInstance"); } override void visit(const TypeofExpression typeofExpression) { mixin (tagAndAccept!"typeofExpression"); } override void visit(const TypeSpecialization typeSpecialization) { mixin (tagAndAccept!"typeSpecialization"); } override void visit(const TraitsExpression traitsExpression) { mixin (tagAndAccept!"traitsExpression"); } override void visit(const Vector vector) { mixin (tagAndAccept!"vector"); }