| 145 | # an Argument namedtuple. None if it was unable to find the argument |
| 146 | # |
| 147 | def parseArgumentStartingAt(lines, startPos): |
| 148 | |
| 149 | # The algorithm uses the heuristic of assuming that the argument ends |
| 150 | # when it finds a terminating character (either a comma or right parenthesis) |
| 151 | # in a position where the relative parenthesis/curly braces/bracket depth is 0 |
| 152 | # The latter constraint prevents false positives where function calls are used |
| 153 | # to generate the parameter (i.e. log("number is %d", calculate(a, b))) |
| 154 | parenDepth = 0 |
| 155 | curlyDepth = 0 |
| 156 | bracketDepth = 0 |
| 157 | inQuotes = False |
| 158 | argSrcStr = "" |
| 159 | |
| 160 | offset = startPos.offset |
| 161 | for lineNum in range(startPos.lineNum, len(lines)): |
| 162 | line = lines[lineNum] |
| 163 | |
| 164 | prevWasEscape = False |
| 165 | for i in range(offset, len(line)): |
| 166 | c = line[i] |
| 167 | argSrcStr = argSrcStr + c |
| 168 | |
| 169 | # If it's an escape, we don't care what comes after it |
| 170 | if c == "\\" or prevWasEscape: |
| 171 | prevWasEscape = not prevWasEscape |
| 172 | continue |
| 173 | |
| 174 | # Start counting depths |
| 175 | if c == "\"": |
| 176 | inQuotes = not inQuotes |
| 177 | |
| 178 | # Don't count curlies and parenthesis when in quotes |
| 179 | if inQuotes: |
| 180 | continue |
| 181 | |
| 182 | if c == "{": |
| 183 | curlyDepth = curlyDepth + 1 |
| 184 | elif c == "}": |
| 185 | curlyDepth = curlyDepth - 1 |
| 186 | elif c == "(": |
| 187 | parenDepth = parenDepth + 1 |
| 188 | elif c == ")" and parenDepth > 0: |
| 189 | parenDepth = parenDepth - 1 |
| 190 | elif c == "[": |
| 191 | bracketDepth = bracketDepth + 1 |
| 192 | elif c == "]": |
| 193 | bracketDepth = bracketDepth - 1 |
| 194 | elif (c == "," or c == ")") and curlyDepth == 0 \ |
| 195 | and parenDepth == 0 and bracketDepth == 0: |
| 196 | # found it! |
| 197 | endPos = FilePosition(lineNum, i) |
| 198 | return Argument(argSrcStr[:-1], startPos, endPos) |
| 199 | |
| 200 | # Couldn't find it on this line, must be on the next |
| 201 | offset = 0 |
| 202 | |
| 203 | return None |
| 204 | |