diff --git a/ruby/ql/src/queries/modeling/internal/Types.qll b/ruby/ql/src/queries/modeling/internal/Types.qll index 65249d8d944..2d2d74929d7 100644 --- a/ruby/ql/src/queries/modeling/internal/Types.qll +++ b/ruby/ql/src/queries/modeling/internal/Types.qll @@ -63,8 +63,8 @@ module Types { methodReturnsType(methodNode, classNode) | type1 = classNode.getQualifiedName() and - type2 = Util::getAnAccessPathPrefix(methodNode.asExpr().getExpr()) and - path = "Method[" + Util::getNormalizedMethodName(methodNode) + "].ReturnValue" + type2 = Util::getAnAccessPathPrefix(methodNode) and + path = Util::getMethodPath(methodNode) + ".ReturnValue" ) } @@ -111,25 +111,8 @@ module Types { methodTakesParameterOfType(methodNode, classNode, parameterNode) | type1 = classNode.getQualifiedName() and - type2 = Util::getAnAccessPathPrefix(methodNode.asExpr().getExpr()) and - ( - exists(int paramIdx | paramIdx = parameterNode.getParameter().getPosition() | - path = - "Method[" + Util::getNormalizedMethodName(methodNode) + "].Parameter[" + paramIdx + "]" - ) - or - // TODO: verify that this works - exists(string kwName | - kwName = parameterNode.getParameter().(Ast::KeywordParameter).getName() - | - path = - "Method[" + Util::getNormalizedMethodName(methodNode) + "].Parameter[" + kwName + ":]" - ) - or - // TODO: verify that this works - parameterNode.getParameter() instanceof Ast::BlockParameter and - path = "Method[" + Util::getNormalizedMethodName(methodNode) + "].Parameter[block]" - ) + type2 = Util::getAnAccessPathPrefix(methodNode) and + path = Util::getMethodPath(methodNode) + "." + Util::getParameterPath(parameterNode) ) } @@ -168,10 +151,8 @@ module Types { methodYieldsType(methodNode, argIdx, classNode) | type1 = classNode.getQualifiedName() and - type2 = Util::getAnAccessPathPrefix(methodNode.asExpr().getExpr()) and - path = - "Method[" + Util::getNormalizedMethodName(methodNode) + "].Argument[block].Parameter[" + - argIdx + "]" + type2 = Util::getAnAccessPathPrefix(methodNode) and + path = Util::getMethodPath(methodNode) + ".Argument[block].Parameter[" + argIdx + "]" ) } diff --git a/ruby/ql/src/queries/modeling/internal/Util.qll b/ruby/ql/src/queries/modeling/internal/Util.qll index c71e8566853..777791ab600 100644 --- a/ruby/ql/src/queries/modeling/internal/Util.qll +++ b/ruby/ql/src/queries/modeling/internal/Util.qll @@ -2,7 +2,7 @@ private import ruby // `SomeClass#initialize` methods are usually called indirectly via // `SomeClass.new`, so we need to account for this when generating access paths -string getNormalizedMethodName(DataFlow::MethodNode methodNode) { +private string getNormalizedMethodName(DataFlow::MethodNode methodNode) { exists(string actualMethodName | actualMethodName = methodNode.getMethodName() | if actualMethodName = "initialize" then result = "new" else result = actualMethodName ) @@ -14,12 +14,34 @@ private string getAccessPathSuffix(Ast::MethodBase method) { else result = "" } -string getAnAccessPathPrefix(Ast::MethodBase method) { - result = - method.getEnclosingModule().(Ast::ConstantWriteAccess).getAQualifiedName() + - getAccessPathSuffix(method) +string getAnAccessPathPrefix(DataFlow::MethodNode methodNode) { + exists(Ast::MethodBase method | method = methodNode.asExpr().getExpr() | + result = + method.getEnclosingModule().(Ast::ConstantWriteAccess).getAQualifiedName() + + getAccessPathSuffix(method) + ) } class RelevantFile extends File { RelevantFile() { not this.getRelativePath().regexpMatch(".*/?test(case)?s?/.*") } } + +string getMethodPath(DataFlow::MethodNode methodNode) { + result = "Method[" + getNormalizedMethodName(methodNode) + "]" +} + +string getParameterPath(DataFlow::ParameterNode paramNode) { + exists(Ast::Parameter param, string paramSpec | + param = paramNode.asParameter() and + ( + paramSpec = param.getPosition().toString() + or + paramSpec = param.(Ast::KeywordParameter).getName() + ":" + or + param instanceof Ast::BlockParameter and + paramSpec = "block" + ) + | + result = "Parameter[" + paramSpec + "]" + ) +}