// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'package:_fe_analyzer_shared/src/scanner/characters.dart'; String categorize(StackTrace st) { List lines = parseStackTrace(st); List notSdk = lines.where((l) => l.uri.scheme != "dart").toList(); return "${notSdk.first.uri.pathSegments.last}/${notSdk.first.line}"; } List parseStackTrace(StackTrace st) { List result = []; List lines = st.toString().split("\n"); for (int i = 0; i < lines.length; i++) { String s = lines[i]; if (s == "") continue; if (s == "...") continue; if (s == "") continue; if (s.startsWith("#")) { int j = 1; for (; j < s.length; j++) { int c = s.codeUnitAt(j); if (c >= $0 && c <= $9) { // #numGoesHere } else { break; } } s = s.substring(j).trim(); int indexOfParen = s.indexOf("("); String method = s.substring(0, indexOfParen).trim(); if (s[s.length - 1] != ")") throw "s"; String uriEtc = s.substring(indexOfParen + 1, s.length - 1); List colonSplit = uriEtc.split(":"); int column = -1; int line = -1; // If last two are numbers it's line and column --- the rest is uri; // if last is number it's line --- the rest is uri // else its all uri. if (uriEtc.length >= 2) { column = int.tryParse(colonSplit[colonSplit.length - 1]) ?? -1; line = int.tryParse(colonSplit[colonSplit.length - 2]) ?? -1; } String uriPart; if (line > -1 && column > -1) { uriPart = colonSplit.take(colonSplit.length - 2).join(":"); } else if (column > -1) { line = column; column = -1; uriPart = colonSplit.take(colonSplit.length - 1).join(":"); } else { uriPart = uriEtc; } StackTraceLine stLine = new StackTraceLine( method, Uri.parse(uriPart), line, column, lines[i]); result.add(stLine); } else { throw "Unexpected line: '$s' in stacktrace: $st"; } } return result; } class StackTraceLine { final String method; final Uri uri; final int line; final int column; final String orgLine; StackTraceLine(this.method, this.uri, this.line, this.column, this.orgLine); }