Tell the software's npm scope from a node in the particulars check, and compile its matchers once (issue 1838)
@novox/mesh-sdk and @novox:registry= are the software's package path, as the Go module path is; who@node is still a node name (1838/AC2). Reading every module, a regexp compiled per name per line made the check take 41 s; compiled once, 7.5 s.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
// CamelCase boundary parts one, so a longer word holding a name is another word.
|
||||
// Three names hold a node name and are not one, so they are blanked before a line is read: the forge's host
|
||||
// (git.novox.be) and organisation path (novox/<repo>), the hardware model (asus-zephyrus-g14, ROG Zephyrus G14)
|
||||
// and the software's own name (Novox Mesh, novox-mesh).
|
||||
// and the software's own name and npm scope (Novox Mesh, novox-mesh, @novox/mesh-sdk).
|
||||
//
|
||||
// go run . <catalogue root>
|
||||
//
|
||||
@@ -33,8 +33,10 @@ var forge = regexp.MustCompile(`(?i)git\.novox\.be(?:/novox/[\w.-]+)?|(?:^|[^/\w
|
||||
|
||||
// ownNames are the hardware model's and the software's own names, blanked before a line is read: the model
|
||||
// in any separator and case (asus-zephyrus-g14, ASUS_ZEPHYRUS_G14, ROG Zephyrus G14), the software as two
|
||||
// words or hyphened, whole (Novox Mesh, novox mesh, novox-mesh), so novox-mesh-vault stays a node name joined.
|
||||
var ownNames = regexp.MustCompile(`(?i)(?:asus[-_ ])?zephyrus[-_ ]g14|(?:^|[^\w-])novox[- ]mesh(?:$|[^\w-])`)
|
||||
// words or hyphened, whole (Novox Mesh, novox mesh, novox-mesh), so novox-mesh-vault stays a node name joined;
|
||||
// and the software's npm scope (@novox/mesh-sdk, @novox:registry=), its package path as the Go module path is,
|
||||
// where no word stands before the @, so a session's who@node (fix-1@novox) is still a node name.
|
||||
var ownNames = regexp.MustCompile(`(?i)(?:asus[-_ ])?zephyrus[-_ ]g14|(?:^|[^\w-])novox[- ]mesh(?:$|[^\w-])|(?:^|[^\w.-])@novox(?:$|[^\w-])`)
|
||||
|
||||
func main() {
|
||||
root := "."
|
||||
@@ -173,12 +175,24 @@ func hits(line string, names []string) []string {
|
||||
line = ownNames.ReplaceAllStringFunc(line, blank)
|
||||
var out []string
|
||||
for _, n := range names {
|
||||
q := regexp.QuoteMeta(n)
|
||||
camel := regexp.QuoteMeta(strings.ToUpper(n[:1]) + n[1:])
|
||||
rx := regexp.MustCompile(`(?i:(?:^|[^A-Za-z0-9])` + q + `(?:$|[^A-Za-z0-9]))|[a-z0-9]` + camel + `(?:$|[^a-z])|(?:^|[^A-Za-z0-9])` + q + `[A-Z0-9]`)
|
||||
if rx.MatchString(line) {
|
||||
if matcher(n).MatchString(line) {
|
||||
out = append(out, strings.ToLower(n))
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// matchers holds each name's matcher, compiled once: the check reads every line of every module.
|
||||
var matchers = map[string]*regexp.Regexp{}
|
||||
|
||||
// matcher is the matcher of one name: as a word, or as a part of a CamelCase identifier.
|
||||
func matcher(n string) *regexp.Regexp {
|
||||
if rx, ok := matchers[n]; ok {
|
||||
return rx
|
||||
}
|
||||
q := regexp.QuoteMeta(n)
|
||||
camel := regexp.QuoteMeta(strings.ToUpper(n[:1]) + n[1:])
|
||||
rx := regexp.MustCompile(`(?i:(?:^|[^A-Za-z0-9])` + q + `(?:$|[^A-Za-z0-9]))|[a-z0-9]` + camel + `(?:$|[^a-z])|(?:^|[^A-Za-z0-9])` + q + `[A-Z0-9]`)
|
||||
matchers[n] = rx
|
||||
return rx
|
||||
}
|
||||
|
||||
@@ -169,3 +169,32 @@ func TestANodeNameBesideTheHardwareOrTheSoftwareIsRefused(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1838/AC2: the software's npm scope (@novox/mesh-sdk, @novox:registry=) is its package path, as the Go module
|
||||
// path is; a session's who@node naming a node is still a node name.
|
||||
func TestTheSoftwaresNpmScopeIsNotANodeName(t *testing.T) {
|
||||
for _, s := range []string{
|
||||
"printf '%s\\n' ${shellQuote(`@novox:registry=${registry}`)}",
|
||||
"const url = `${asked}@novox%2fmesh-sdk`;",
|
||||
"# The @novox scope resolves from the mesh's own package registry",
|
||||
`"dependencies": { "@novox/mesh-sdk": "^0.1.0" }`,
|
||||
} {
|
||||
if got := scan("f", s, names); len(got) != 0 {
|
||||
t.Errorf("%q refused: %v", s, got)
|
||||
}
|
||||
}
|
||||
for _, s := range []string{"by fix-1@novox", "jochen@novox:"} {
|
||||
if got := scan("f", s, names); len(got) != 1 {
|
||||
t.Errorf("%q gave %v, want one finding", s, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 1838/AC1: reading every module, the check compiles its matchers once, not once a line: a line read costs a
|
||||
// few allocations, not a regexp compiled per name (the whole catalogue took 41 s with one per line).
|
||||
func TestALineIsReadWithoutCompilingAMatcher(t *testing.T) {
|
||||
line := "a line of code that names nothing at all, with git.novox.be/novox/mesh-sdk in it"
|
||||
if n := testing.AllocsPerRun(100, func() { hits(line, names) }); n > 20 {
|
||||
t.Errorf("a line costs %.0f allocations, want at most 20", n)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user