• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

AlexsanderHamir / prof / 16530231405

25 Jul 2025 07:40PM UTC coverage: 15.814% (-0.7%) from 16.518%
16530231405

push

github

web-flow
Merge pull request #3 from AlexsanderHamir/refactors

Core non-wrapping feature implemented

0 of 160 new or added lines in 9 files covered. (0.0%)

241 of 1524 relevant lines covered (15.81%)

14.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/parser/api.go
1
package parser
2

3
import (
4
        "bufio"
5
        "errors"
6
        "fmt"
7
        "regexp"
8
        "strings"
9

10
        "github.com/AlexsanderHamir/prof/args"
11
        "github.com/AlexsanderHamir/prof/config"
12
        "github.com/AlexsanderHamir/prof/shared"
13
)
14

15
const (
16
        funcNameRegexp       = `\.([^.(]+)(?:\([^)]*\))?$`
17
        floatRegexp          = `\d+(?:\.\d+)?`
18
        header               = "flat  flat%   sum%        cum   cum%"
19
        minProfileLinelength = 6
20
)
21

22
// Line Indexes.
23
const (
24
        flatIndex           = 0
25
        flatPercentageIndex = 1
26
        sumPercentageIndex  = 2
27
        cumIndex            = 3
28
        cumPercentageIndex  = 4
29
        functionNameIndex   = 5
30
)
31

32
var (
33
        funcNameRegexpCompiled = regexp.MustCompile(funcNameRegexp)
34
        floatRegexpCompiled    = regexp.MustCompile(floatRegexp)
35
)
36

37
// ProfileFilter collects filters for extracting function names from a profile.
38
type ProfileFilter struct {
39
        // Include only lines starting with specified prefix
40
        FunctionPrefixes []string
41

42
        // Ignore all functions after the last dot even if includes the above prefix
43
        IgnoreFunctions []string
44
}
45

46
type LineObj struct {
47
        FnName         string
48
        Flat           float64
49
        FlatPercentage float64
50
        SumPercentage  float64
51
        Cum            float64
52
        CumPercentage  float64
53
}
54

55
func TurnLinesIntoObjects(profilePath, profileType string) ([]*LineObj, error) {
×
56
        var lines []string
×
57

×
58
        scanner, file, err := shared.GetScanner(profilePath)
×
59
        if err != nil {
×
60
                return nil, err
×
61
        }
×
62
        defer file.Close()
×
63

×
64
        shouldRemove := true
×
65
        CollectOrRemoveHeader(scanner, profileType, &lines, shouldRemove)
×
66

×
67
        GetAllProfileLines(scanner, &lines)
×
68

×
69
        lineObjs, err := createLineObjects(lines)
×
70
        if err != nil {
×
71
                return nil, fmt.Errorf("failed creating line objects : %w", err)
×
72
        }
×
73

74
        return lineObjs, err
×
75
}
76

77
// GetAllFunctionNames extracts all function names from a profile text file, applying the given filter.
NEW
78
func GetAllFunctionNames(filePath string, filter config.FunctionFilter) (names []string, err error) {
×
79
        scanner, file, err := shared.GetScanner(filePath)
×
80
        if err != nil {
×
81
                return nil, fmt.Errorf("GetAllFunctionNames Failed: %w", err)
×
82
        }
×
83

84
        defer func() {
×
85
                if closeErr := file.Close(); closeErr != nil {
×
86
                        if err == nil {
×
87
                                err = fmt.Errorf("file close failed: %w", closeErr)
×
88
                        }
×
89
                }
90
        }()
91

92
        ignoreSet := getFilterSets(filter.IgnoreFunctions)
×
93

×
94
        var foundHeader bool
×
95
        for scanner.Scan() {
×
96
                line := strings.TrimSpace(scanner.Text())
×
97
                if line == "" {
×
98
                        continue
×
99
                }
100

101
                if strings.Contains(line, header) {
×
102
                        foundHeader = true
×
103
                        continue
×
104
                }
105

106
                // Skip lines until we find the header, then process profile data
107
                if !foundHeader {
×
108
                        continue
×
109
                }
110

NEW
111
                if funcName := extractFunctionName(line, filter.IncludePrefixes, ignoreSet); funcName != "" {
×
112
                        names = append(names, funcName)
×
113
                }
×
114
        }
115

116
        if err = scanner.Err(); err != nil {
×
117
                return nil, fmt.Errorf("error reading profile file: %w", err)
×
118
        }
×
119

120
        if !foundHeader {
×
121
                return nil, errors.New("profile file header not found")
×
122
        }
×
123

124
        return names, nil
×
125
}
126

127
// ShouldKeepLine determines if a line from a profile should be kept based on profile values and ignore filters.
128
func ShouldKeepLine(line string, agrs *args.LineFilterArgs) bool {
×
129
        if line == "" {
×
130
                return false
×
131
        }
×
132

133
        lineParts := strings.Fields(line)
×
134
        if len(lineParts) < minProfileLinelength {
×
135
                return false
×
136
        }
×
137

138
        if !filterByNumber(agrs.ProfileFilters, lineParts) {
×
139
                return false
×
140
        }
×
141

142
        if !filterByIgnoreFunctions(agrs.IgnoreFunctionSet, lineParts) {
×
143
                return false
×
144
        }
×
145

146
        return filterByIgnorePrefixes(agrs.IgnorePrefixSet, lineParts)
×
147
}
148

149
func GetAllProfileLines(scanner *bufio.Scanner, lines *[]string) {
×
150
        for scanner.Scan() {
×
151
                *lines = append(*lines, scanner.Text())
×
152
        }
×
153
}
154

155
func CollectOrRemoveHeader(scanner *bufio.Scanner, profileType string, lines *[]string, shouldRemove bool) {
×
156
        lineCount := 0
×
157

×
158
        headerIndex := 6
×
159
        if profileType != "cpu" {
×
160
                headerIndex = 5
×
161
        }
×
162

163
        for lineCount < headerIndex && scanner.Scan() {
×
164
                if !shouldRemove {
×
165
                        *lines = append(*lines, scanner.Text())
×
166
                }
×
167
                lineCount++
×
168
        }
169
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc