summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/logging.go
blob: c5361ed46b64fcf3198b877104555bd6e29b5864 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
	"fmt"
	"io"
	"path"
	"strings"
)

type LogLevel struct {
	TraditionalName string
	GccName         string
}

var (
	llFatal   = &LogLevel{"FATAL", "fatal"}
	llError   = &LogLevel{"ERROR", "error"}
	llWarn    = &LogLevel{"WARN", "warning"}
	llNote    = &LogLevel{"NOTE", "note"}
	llAutofix = &LogLevel{"AUTOFIX", "autofix"}
)

var dummyLine = NewLine("", 0, "", nil)

func shallBeLogged(fname, lineno, msg string) bool {
	uniq := path.Clean(fname) + ":" + lineno + ":" + msg
	if G.logged[uniq] {
		return false
	}

	if G.logged == nil {
		G.logged = make(map[string]bool)
	}
	G.logged[uniq] = true
	return true
}

func logs(level *LogLevel, fname, lineno, format, msg string) bool {
	if fname != "" {
		fname = cleanpath(fname)
	}

	if !G.opts.LogVerbose && !shallBeLogged(fname, lineno, msg) {
		return false
	}

	var text, sep string
	if !G.opts.GccOutput {
		text += sep + level.TraditionalName + ":"
		sep = " "
	}
	if fname != "" {
		text += sep + fname
		sep = ": "
		if lineno != "" {
			text += ":" + lineno
		}
	}
	if G.opts.GccOutput {
		text += sep + level.GccName + ":"
		sep = " "
	}
	if G.opts.Profiling {
		G.loghisto.Add(format, 1)
	}
	text += sep + msg + "\n"

	out := G.logOut
	if level == llFatal {
		out = G.logErr
	}

	io.WriteString(out, text)

	switch level {
	case llFatal:
		panic(pkglintFatal{})
	case llError:
		G.errors++
	case llWarn:
		G.warnings++
	}
	return true
}

func Explain(explanation ...string) {
	if G.opts.Explain {
		complete := strings.Join(explanation, "\n")
		if G.explanationsGiven[complete] {
			return
		}
		if G.explanationsGiven == nil {
			G.explanationsGiven = make(map[string]bool)
		}
		G.explanationsGiven[complete] = true

		io.WriteString(G.logOut, "\n")
		for _, explanationLine := range explanation {
			io.WriteString(G.logOut, "\t"+explanationLine+"\n")
		}
		io.WriteString(G.logOut, "\n")
	} else if G.Testing {
		for _, s := range explanation {
			if l := tabLength(s); l > 68 && contains(s, " ") {
				print(fmt.Sprintf("Long explanation line (%d): %s\n", l, s))
			}
			if m, before := match1(s, `(.+)\. [^ ]`); m {
				if !matches(before, `\d$|e\.g`) {
					print(fmt.Sprintf("Short space after period: %s\n", s))
				}
			}
		}
	}
	G.explanationsAvailable = true
}

type pkglintFatal struct{}