diff --git a/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.spec.tsx b/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.spec.tsx index b9e3ae440ebe89..57b7e58d05ebc9 100644 --- a/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.spec.tsx +++ b/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.spec.tsx @@ -122,6 +122,45 @@ describe('RawStacktraceContent', () => { ); }); + it('renders dart example', () => { + const dartData: StacktraceType = { + hasSystemFrames: false, + framesOmitted: null, + registers: {}, + frames: [ + FrameFixture({ + function: 'doThing', + package: 'flutter', + lineNo: 300, + colNo: 2, + filename: 'ink_well.dart', + absPath: 'package:flutter/src/material/ink_well.dart', + platform: undefined, + }), + FrameFixture({ + function: '', + package: '', + platform: undefined, + }), + FrameFixture({ + function: 'main', + package: 'sentry_flutter', + lineNo: 778, + colNo: 5, + filename: 'main.dart', + absPath: 'package:sentry_flutter/main.dart', + platform: undefined, + }), + ], + }; + expect(displayRawContent(dartData, 'dart', exception)).toEqual( + `Error: an error occurred + #0 main (package:sentry_flutter/main.dart:778:5) + #1 + #2 doThing (package:flutter/src/material/ink_well.dart:300:2)` + ); + }); + const inAppFrame = (fnName, line) => FrameFixture({ function: fnName, diff --git a/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.tsx b/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.tsx index d1494b9f83400d..27816548da83c8 100644 --- a/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.tsx +++ b/static/app/components/events/interfaces/crashContent/stackTrace/rawContent.tsx @@ -98,6 +98,33 @@ export function getJavaFrame(frame: Frame): string { return result; } +export function getDartFrame(frame: Frame, frameIdxFromEnd: number): string { + let result = ` #${frameIdxFromEnd}`; + + if (frame.function === '') { + return `${result} ${frame.function}`; + } + + if (defined(frame.function)) { + result += ' ' + frame.function; + } + if (defined(frame.absPath)) { + result += ' ('; + + result += frame.absPath; + if (defined(frame.lineNo) && frame.lineNo >= 0) { + result += ':' + frame.lineNo; + } + if (defined(frame.colNo) && frame.colNo >= 0) { + result += ':' + frame.colNo; + } + + result += ')'; + } + + return result; +} + function ljust(str: string, len: number) { return str + Array(Math.max(0, len - str.length) + 1).join(' '); } @@ -138,7 +165,12 @@ function getPreamble(exception: ExceptionValue, platform: string | undefined): s } } -function getFrame(frame: Frame, frameIdx: number, platform: string | undefined): string { +function getFrame( + frame: Frame, + frameIdx: number, + frameIdxFromEnd: number, + platform: string | undefined +): string { if (frame.platform) { platform = frame.platform; } @@ -153,6 +185,8 @@ function getFrame(frame: Frame, frameIdx: number, platform: string | undefined): return getPythonFrame(frame); case 'java': return getJavaFrame(frame); + case 'dart': + return getDartFrame(frame, frameIdxFromEnd); case 'objc': // fallthrough case 'cocoa': @@ -180,7 +214,7 @@ export default function displayRawContent( : rawFrames; const frames = framesToUse.map((frame, frameIdx) => - getFrame(frame, frameIdx, platform) + getFrame(frame, frameIdx, framesToUse.length - frameIdx - 1, platform) ); if (platform !== 'python') {