mirror of
https://github.com/hanzoai/docdb.git
synced 2026-10-30 18:39:39 +00:00
These three are generic upstream helper libraries that carry no local changes: the hashes recorded for them are byte-identical to the upstream modules, and their pinned go.mod bytes declare the upstream path. A github.com/hanzoai requirement therefore has nothing to resolve against from a cold cache. Point go.mod, go.sum, and imports at upstream, which is what the root module already does for wire. Pin the local docdb replace at v1.0.0; the prior v2 placeholder failed go.mod parsing.
143 lines
3.9 KiB
Go
143 lines
3.9 KiB
Go
// Copyright 2021 Hanzo AI Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package main contains linter for comments.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"log"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/FerretDB/gh"
|
|
"golang.org/x/tools/go/analysis"
|
|
"golang.org/x/tools/go/analysis/singlechecker"
|
|
|
|
"github.com/hanzoai/docdb/tools/github"
|
|
)
|
|
|
|
// todoRE represents correct "// TODO" comment format.
|
|
// It returns url, owner, repo and issue number as submatches.
|
|
var todoRE = regexp.MustCompile(`^// TODO (\Qhttps://github.com/\E(hanzoai|docdb|yugabyte)/([-\w]+)/issues/(\d+))$`)
|
|
|
|
// analyzer represents the checkcomments analyzer.
|
|
var analyzer = &analysis.Analyzer{
|
|
Name: "checkcomments",
|
|
Doc: "check TODO comments",
|
|
Run: run,
|
|
Flags: *flag.NewFlagSet("", flag.ExitOnError),
|
|
}
|
|
|
|
// init initializes the analyzer flags.
|
|
func init() {
|
|
analyzer.Flags.Bool("offline", false, "do not check issues open/closed status")
|
|
analyzer.Flags.Bool("cache-debug", false, "log cache hits/misses")
|
|
analyzer.Flags.Bool("client-debug", false, "log GitHub API requests/responses")
|
|
analyzer.Flags.Bool("skip-private", true, "do not check https://github.com/hanzoai/docdb-DocumentDB/issues/XXX URLs")
|
|
}
|
|
|
|
// main runs the analyzer.
|
|
func main() {
|
|
singlechecker.Main(analyzer)
|
|
}
|
|
|
|
// run analyses TODO comments.
|
|
func run(pass *analysis.Pass) (any, error) {
|
|
var client *github.Client
|
|
|
|
if !pass.Analyzer.Flags.Lookup("offline").Value.(flag.Getter).Get().(bool) {
|
|
p, err := github.CacheFilePath()
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
cacheDebugF := gh.NoopPrintf
|
|
if pass.Analyzer.Flags.Lookup("cache-debug").Value.(flag.Getter).Get().(bool) {
|
|
cacheDebugF = log.New(log.Writer(), "", log.Flags()).Printf
|
|
}
|
|
|
|
clientDebugF := gh.NoopPrintf
|
|
if pass.Analyzer.Flags.Lookup("client-debug").Value.(flag.Getter).Get().(bool) {
|
|
clientDebugF = log.New(log.Writer(), "client-debug: ", log.Flags()).Printf
|
|
}
|
|
|
|
if client, err = github.NewClient(p, log.Printf, cacheDebugF, clientDebugF); err != nil {
|
|
log.Panic(err)
|
|
}
|
|
}
|
|
|
|
skipPrivate := pass.Analyzer.Flags.Lookup("skip-private").Value.(flag.Getter).Get().(bool)
|
|
|
|
for _, f := range pass.Files {
|
|
for _, cg := range f.Comments {
|
|
for _, c := range cg.List {
|
|
line := c.Text
|
|
|
|
// the space between `//` and `TODO` is always added by `task fmt`
|
|
if !strings.HasPrefix(line, "// TODO") {
|
|
continue
|
|
}
|
|
|
|
if f.Name.Name == "testdata" {
|
|
line, _, _ = strings.Cut(line, ` // want "`)
|
|
}
|
|
|
|
match := todoRE.FindStringSubmatch(line)
|
|
|
|
if len(match) != 5 {
|
|
pass.Reportf(c.Pos(), "invalid TODO: incorrect format")
|
|
continue
|
|
}
|
|
|
|
url, owner, repo := match[1], match[2], match[3]
|
|
|
|
num, err := strconv.Atoi(match[4])
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if num <= 0 {
|
|
pass.Reportf(c.Pos(), "invalid TODO: incorrect issue number")
|
|
continue
|
|
}
|
|
|
|
if skipPrivate && repo == "docdb-internal" {
|
|
continue
|
|
}
|
|
|
|
status, err := client.IssueStatus(context.TODO(), owner, repo, num)
|
|
if err != nil {
|
|
log.Panic(err)
|
|
}
|
|
|
|
switch status {
|
|
case github.IssueOpen:
|
|
// nothing
|
|
case github.IssueClosed:
|
|
pass.Reportf(c.Pos(), "invalid TODO: linked issue %s is closed", url)
|
|
case github.IssueNotFound:
|
|
pass.Reportf(c.Pos(), "invalid TODO: linked issue %s is not found", url)
|
|
default:
|
|
log.Panicf("unknown issue status: %s", status)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, nil
|
|
}
|