GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

datemath.*parser.ExitDuration   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 37
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 31
nop 1
dl 0
loc 37
rs 2.9998
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like datemath.*parser.ExitDuration often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package datemath
2
3
import (
4
	"fmt"
5
	"strconv"
6
	"strings"
7
	"time"
8
9
	"github.com/antlr/antlr4/runtime/Go/antlr"
10
	"github.com/araddon/dateparse"
11
)
12
13
//go:generate antlr -Dlanguage=Go -listener -visitor -o . -package datemath Datemath.g4
14
15
type parser struct {
16
	*BaseDatemathListener
17
18
	env map[string]time.Time
19
20
	errors []error
21
	ts     time.Time
22
23
	// duration
24
	d             time.Duration
25
	ddy, ddm, ddd int
26
}
27
28
func Eval(input string) (time.Time, error) {
0 ignored issues
show
introduced by
exported function Eval should have comment or be unexported
Loading history...
29
	return EvalWithEnv(input, map[string]time.Time{})
30
}
31
32
func EvalWithEnv(input string, env map[string]time.Time) (time.Time, error) {
0 ignored issues
show
introduced by
exported function EvalWithEnv should have comment or be unexported
Loading history...
33
	is := antlr.NewInputStream(input)
34
35
	lexer := NewDatemathLexer(is)
36
	stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
37
	datemath := NewDatemathParser(stream)
38
39
	p := &parser{
40
		env: env,
41
	}
42
43
	lexer.RemoveErrorListeners()
44
	datemath.RemoveErrorListeners()
45
	lexer.AddErrorListener(p)
46
	datemath.AddErrorListener(p)
47
48
	antlr.ParseTreeWalkerDefault.Walk(p, datemath.Start())
49
50
	if len(p.errors) > 0 {
51
		return time.Time{}, p.errors[0]
52
	}
53
	return p.ts, nil
54
}
55
56
func (p *parser) ExitDuration(c *DurationContext) {
57
	var err error
58
	if terminalnode, ok := c.GetChild(0).(*antlr.TerminalNodeImpl); ok {
59
		switch terminalnode.GetSymbol().GetTokenType() {
60
		case DatemathLexerEsDuration:
61
			txt := c.GetText()
62
			num := 1
63
			if len(txt) > 1 {
64
				num, err = strconv.Atoi(txt[:len(txt)-1])
65
			}
66
			if err == nil {
67
				switch txt[len(txt)-1] {
68
				case 'y':
69
					p.ddy = num
70
				case 'M':
71
					p.ddm = num
72
				case 'd':
73
					p.ddd = num
74
				case 'w':
75
					p.ddd = 7 * num
76
				case 'H':
77
					p.d = time.Duration(num) * time.Hour
78
				case 'h':
79
					p.d = time.Duration(num) * time.Hour
80
				case 'm':
81
					p.d = time.Duration(num) * time.Minute
82
				case 's':
83
					p.d = time.Duration(num) * time.Second
84
				}
85
			}
86
		case DatemathLexerGoDuration:
87
			p.d, err = time.ParseDuration(c.GetText())
88
		}
89
90
	}
91
	if err != nil {
92
		p.errors = append(p.errors, err)
93
	}
94
}
95
96
func (p *parser) ExitBinary(c *BinaryContext) {
97
	op := c.GetOp().GetText()
98
	switch op {
99
	case "-":
100
		p.ts = p.ts.AddDate(-p.ddy, -p.ddm, -p.ddd)
101
		p.ts = p.ts.Add(-1 * p.d)
102
	case "+":
103
		p.ts = p.ts.AddDate(p.ddy, p.ddm, p.ddd)
104
		p.ts = p.ts.Add(p.d)
105
	}
106
107
	p.d, p.ddy, p.ddm, p.ddd = 0, 0, 0, 0
108
}
109
110
func (p *parser) ExitRound(c *RoundContext) {
111
	p.ts = p.ts.Truncate(p.d)
112
	if p.ddy != 0 {
113
		p.ts = time.Date(p.ts.Year()/p.ddy*p.ddy, 1, 1, 0, 0, 0, 0, time.UTC)
114
	} else if p.ddm != 0 {
115
		p.ts = time.Date(p.ts.Year(), time.Month((int(p.ts.Month())-1)/p.ddm*p.ddm+1), 1, 0, 0, 0, 0, time.UTC)
116
	} else if p.ddd != 0 {
117
		if p.ddd%7 == 0 {
118
			// Special treatment for weeks
119
			weekday := int(p.ts.Weekday())
120
			if weekday == 0 {
121
				weekday = 7
122
			}
123
			_, w := p.ts.ISOWeek()
124
			p.ts = p.ts.AddDate(0, 0, -weekday+1-w%(p.ddd/7)*7).Truncate(86400 * time.Second)
125
		} else {
126
			p.ts = time.Date(p.ts.Year(), p.ts.Month(), p.ts.Day()/p.ddd*p.ddd, 0, 0, 0, 0, time.UTC)
127
		}
128
	}
129
	p.d, p.ddy, p.ddm, p.ddd = 0, 0, 0, 0
130
}
131
132
func (p *parser) ExitBuiltin(c *BuiltinContext) {
133
	name := c.GetText()
134
	switch name {
135
	case "now":
136
		if ts, ok := p.env["now"]; ok {
137
			p.ts = ts
138
			return
139
		}
140
		p.ts = time.Now().UTC()
141
	}
142
}
143
144
func (p *parser) ExitIdentifier(c *IdentifierContext) {
145
	name := c.GetText()
146
	if ts, ok := p.env[name]; ok {
147
		p.ts = ts
148
		return
149
	}
150
	p.errors = append(p.errors, fmt.Errorf("Unknown identifier: '%s'", name))
151
}
152
153
func (p *parser) ExitLiteral(c *LiteralContext) {
154
	var err error
155
	p.ts, err = dateparse.ParseAny(strings.Trim(c.GetText(), "'"))
156
	if err != nil {
157
		p.errors = append(p.errors, err)
158
	}
159
}
160
161
func (p *parser) ExitDateLiteral(c *DateLiteralContext) {
162
	var err error
163
	p.ts, err = dateparse.ParseAny(strings.TrimRight(c.GetText(), "|"))
164
	if err != nil {
165
		p.errors = append(p.errors, err)
166
	}
167
}
168
169
func (p *parser) SyntaxError(recognizer antlr.Recognizer, offendingSymbol interface{}, line, column int, msg string, e antlr.RecognitionException) {
170
	p.errors = append(p.errors, fmt.Errorf(":%d:%d:%s", line, column, msg))
171
}
172
173
func (p *parser) ReportAmbiguity(_ antlr.Parser, _ *antlr.DFA, _, _ int, _ bool, _ *antlr.BitSet, _ antlr.ATNConfigSet) {
174
}
175
176
func (p *parser) ReportAttemptingFullContext(_ antlr.Parser, _ *antlr.DFA, _, _ int, _ *antlr.BitSet, _ antlr.ATNConfigSet) {
177
}
178
179
func (p *parser) ReportContextSensitivity(_ antlr.Parser, _ *antlr.DFA, _, _, _ int, _ antlr.ATNConfigSet) {
180
}
181