diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py index 173b5a60111..a4c3ea516f5 100644 --- a/share/qtcreator/debugger/cdbbridge.py +++ b/share/qtcreator/debugger/cdbbridge.py @@ -353,9 +353,6 @@ class Dumper(DumperBase): self.ptrSize = lambda: size return size - def put(self, stuff): - self.output += stuff - def stripQintTypedefs(self, typeName): if typeName.startswith('qint'): prefix = '' @@ -423,7 +420,7 @@ class Dumper(DumperBase): self.setVariableFetchingOptions(args) - self.output = '' + self.output = [] self.currentIName = 'local' self.put('data=[') @@ -445,10 +442,11 @@ class Dumper(DumperBase): self.qtNamespaceToReport = self.qtNamespace() if self.qtNamespaceToReport: - self.output += ',qtnamespace="%s"' % self.qtNamespaceToReport + self.put(',qtnamespace="%s"' % self.qtNamespaceToReport) self.qtNamespaceToReport = None - self.reportResult(self.output, args) + self.reportResult(''.join(self.output), args) + self.output = [] def report(self, stuff): sys.stdout.write(stuff + "\n") diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 22f3f732d87..8beba72113a 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -112,7 +112,7 @@ class Children(): self.d.currentNumChild = self.savedNumChild self.d.currentMaxNumChild = self.savedMaxNumChild if self.d.isCli: - self.d.output += '\n' + ' ' * self.d.indent + self.d.put('\n' + ' ' * self.d.indent) self.d.put(self.d.childrenSuffix) return True @@ -173,7 +173,7 @@ class DumperBase(): self.displayStringLimit = 100 self.useTimeStamps = False - self.output = '' + self.output = [] self.typesReported = {} self.typesToReport = {} self.qtNamespaceToReport = None @@ -309,9 +309,9 @@ class DumperBase(): self.putField('name', item.name) else: self.indent += 1 - self.output += '\n' + ' ' * self.indent + self.put('\n' + ' ' * self.indent) if isinstance(item.name, str): - self.output += item.name + ' = ' + self.put(item.name + ' = ') item.savedIName = self.currentIName item.savedValue = self.currentValue item.savedType = self.currentType @@ -869,7 +869,12 @@ class DumperBase(): self.putPlainChildren(value) def put(self, stuff): - self.output += stuff + self.output.append(stuff) + + def takeOutput(self): + res = '\n'.join(self.output) + self.output = [] + return res def check(self, exp): if not exp: diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index f142a30fb4a..f5e260c54d5 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -175,24 +175,6 @@ def importPlainDumpers(args): registerCommand('importPlainDumpers', importPlainDumpers) -class OutputSaver(): - def __init__(self, d): - self.d = d - - def __enter__(self): - self.savedOutput = self.d.output - self.d.output = '' - - def __exit__(self, exType, exValue, exTraceBack): - if self.d.passExceptions and exType is not None: - self.d.showException('OUTPUTSAVER', exType, exValue, exTraceBack) - self.d.output = self.savedOutput - else: - self.savedOutput += self.d.output - self.d.output = self.savedOutput - return False - - ####################################################################### # # The Dumper Class @@ -214,7 +196,7 @@ class Dumper(DumperBase): self.interpreterBreakpointResolvers = [] def prepare(self, args): - self.output = '' + self.output = [] self.setVariableFetchingOptions(args) def fromFrameValue(self, nativeValue): @@ -690,7 +672,7 @@ class Dumper(DumperBase): safePrint(res) return - self.output += 'data=[' + self.put('data=[') partialVar = args.get('partialvar', '') isPartial = len(partialVar) > 0 @@ -713,27 +695,26 @@ class Dumper(DumperBase): self.handleLocals(variables) self.handleWatches(args) - self.output += '],typeinfo=[' + self.put('],typeinfo=[') for name in self.typesToReport.keys(): typeobj = self.typesToReport[name] # Happens e.g. for '(anonymous namespace)::InsertDefOperation' #if not typeobj is None: - # self.output.append('{name="%s",size="%s"}' - # % (self.hexencode(name), typeobj.sizeof)) - self.output += ']' + # self.put('{name="%s",size="%s"}' % (self.hexencode(name), typeobj.sizeof)) + self.put(']') self.typesToReport = {} if self.forceQtNamespace: self.qtNamespaceToReport = self.qtNamespace() if self.qtNamespaceToReport: - self.output += ',qtnamespace="%s"' % self.qtNamespaceToReport + self.put(',qtnamespace="%s"' % self.qtNamespaceToReport) self.qtNamespaceToReport = None - self.output += ',partial="%d"' % isPartial - self.output += ',counts=%s' % self.counts - self.output += ',timings=%s' % self.timings - self.reportResult(self.output, args) + self.put(',partial="%d"' % isPartial) + self.put(',counts=%s' % self.counts) + self.put(',timings=%s' % self.timings) + self.reportResult(''.join(self.output), args) def parseAndEvaluate(self, exp): val = self.nativeParseAndEvaluate(exp) @@ -1321,7 +1302,7 @@ class Dumper(DumperBase): limit = 10000 self.prepare(args) - self.output = '' + self.output = [] i = 0 if extraQml: @@ -1375,58 +1356,60 @@ class Dumper(DumperBase): frame = gdb.newest_frame() self.currentCallContext = None + self.output = [] + self.put('stack={frames=[') while i < limit and frame: - with OutputSaver(self): - name = frame.name() - functionName = '??' if name is None else name - fileName = '' - objfile = '' - symtab = '' - pc = frame.pc() - sal = frame.find_sal() - line = -1 - if sal: - line = sal.line - symtab = sal.symtab - if symtab is not None: - objfile = fromNativePath(symtab.objfile.filename) - fullname = symtab.fullname() - if fullname is None: - fileName = '' - else: - fileName = fromNativePath(fullname) + name = frame.name() + functionName = '??' if name is None else name + fileName = '' + objfile = '' + symtab = '' + pc = frame.pc() + sal = frame.find_sal() + line = -1 + if sal: + line = sal.line + symtab = sal.symtab + if symtab is not None: + objfile = fromNativePath(symtab.objfile.filename) + fullname = symtab.fullname() + if fullname is None: + fileName = '' + else: + fileName = fromNativePath(fullname) - if self.nativeMixed and functionName == 'qt_qmlDebugMessageAvailable': - interpreterStack = self.extractInterpreterStack() - #print('EXTRACTED INTEPRETER STACK: %s' % interpreterStack) - for interpreterFrame in interpreterStack.get('frames', []): - function = interpreterFrame.get('function', '') - fileName = interpreterFrame.get('file', '') - language = interpreterFrame.get('language', '') - lineNumber = interpreterFrame.get('line', 0) - context = interpreterFrame.get('context', 0) + if self.nativeMixed and functionName == 'qt_qmlDebugMessageAvailable': + interpreterStack = self.extractInterpreterStack() + #print('EXTRACTED INTEPRETER STACK: %s' % interpreterStack) + for interpreterFrame in interpreterStack.get('frames', []): + function = interpreterFrame.get('function', '') + fileName = interpreterFrame.get('file', '') + language = interpreterFrame.get('language', '') + lineNumber = interpreterFrame.get('line', 0) + context = interpreterFrame.get('context', 0) - self.put(('frame={function="%s",file="%s",' - 'line="%s",language="%s",context="%s"}') - % (function, self.hexencode(fileName), lineNumber, language, context)) + self.put(('frame={function="%s",file="%s",' + 'line="%s",language="%s",context="%s"}') + % (function, self.hexencode(fileName), lineNumber, language, context)) - if False and self.isInternalInterpreterFrame(functionName): - frame = frame.older() - self.put(('frame={address="0x%x",function="%s",' - 'file="%s",line="%s",' - 'module="%s",language="c",usable="0"}') % - (pc, functionName, fileName, line, objfile)) - i += 1 - frame = frame.older() - continue + if False and self.isInternalInterpreterFrame(functionName): + frame = frame.older() + self.put(('frame={address="0x%x",function="%s",' + 'file="%s",line="%s",' + 'module="%s",language="c",usable="0"}') % + (pc, functionName, fileName, line, objfile)) + i += 1 + frame = frame.older() + continue - self.put(('frame={level="%s",address="0x%x",function="%s",' - 'file="%s",line="%s",module="%s",language="c"}') % - (i, pc, functionName, fileName, line, objfile)) + self.put(('frame={level="%s",address="0x%x",function="%s",' + 'file="%s",line="%s",module="%s",language="c"}') % + (i, pc, functionName, fileName, line, objfile)) frame = frame.older() i += 1 - self.reportResult('stack={frames=[' + self.output + ']}', args) + self.put(']}') + self.reportResult(self.takeOutput(), args) def createResolvePendingBreakpointsHookBreakpoint(self, args): class Resolver(gdb.Breakpoint): @@ -1512,6 +1495,7 @@ class Dumper(DumperBase): onHit=self.tracepointHit, onExpression=lambda tp, expr, val: self.tracepointExpression(tp, expr, val, args)) self.reportResult("tracepoint=%s" % self.resultToMi(tp.dicts()), args) + class CliDumper(Dumper): def __init__(self): Dumper.__init__(self) @@ -1559,16 +1543,18 @@ class CliDumper(Dumper): self.expandableINames = set() self.prepare(args) - self.output = name + ' = ' + self.output = [] + self.put(name + ' = ') value = self.parseAndEvaluate(name) with TopLevelItem(self, name): self.putItem(value) if not self.expandableINames: - return self.output + '\n\nNo drill down available.\n' + self.put('\n\nNo drill down available.\n') + return self.takeOutput() pattern = ' pp ' + name + ' ' + '%s' - return (self.output + return (self.takeOutput() + '\n\nDrill down:\n ' + '\n '.join(pattern % x for x in self.expandableINames) + '\n') diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 032b2242211..cc60ef16de3 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -1270,7 +1270,7 @@ class Dumper(DumperBase): self.reportResult('error="No frame"', args) return - self.output = '' + self.output = [] isPartial = len(self.partialVariable) > 0 self.currentIName = 'local' @@ -1323,7 +1323,7 @@ class Dumper(DumperBase): self.handleWatches(args) self.put('],partial="%d"' % isPartial) - self.reportResult(self.output, args) + self.reportResult(self.takeOutput(), args) def fetchRegisters(self, args=None): @@ -2101,7 +2101,7 @@ class SummaryDumper(Dumper, LogMixin): self.dumpermodules = ['qttypes'] self.loadDumpers({}) - self.output = '' + self.output = [] def report(self, stuff): return # Don't mess up lldb output @@ -2123,12 +2123,12 @@ class SummaryDumper(Dumper, LogMixin): self.expandedINames = [value.name] if expanded else [] savedOutput = self.output - self.output = '' + self.output = [] with TopLevelItem(self, value.name): self.putItem(value) # FIXME: Hook into putField, etc to build up object instead of parsing MI - response = gdbmiparser.parse_response("^ok,summary=%s" % self.output) + response = gdbmiparser.parse_response("^ok,summary=%s" % self.takeOutput())) self.output = savedOutput self.expandedINames = oldExpanded