func resolveMappings()

in internal/r8/deobfuscator.go [93:161]


func resolveMappings(types map[string]StacktraceType, mapReader io.Reader) error {
	scanner := bufio.NewScanner(mapReader)
	var currentType *StacktraceType

	for scanner.Scan() {
		line := scanner.Text()
		typeMatch := typePattern.FindStringSubmatch(line)
		if typeMatch != nil {
			// Found a class declaration within the map.
			obfuscatedName := typeMatch[2]
			stacktraceType, ok := types[obfuscatedName]
			if ok {
				// The class found is also in the stacktrace.
				currentType = &stacktraceType
				for _, frames := range stacktraceType.methods {
					for _, frame := range frames {
						if frame.Original == nil {
							frame.Original = &modelpb.Original{}
						}
						// Multiple frames might point to the same class, so we need to deobfuscate the class name for them all.
						frame.Original.Classname = obfuscatedName
						frame.Classname = typeMatch[1]
						frame.SourcemapUpdated = true
					}
				}
			} else {
				// The class found is not part of the stacktrace. We need to clear the current type to avoid looping
				// through this class' methods, as R8 maps list the classes' methods right below the class definition.
				currentType = nil
			}
		} else if currentType != nil {
			// We found a class in the map that is also in the stacktrace, so we enter here to loop through its methods.
			methodMatch := methodPattern.FindStringSubmatch(line)
			if methodMatch != nil {
				// We found a method definition.
				sourceFileStart := methodMatch[1]
				sourceFileEnd := methodMatch[2]
				methodObfuscatedName := methodMatch[4]
				methodRealName := methodMatch[3]
				methodKey := methodObfuscatedName
				if sourceFileStart != "" && sourceFileStart == sourceFileEnd {
					// This method might be compressed, in other words, its deobfuscated form might have multiple lines.
					methodKey += ":" + sourceFileStart
				}
				frames, ok := currentType.methods[methodKey]
				if ok {
					// We found this method in the stacktrace too. Since a method might be referenced multiple times
					// in a single stacktrace, we must make sure to deobfuscate them all.
					for _, frame := range frames {
						if frame.Original.Function == "" {
							frame.Original.Function = methodObfuscatedName
							frame.Function = methodRealName
						} else {
							// If it enters here, it means that this method is compressed and its first line was set
							// previously, so now we have to append extra lines to it.
							frame.Function += "\n" + methodRealName
						}
					}
				}
			}
		}
	}

	if err := scanner.Err(); err != nil {
		return err
	}

	return nil
}