Address new linter complaints

This commit is contained in:
Katrina Verey
2022-03-29 18:18:23 -04:00
parent b368b347d1
commit 14947e449b
77 changed files with 220 additions and 210 deletions

View File

@@ -5,6 +5,7 @@ run:
deadline: 5m
skip-dirs:
- yaml/internal/k8sgen/pkg
- internal/forked
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
@@ -14,34 +15,35 @@ linters:
- bodyclose
- deadcode
- depguard
# - dogsled # uncomment after upgrading golangci-lint (Issue #3663)
- dogsled
- dupl
- errcheck
# - errcheck
- exportloopref
# - funlen
- gochecknoinits
- goconst
- gocritic
- gocyclo
- gofmt
- goimports
# - gosec
- gosec
- gosimple
- govet
- ineffassign
- lll
- misspell
- nakedret
- nolintlint
- revive
- scopelint
- staticcheck
- structcheck
- stylecheck
# - stylecheck # seems redundant with revive, which replaced golint
- typecheck
- unconvert
- unparam
- unused
- varcheck
# - whitespace # uncomment after upgrading golangci-lint (Issue #3663)
- whitespace
linters-settings:
dupl:
@@ -50,5 +52,21 @@ linters-settings:
line-length: 170
gocyclo:
min-complexity: 30
golint:
min-confidence: 0.85
revive:
rules:
- name: var-naming
arguments:
- [ "ID", "API", "JSON" ] # AllowList
- [ ] # DenyList
gosec:
config:
G306: "0644"
issues:
exclude-rules:
- linters:
- revive
text: "don't use leading"
- linters:
- staticcheck
text: "SA1019: kioutil.Legacy"

View File

@@ -12,11 +12,8 @@ export PATH := $(MYGOBIN):$(PATH)
$(MYGOBIN)/addlicense:
go get github.com/google/addlicense
# TODO: Issue #3663
# Update this version of golangci-lint
# Ideally use same version as in {REPO}/hack/go.mod
$(MYGOBIN)/golangci-lint:
go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.17.0
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.2
$(MYGOBIN)/k8scopy:
( cd ../cmd/k8scopy; go install . )
@@ -24,7 +21,7 @@ $(MYGOBIN)/k8scopy:
$(MYGOBIN)/stringer:
go get golang.org/x/tools/cmd/stringer
all: license fix vet fmt test tidy
all: license fix vet fmt test lint tidy
k8sGenDir := yaml/internal/k8sgen/pkg
@@ -36,7 +33,8 @@ clean:
lint: $(MYGOBIN)/golangci-lint
$(MYGOBIN)/golangci-lint \
run ./...
run ./... \
--path-prefix=kyaml
license: $(MYGOBIN)/addlicense

View File

@@ -163,7 +163,6 @@ func (n *fsNode) AddFile(
}
func (n *fsNode) addDir(path string) (result *fsNode, err error) {
parent := n
dName, subDirName := mySplit(path)
if dName != "" {

View File

@@ -93,7 +93,6 @@ func TestMakeFsInMemory(t *testing.T) {
t, "MakeFsInMemory", true, topCases, MakeFsInMemory())
}
//nolint:gocyclo
func runBasicOperations(
t *testing.T, tName string, isFSysRooted bool,
cases []pathCase, fSys FileSystem) {
@@ -449,10 +448,10 @@ var bunchOfFiles = []struct {
addAsDir: true,
},
{
path: filepath.Join("x"),
path: "x",
},
{
path: filepath.Join("y"),
path: "y",
},
{
path: filepath.Join("b", "d", "a", "c", "i", "beans"),
@@ -559,7 +558,7 @@ func TestRemove(t *testing.T) {
orgCount -= 3
// Now drop one more for a total of four dropped.
result, _ = n.Find(filepath.Join("y"))
result, _ = n.Find("y")
err = result.Remove()
if err != nil {
t.Fatalf("%s; unable to remove: %v", path, err)
@@ -692,7 +691,7 @@ func TestFind(t *testing.T) {
},
{
what: "directory",
arg: filepath.Join("b"),
arg: "b",
expectDir: true,
},
{
@@ -869,7 +868,7 @@ func TestFileOps(t *testing.T) {
defer f.Close()
for {
buf := make([]byte, rand.Intn(10))
buf := make([]byte, rand.Intn(10)) // nolint:gosec
n, err := f.Read(buf)
if err != nil && err != io.EOF {
t.Fatalf("unexpected error: %v", err)

View File

@@ -128,7 +128,7 @@ func (fsOnDisk) ReadFile(name string) ([]byte, error) { return ioutil.ReadFile(n
// WriteFile delegates to ioutil.WriteFile with read/write permissions.
func (fsOnDisk) WriteFile(name string, c []byte) error {
return ioutil.WriteFile(name, c, 0666)
return ioutil.WriteFile(name, c, 0666) //nolint:gosec
}
// Walk delegates to filepath.Walk.

View File

@@ -194,8 +194,8 @@ func TestReadFilesRealFS(t *testing.T) {
"file-1.xtn",
},
expectedDirs: map[string][]string{
testDir: []string{dir},
dir: []string{nestedDir},
testDir: {dir},
dir: {nestedDir},
},
},
"AllHiddenFiles": {
@@ -206,7 +206,7 @@ func TestReadFilesRealFS(t *testing.T) {
".some-file-4.xtn",
},
expectedDirs: map[string][]string{
testDir: []string{hiddenDir},
testDir: {hiddenDir},
},
},
"foo_File": {

View File

@@ -273,9 +273,9 @@ type resultsChecker interface {
shouldUpdateFixtures() bool
// updateFixtures modifies the test fixture files to match the given content
updateFixtures(t *testing.T, actualOutput string, actualError string)
// assertOutputMatches compares the expected output to the output recieved.
// assertOutputMatches compares the expected output to the output received.
assertOutputMatches(t *testing.T, expected string, actual string)
// assertErrorMatches compares teh expected error to the error received.
// assertErrorMatches compares the expected error to the error received.
assertErrorMatches(t *testing.T, expected string, actual string)
}

View File

@@ -75,14 +75,16 @@ spec:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
internal value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
color:
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
submits requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
@@ -141,7 +143,7 @@ func TestSchemaFromFunctionDefinition(t *testing.T) {
} else {
require.NoError(t, err)
var gotProps []string
for prop, _ := range got.Properties {
for prop := range got.Properties {
gotProps = append(gotProps, prop)
}
sort.Strings(tt.wantProps)

View File

@@ -189,7 +189,7 @@ func (c *Filter) getCommand() (string, []string) {
}
args = append(args, runtimeutil.NewContainerEnvFromStringSlice(c.Env).GetDockerFlags()...)
a := append(args, c.Image)
a := append(args, c.Image) //nolint:gocritic
return "docker", a
}

View File

@@ -6,11 +6,11 @@ package container
import (
"bytes"
"fmt"
"github.com/stretchr/testify/require"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/kyaml/fn/runtime/runtimeutil"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/yaml"

View File

@@ -34,7 +34,7 @@ func (c *Filter) Filter(nodes []*yaml.RNode) ([]*yaml.RNode, error) {
}
func (c *Filter) Run(reader io.Reader, writer io.Writer) error {
cmd := exec.Command(c.Path, c.Args...)
cmd := exec.Command(c.Path, c.Args...) // nolint:gosec
cmd.Stdin = reader
cmd.Stdout = writer
cmd.Stderr = os.Stderr

View File

@@ -330,7 +330,7 @@ func (r *ByteReader) decode(originalYAML string, index int, decoder *yaml.Decode
// derive and add the seqindent annotation
seqIndentStyle := yaml.DeriveSeqIndentStyle(originalYAML)
if seqIndentStyle != "" {
r.SetAnnotations[kioutil.SeqIndentAnnotation] = fmt.Sprintf("%s", seqIndentStyle)
r.SetAnnotations[kioutil.SeqIndentAnnotation] = seqIndentStyle
}
}
}

View File

@@ -41,7 +41,7 @@ func TestIgnoreFilesMatcher_readIgnoreFile(t *testing.T) {
fsMakers := map[string]func(bool) (string, filesys.FileSystem){
// onDisk creates a temp directory and returns a nil FileSystem, testing
// the normal conditions under which ignoreFileMatcher is used.
"onDisk": func(writeIgnoreFile bool) (string, filesys.FileSystem) {
"onDisk": func(writeIgnoreFile bool) (string, filesys.FileSystem) { //nolint:unparam
dir, err := ioutil.TempDir("", "kyaml-test")
require.NoError(t, err)
@@ -107,10 +107,10 @@ func TestLocalPackageReader_Read_ignoreFile(t *testing.T) {
filepath.Join("a", "c"),
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("a", "b", "a_test.yaml"): readFileA,
filepath.Join("a", "c", "c_test.yaml"): readFileB,
filepath.Join(".krmignore"): []byte(`
".krmignore": []byte(`
a/c/c_test.yaml
`,
),
@@ -127,10 +127,10 @@ a/c/c_test.yaml
filepath.Join("a", "c"),
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("a", "b", "a_test.yaml"): readFileA,
filepath.Join("a", "c", "c_test.yaml"): readFileB,
filepath.Join(".krmignore"): []byte(`
".krmignore": []byte(`
a/c
`,
),
@@ -146,10 +146,10 @@ a/c
filepath.Join("a", "c"),
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("a", "c", "a_test.yaml"): readFileA,
filepath.Join("a", "c", "c_test.yaml"): readFileB,
filepath.Join(".krmignore"): []byte(`
".krmignore": []byte(`
d/e/f.yaml
`,
),
@@ -168,10 +168,10 @@ a_test.yaml
filepath.Join("a", "c"),
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("a", "c", "a_test.yaml"): readFileA,
filepath.Join("a", "c", "c_test.yaml"): readFileB,
filepath.Join(".krmignore"): []byte(`
".krmignore": []byte(`
a/c/c_test.yaml
`,
),
@@ -187,16 +187,16 @@ a_test.yaml
{
name: "handles a combination of packages and directories",
directories: []string{
filepath.Join("a"),
"a",
filepath.Join("d", "e"),
filepath.Join("f"),
"f",
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("d", "pkgFile"): {},
filepath.Join("d", "e", "pkgFile"): {},
filepath.Join("f", "pkgFile"): {},
filepath.Join("manifest.yaml"): []byte(`root: root`),
"manifest.yaml": []byte(`root: root`),
filepath.Join("a", "manifest.yaml"): []byte(`a: a`),
filepath.Join("d", "manifest.yaml"): []byte(`d: d`),
filepath.Join("d", "e", "manifest.yaml"): []byte(`e: e`),
@@ -215,14 +215,14 @@ manifest.yaml
{
name: "ignore file can exclude subpackages",
directories: []string{
filepath.Join("a"),
"a",
},
files: map[string][]byte{
filepath.Join("pkgFile"): {},
"pkgFile": {},
filepath.Join("a", "pkgFile"): {},
filepath.Join("manifest.yaml"): []byte(`root: root`),
"manifest.yaml": []byte(`root: root`),
filepath.Join("a", "manifest.yaml"): []byte(`a: a`),
filepath.Join(".krmignore"): []byte(`
".krmignore": []byte(`
a
`),
},

View File

@@ -270,7 +270,10 @@ func ReconcileInternalAnnotations(result []*yaml.RNode, nodeAnnosMap map[string]
}
// determineAnnotationsFormat determines if the resources are using one of the internal and legacy annotation format or both of them.
func determineAnnotationsFormat(nodeAnnosMap map[string]map[string]string) (useInternal, useLegacy bool, err error) {
func determineAnnotationsFormat(nodeAnnosMap map[string]map[string]string) (bool, bool, error) {
var useInternal, useLegacy bool
var err error
if len(nodeAnnosMap) == 0 {
return true, true, nil
}
@@ -295,7 +298,7 @@ func determineAnnotationsFormat(nodeAnnosMap map[string]map[string]string) (useI
}
if (foundOneOf && !*internal) || (!foundOneOf && *internal) {
err = fmt.Errorf("the annotation formatting in the input resources is not consistent")
return
return useInternal, useLegacy, err
}
foundOneOf = foundLegacyPath || foundLegacyIndex || foundLegacyId
@@ -305,7 +308,7 @@ func determineAnnotationsFormat(nodeAnnosMap map[string]map[string]string) (useI
}
if (foundOneOf && !*legacy) || (!foundOneOf && *legacy) {
err = fmt.Errorf("the annotation formatting in the input resources is not consistent")
return
return useInternal, useLegacy, err
}
}
if internal != nil {
@@ -314,7 +317,7 @@ func determineAnnotationsFormat(nodeAnnosMap map[string]map[string]string) (useI
if legacy != nil {
useLegacy = *legacy
}
return
return useInternal, useLegacy, err
}
func missingInternalOrLegacyAnnotations(rn *yaml.RNode) error {
@@ -382,13 +385,14 @@ func checkAnnotationsAltered(rn *yaml.RNode, nodeAnnosMap map[string]map[string]
originalPath = originalAnnotations[kioutil.LegacyPathAnnotation]
}
if originalPath != "" {
if originalPath != internal.path && originalPath != legacy.path && internal.path != legacy.path {
switch {
case originalPath != internal.path && originalPath != legacy.path && internal.path != legacy.path:
return fmt.Errorf("resource input to function has mismatched legacy and internal path annotations")
} else if originalPath != internal.path {
case originalPath != internal.path:
if _, err := rn.Pipe(yaml.SetAnnotation(kioutil.LegacyPathAnnotation, internal.path)); err != nil {
return err
}
} else if originalPath != legacy.path {
case originalPath != legacy.path:
if _, err := rn.Pipe(yaml.SetAnnotation(kioutil.PathAnnotation, legacy.path)); err != nil {
return err
}
@@ -400,13 +404,14 @@ func checkAnnotationsAltered(rn *yaml.RNode, nodeAnnosMap map[string]map[string]
originalIndex = originalAnnotations[kioutil.LegacyIndexAnnotation]
}
if originalIndex != "" {
if originalIndex != internal.index && originalIndex != legacy.index && internal.index != legacy.index {
switch {
case originalIndex != internal.index && originalIndex != legacy.index && internal.index != legacy.index:
return fmt.Errorf("resource input to function has mismatched legacy and internal index annotations")
} else if originalIndex != internal.index {
case originalIndex != internal.index:
if _, err := rn.Pipe(yaml.SetAnnotation(kioutil.LegacyIndexAnnotation, internal.index)); err != nil {
return err
}
} else if originalIndex != legacy.index {
case originalIndex != legacy.index:
if _, err := rn.Pipe(yaml.SetAnnotation(kioutil.IndexAnnotation, legacy.index)); err != nil {
return err
}

View File

@@ -883,7 +883,6 @@ data:
assert.Error(t, err)
assert.Equal(t, tc.expectedErr, err.Error())
}
})
}
}

View File

@@ -644,7 +644,9 @@ metadata:
internal.config.kubernetes.io/e: 'f'
internal.config.kubernetes.io/g: 'h'
`,
expectedErr: `internal annotations differ: internal.config.kubernetes.io/a, internal.config.kubernetes.io/c, internal.config.kubernetes.io/e, internal.config.kubernetes.io/g`,
expectedErr: `internal annotations differ: ` +
`internal.config.kubernetes.io/a, internal.config.kubernetes.io/c, ` +
`internal.config.kubernetes.io/e, internal.config.kubernetes.io/g`,
},
}

View File

@@ -216,9 +216,19 @@ func TestLocalPackageReader_Read_JSON(t *testing.T) {
require.NoError(t, err)
require.Len(t, nodes, 2)
expected := []string{
`{"a": "b", metadata: {annotations: {config.kubernetes.io/index: '0', config.kubernetes.io/path: 'a_test.json', internal.config.kubernetes.io/index: '0', internal.config.kubernetes.io/path: 'a_test.json'}}}
`{"a": "b", ` +
`metadata: {annotations: {` +
`config.kubernetes.io/index: '0', ` +
`config.kubernetes.io/path: 'a_test.json', ` +
`internal.config.kubernetes.io/index: '0', ` +
`internal.config.kubernetes.io/path: 'a_test.json'}}}
`,
`{"e": "f", "g": {"h": ["i", "j"]}, metadata: {annotations: {config.kubernetes.io/index: '0', config.kubernetes.io/path: 'b_test.json', internal.config.kubernetes.io/index: '0', internal.config.kubernetes.io/path: 'b_test.json'}}}
`{"e": "f", "g": {"h": ["i", "j"]}, ` +
`metadata: {annotations: {` +
`config.kubernetes.io/index: '0', ` +
`config.kubernetes.io/path: 'b_test.json', ` +
`internal.config.kubernetes.io/index: '0', ` +
`internal.config.kubernetes.io/path: 'b_test.json'}}}
`,
}
for i := range nodes {

View File

@@ -325,7 +325,7 @@ metadata:
// These two lines are similar to calling ioutil.TempDir, but we don't actually create any directory.
rand.Seed(time.Now().Unix())
path := filepath.Join(os.TempDir(), fmt.Sprintf("kyaml-test%d", rand.Int31()))
path := filepath.Join(os.TempDir(), fmt.Sprintf("kyaml-test%d", rand.Int31())) //nolint:gosec
require.NoError(t, mockFS.MkdirAll(filepath.Join(path, "a")))
return path, node1, node2, node3, func() { require.NoError(t, mockFS.RemoveAll(path)) }
}

View File

@@ -39,10 +39,7 @@ func syncOrder(from, to *yaml.RNode) error {
return syncOrder(fNode.Value, tNode.Value)
})
case yaml.SequenceNode:
return VisitElements(from, to, func(fNode, tNode *yaml.RNode) error {
// Traverse each list element
return syncOrder(fNode, tNode)
})
return VisitElements(from, to, syncOrder) // Traverse each list element
}
return nil
}

View File

@@ -259,7 +259,7 @@ spec:
properties:
conditions:
items:
description: ControlPlaneRevisionCondition is a repeated struct definining the current conditions of a ControlPlaneRevision.
description: ControlPlaneRevisionCondition is a repeated struct defining the current conditions of a ControlPlaneRevision.
properties:
lastTransitionTime:
description: Last time the condition transitioned from one status to another
@@ -347,7 +347,7 @@ spec:
type: array
items:
type: object
description: ControlPlaneRevisionCondition is a repeated struct definining the current conditions of a ControlPlaneRevision.
description: ControlPlaneRevisionCondition is a repeated struct defining the current conditions of a ControlPlaneRevision.
properties:
type:
type: string

View File

@@ -82,15 +82,15 @@ func createTestDirStructure(dir string) error {
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(dir, "subpkg1", "Krmfile"), []byte(""), 0777)
err = ioutil.WriteFile(filepath.Join(dir, "subpkg1", "Krmfile"), []byte(""), 0644)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(dir, "subpkg2", "Krmfile"), []byte(""), 0777)
err = ioutil.WriteFile(filepath.Join(dir, "subpkg2", "Krmfile"), []byte(""), 0644)
if err != nil {
return err
}
err = ioutil.WriteFile(filepath.Join(dir, "Krmfile"), []byte(""), 0777)
err = ioutil.WriteFile(filepath.Join(dir, "Krmfile"), []byte(""), 0644)
if err != nil {
return err
}

View File

@@ -342,7 +342,7 @@ metadata:
{name: "sort functions -- deepest first",
in: []f{
{
path: filepath.Join("a.yaml"),
path: "a.yaml",
value: `
metadata:
annotations:
@@ -382,7 +382,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:
@@ -412,7 +412,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:
@@ -442,7 +442,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:
@@ -473,7 +473,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:
@@ -502,7 +502,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:
@@ -543,7 +543,7 @@ metadata:
`,
},
{
path: filepath.Join("b.yaml"),
path: "b.yaml",
value: `
metadata:
annotations:

View File

@@ -50,7 +50,7 @@ func (fs *FieldSetter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
}
// Set updates the OpenAPI definitions and resources with the new setter value
func (fs FieldSetter) Set() (int, error) {
func (fs *FieldSetter) Set() (int, error) {
// Update the OpenAPI definitions
soa := setters2.SetOpenAPI{
Name: fs.Name,

View File

@@ -64,7 +64,7 @@ func (c *SetterCreator) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
return nil, c.Create()
}
func (c SetterCreator) Create() error {
func (c *SetterCreator) Create() error {
err := c.validateSetterInfo()
if err != nil {
return err

View File

@@ -864,7 +864,6 @@ func TestMapEntrySetter(t *testing.T) {
assert.NotNil(t, err)
assert.Equal(t, tc.expectedErr.Error(), err.Error())
}
})
}
}
@@ -1092,15 +1091,14 @@ func (c filter) Filter(object *RNode) (*RNode, error) {
}
func TestResourceNode_Pipe(t *testing.T) {
r0, r1, r2, r3 := &RNode{}, &RNode{}, &RNode{}, &RNode{}
var r0, r1, r2, r3 *RNode
var called []string
// check the nil value case
r0 = nil
_, err := r0.Pipe(FieldMatcher{Name: "foo"})
assert.NoError(t, err)
r0 = &RNode{}
r0, r1, r2, r3 = &RNode{}, &RNode{}, &RNode{}, &RNode{}
// all filters successful
v, err := r0.Pipe(
filter{fn: func(object *RNode) (*RNode, error) {

View File

@@ -99,7 +99,6 @@ func (p *PathMatcher) filter(rn *RNode) (*RNode, error) {
}
func (p *PathMatcher) doMatchEvery(rn *RNode) (*RNode, error) {
if err := rn.VisitElements(p.visitEveryElem); err != nil {
return nil, err
}
@@ -108,7 +107,6 @@ func (p *PathMatcher) doMatchEvery(rn *RNode) (*RNode, error) {
}
func (p *PathMatcher) visitEveryElem(elem *RNode) error {
fieldName := p.Path[0]
// recurse on the matching element
pm := &PathMatcher{Path: p.Path[1:]}

View File

@@ -1168,7 +1168,6 @@ items:
assert.NotNil(t, err)
assert.Equal(t, tc.expectedErr.Error(), err.Error())
}
})
}
}

View File

@@ -67,5 +67,4 @@ func keyLineBeforeSeqElem(lines []string, seqElemIndex int) string {
return parts[0] // throw away the trailing comment part
}
return ""
}