style: drop the line comments added with the triage fixes

CLAUDE.md rules out // line comments in committed Go. The rationale they
carried is in the commit messages for each fix; doc comments that already
existed are kept, updated where the code they describe changed.

Also replaces reflect.Ptr with reflect.Pointer and rewrites the YAML keyword
alternation as a lookup table, both flagged by golangci-lint.
This commit is contained in:
Sanaei
2026-07-27 14:37:57 +02:00
parent 6f4cc1e53c
commit 8bc00d1e90
8 changed files with 14 additions and 87 deletions
+14 -31
View File
@@ -8,23 +8,24 @@ import (
"github.com/goccy/go-yaml"
)
// yamlQuotedString is a string that must reach a YAML parser as a string.
// Single-quoted style is used because it carries the value literally — no
// escape processing — which suits hex ids, passwords and pre-shared keys.
type yamlQuotedString string
func (s yamlQuotedString) MarshalYAML() ([]byte, error) {
return []byte("'" + strings.ReplaceAll(string(s), "'", "''") + "'"), nil
}
// yamlPlainScalarNotString matches the plain scalars a YAML parser resolves to
// something other than a string. It covers the YAML 1.2 core schema plus the
// 1.1 forms go-yaml v3 — the library the Clash cores use — still resolves:
// null, booleans (including y/yes/on and friends), integers in every base,
// sexagesimals, floats, and dates.
var yamlPlainScalarNotString = regexp.MustCompile(`^(?:` +
`~|[Nn]ull|NULL|` +
`[Tt]rue|TRUE|[Ff]alse|FALSE|[Yy]es|YES|[Nn]o|NO|[Oo]n|ON|[Oo]ff|OFF|[YyNn]|` +
var yamlNonStringWords = map[string]bool{
"~": true, "null": true, "Null": true, "NULL": true,
"true": true, "True": true, "TRUE": true,
"false": true, "False": true, "FALSE": true,
"yes": true, "Yes": true, "YES": true,
"no": true, "No": true, "NO": true,
"on": true, "On": true, "ON": true,
"off": true, "Off": true, "OFF": true,
"y": true, "Y": true, "n": true, "N": true,
}
var yamlNonStringNumber = regexp.MustCompile(`^(?:` +
`[-+]?[0-9]+|` +
`0[oO]?[0-7]+|0[xX][0-9a-fA-F]+|` +
`[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+|` +
@@ -33,29 +34,13 @@ var yamlPlainScalarNotString = regexp.MustCompile(`^(?:` +
`[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}(?:[Tt ].*)?` +
`)$`)
// yamlScalarIsAmbiguous reports whether s must be quoted to survive as a string.
//
// The encoder quotes most of these itself, but not the exponent-float form: a
// REALITY short-id such as "2351e1" is valid hex and, emitted bare, is read as
// 23510. A Clash core then hex-decodes a five-digit number, rejects the proxy
// and drops the whole provider to zero nodes (#6104). goccy's own parser reads
// that token back as a string, so the encoder never sees a problem and a
// round-trip check through it cannot find one either — the resolution rules,
// not the encoder, are the thing to test against. The same shape reaches
// passwords, obfs-passwords and pre-shared keys, so every string in the
// document is checked rather than an enumerated list of fields.
func yamlScalarIsAmbiguous(s string) bool {
if s == "" {
return false
}
return yamlPlainScalarNotString.MatchString(s)
return yamlNonStringWords[s] || yamlNonStringNumber.MatchString(s)
}
// quoteAmbiguousYAMLScalars rebuilds v with every ambiguous string wrapped so
// the encoder is forced to quote it. Containers are rebuilt as map[string]any /
// []any because a typed container cannot hold the wrapper; unambiguous values
// are carried through untouched, so the emitted document is unchanged apart
// from the quotes that were missing.
func quoteAmbiguousYAMLScalars(v any) any {
if v == nil {
return nil
@@ -89,7 +74,7 @@ func quoteAmbiguousYAMLScalars(v any) any {
out[i] = quoteAmbiguousYAMLScalars(rv.Index(i).Interface())
}
return out
case reflect.Ptr, reflect.Interface:
case reflect.Pointer, reflect.Interface:
if rv.IsNil() {
return v
}
@@ -99,8 +84,6 @@ func quoteAmbiguousYAMLScalars(v any) any {
}
}
// marshalClashYAML serializes a Clash config, keeping string values typed as
// strings in the output.
func marshalClashYAML(config any) ([]byte, error) {
return yaml.Marshal(quoteAmbiguousYAMLScalars(config))
}
-12
View File
@@ -7,10 +7,6 @@ import (
"github.com/goccy/go-yaml"
)
// The encoder's own parser reads every one of these back as a string, so a
// round-trip through it proves nothing. What matters is the emitted text: a
// plain scalar that the YAML resolution rules turn into a number, bool, null
// or date is what breaks a Clash core, so those must carry quotes.
func TestAmbiguousScalarsAreQuoted(t *testing.T) {
tests := []struct {
name string
@@ -54,7 +50,6 @@ func TestAmbiguousScalarsAreQuoted(t *testing.T) {
if !tt.mustQuote && quoted {
t.Errorf("%q needs no quoting, got %q", tt.value, got)
}
// Whatever the quoting decision, the document must still parse.
var decoded map[string]any
if err := yaml.Unmarshal(out, &decoded); err != nil {
t.Fatalf("output must stay parseable: %v\n%s", err, out)
@@ -63,8 +58,6 @@ func TestAmbiguousScalarsAreQuoted(t *testing.T) {
}
}
// The value in the report: unquoted, YAML reads 2351e1 as 23510, mihomo hex-
// decodes an odd-length "23510" and the provider drops to zero nodes (#6104).
func TestClashShortIDIsQuotedInOutput(t *testing.T) {
out, err := marshalClashYAML(map[string]any{
"proxies": []any{map[string]any{
@@ -80,8 +73,6 @@ func TestClashShortIDIsQuotedInOutput(t *testing.T) {
}
}
// A password or pre-shared key of the same shape reaches the output the same
// way, so the guard is not specific to short-id.
func TestAmbiguousPasswordIsQuoted(t *testing.T) {
out, err := marshalClashYAML(map[string]any{
"proxies": []any{map[string]any{
@@ -101,8 +92,6 @@ func TestAmbiguousPasswordIsQuoted(t *testing.T) {
}
}
// Values that are unambiguous must not pick up noise quoting, so the emitted
// document stays byte-identical to what the encoder produced before.
func TestUnambiguousScalarsAreUnchanged(t *testing.T) {
config := map[string]any{
"port": 7890,
@@ -125,7 +114,6 @@ func TestUnambiguousScalarsAreUnchanged(t *testing.T) {
}
}
// A quote inside the value must not terminate the scalar.
func TestQuotedScalarEscapesQuotes(t *testing.T) {
out, err := marshalClashYAML(map[string]any{"password": "1e2'3"})
if err != nil {
-3
View File
@@ -624,9 +624,6 @@ func TestUsageOnFirstLinkOnly_SingleBracket(t *testing.T) {
}
}
// Every link of a subscription carries the client's identity, because that is
// what tells one imported profile from another in the client app. Only the
// usage block, which is identical on all of them, is first-link-only (#6098).
func TestEmailOnEveryLink(t *testing.T) {
s := &SubService{
remarkTemplate: "{{INBOUND}} {{EMAIL}}|📊{{TRAFFIC_LEFT}}",