Skip to content

Commit

Permalink
internal/go/gen: Ident type
Browse files Browse the repository at this point in the history
  • Loading branch information
ydnar committed Oct 27, 2023
1 parent eac23b8 commit 5b73438
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
41 changes: 41 additions & 0 deletions internal/go/gen/ident.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gen

import (
"strings"
)

// Ident represents a qualified Go identifier. It is a combination of
// a package path and a short name. For package identifiers, Path
// represents the package path (e.g. "encoding/json") and Name
// represents the short package name (e.g. "json").
type Ident struct {
Path string
Name string
}

// ParseIdent parses string s into an [Ident].
// It returns an error if s cannot be successfully parsed
func ParseIdent(s string) (Ident, error) {
var id Ident
id.Path, id.Name, _ = strings.Cut(s, "#")
if id.Name == "" {
i := strings.LastIndex(id.Path, "/")
if i >= 0 && i < len(id.Path)-1 {
id.Name = id.Path[i+1:] // encoding/json -> json
} else {
id.Name = id.Path // encoding -> encoding
}
}
return id, nil
}

// String returns the canonical string representation of id. It implements the [fmt.Stringer] interface.
//
// The canonical string representation of an [Ident] is "$path#$name". Examples:
// - For a package: "encoding/xml#xml"
// - For a type: "encoding/xml#Attr"
// - For a constant: "encoding/xml#Header"
// - For a function: "encoding/xml#Marshal"
func (id Ident) String() string {
return id.Path + "#" + id.Name
}
38 changes: 38 additions & 0 deletions internal/go/gen/ident_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package gen

import "testing"

func TestParseIdent(t *testing.T) {
tests := []struct {
s string
want Ident
wantErr bool
}{
{"io", Ident{"io", "io"}, false},
{"io/fs", Ident{"io/fs", "fs"}, false},
{"encoding/json", Ident{"encoding/json", "json"}, false},
{"encoding/xml", Ident{"encoding/xml", "xml"}, false},
{"encoding/xml#xml", Ident{"encoding/xml", "xml"}, false},
{"encoding/xml#encxml", Ident{"encoding/xml", "encxml"}, false},
{"encoding/xml#Encoder", Ident{"encoding/xml", "Encoder"}, false},
{"encoding/xml#Decoder", Ident{"encoding/xml", "Decoder"}, false},
{"wasi/clocks", Ident{"wasi/clocks", "clocks"}, false},
{"wasi/clocks#clocks", Ident{"wasi/clocks", "clocks"}, false},
{"wasi/clocks/wallclock", Ident{"wasi/clocks/wallclock", "wallclock"}, false},
{"wasi/clocks/wallclock#wallclock", Ident{"wasi/clocks/wallclock", "wallclock"}, false},
{"wasi/clocks/wallclock#DateTime", Ident{"wasi/clocks/wallclock", "DateTime"}, false},
}
for _, tt := range tests {
t.Run(tt.s, func(t *testing.T) {
got, err := ParseIdent(tt.s)
if tt.wantErr && err == nil {
t.Errorf("ParseIdent(%q): expected error, got nil error", tt.s)
} else if !tt.wantErr && err != nil {
t.Errorf("ParseIdent(%q): expected no error, got error: %v", tt.s, err)
}
if got != tt.want {
t.Errorf("ParseIdent(%q): expected %v, got %v", tt.s, tt.want, got)
}
})
}
}

0 comments on commit 5b73438

Please sign in to comment.