Remove dead code (#1833)
Large parts of pkg/tokens are not used anymore and can be deleted.
This commit is contained in:
parent
1f8938e234
commit
1624d4a1fe
5 changed files with 5 additions and 736 deletions
|
@ -1,44 +0,0 @@
|
||||||
// Copyright 2016-2018, Pulumi Corporation.
|
|
||||||
//
|
|
||||||
// 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 tokens
|
|
||||||
|
|
||||||
// Accessibility determines the visibility of a class member.
|
|
||||||
type Accessibility string
|
|
||||||
|
|
||||||
// Accessibility modifiers.
|
|
||||||
const (
|
|
||||||
PublicAccessibility Accessibility = "public"
|
|
||||||
PrivateAccessibility Accessibility = "private"
|
|
||||||
ProtectedAccessibility Accessibility = "protected"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Special module names.
|
|
||||||
const (
|
|
||||||
DefaultModule ModuleName = ".default" // used to reference the default module.
|
|
||||||
)
|
|
||||||
|
|
||||||
// Special variable names.
|
|
||||||
const (
|
|
||||||
ThisVariable Name = ".this" // the current object (for class methods).
|
|
||||||
SuperVariable Name = ".super" // the parent class object (for class methods).
|
|
||||||
)
|
|
||||||
|
|
||||||
// Special function names.
|
|
||||||
const (
|
|
||||||
EntryPointFunction ModuleMemberName = ".main" // the special package entrypoint function.
|
|
||||||
ModuleInitFunction ModuleMemberName = ".init" // the special module initialization function.
|
|
||||||
ClassConstructorFunction ClassMemberName = ".ctor" // the special class instance constructor function.
|
|
||||||
ClassInitFunction ClassMemberName = ".init" // the special class initialization function.
|
|
||||||
)
|
|
|
@ -1,351 +0,0 @@
|
||||||
// Copyright 2016-2018, Pulumi Corporation.
|
|
||||||
//
|
|
||||||
// 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 tokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/pulumi/pulumi/pkg/util/contract"
|
|
||||||
)
|
|
||||||
|
|
||||||
// tokenBuffer is a parseable token buffer that simply carries a position.
|
|
||||||
type tokenBuffer struct {
|
|
||||||
Tok Type
|
|
||||||
Pos int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newTokenBuffer(tok Type) *tokenBuffer {
|
|
||||||
return &tokenBuffer{
|
|
||||||
Tok: tok,
|
|
||||||
Pos: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) Curr() Type {
|
|
||||||
return b.Tok[b.Pos:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) From(from int) Type {
|
|
||||||
return b.Tok[from:b.Pos]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) Eat(s string) {
|
|
||||||
ate := b.MayEat(s)
|
|
||||||
contract.Assertf(ate, "Expected to eat '%v'", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) MayEat(s string) bool {
|
|
||||||
if strings.HasPrefix(string(b.Curr()), s) {
|
|
||||||
b.Advance(len(s))
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) Advance(by int) {
|
|
||||||
b.Pos += by
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) Done() bool {
|
|
||||||
return b.Pos == len(b.Tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *tokenBuffer) Finish() {
|
|
||||||
b.Pos = len(b.Tok)
|
|
||||||
}
|
|
||||||
|
|
||||||
// typePartDelims are separator characters that are used to parse recursive types.
|
|
||||||
var typePartDelims = MapTypeSeparator + FunctionTypeParamSeparator + FunctionTypeSeparator
|
|
||||||
|
|
||||||
// parseNextType parses one type out of the given token, mutating the buffer in place and returning the resulting type
|
|
||||||
// token. This allows recursive parsing of complex decorated types below (like `map[[]string]func(func())`).
|
|
||||||
func parseNextType(b *tokenBuffer) Type {
|
|
||||||
// First, check for decorated types.
|
|
||||||
tok := b.Curr()
|
|
||||||
if tok.Pointer() {
|
|
||||||
ptr := parseNextPointerType(b)
|
|
||||||
return ptr.Tok
|
|
||||||
} else if tok.Array() {
|
|
||||||
arr := parseNextArrayType(b)
|
|
||||||
return arr.Tok
|
|
||||||
} else if tok.Map() {
|
|
||||||
mam := parseNextMapType(b)
|
|
||||||
return mam.Tok
|
|
||||||
} else if tok.Function() {
|
|
||||||
fnc := parseNextFunctionType(b)
|
|
||||||
return fnc.Tok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, we have either a qualified or simple (primitive) name. Since we might be deep in the middle
|
|
||||||
// of parsing another token, however, we only parse up to any other decorator termination/separator tokens.
|
|
||||||
s := string(tok)
|
|
||||||
sep := strings.IndexAny(s, typePartDelims)
|
|
||||||
if sep == -1 {
|
|
||||||
b.Finish()
|
|
||||||
return tok
|
|
||||||
}
|
|
||||||
b.Advance(sep)
|
|
||||||
return tok[:sep]
|
|
||||||
}
|
|
||||||
|
|
||||||
// PointerType is a type token that decorates an element type token turn it into a pointer: `"*" <Elem>`.
|
|
||||||
type PointerType struct {
|
|
||||||
Tok Type // the full pointer type token.
|
|
||||||
Elem Type // the element portion of the pointer type token.
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
PointerTypeDecors = PointerTypePrefix + "%v"
|
|
||||||
PointerTypePrefix = "*"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewPointerTypeName creates a new array type name from an element type.
|
|
||||||
func NewPointerTypeName(elem TypeName) TypeName {
|
|
||||||
return TypeName(fmt.Sprintf(PointerTypeDecors, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewPointerTypeToken creates a new array type token from an element type.
|
|
||||||
func NewPointerTypeToken(elem Type) Type {
|
|
||||||
return Type(fmt.Sprintf(PointerTypeDecors, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPointerType returns true if the given type token represents an encoded pointer type.
|
|
||||||
func IsPointerType(tok Type) bool {
|
|
||||||
return strings.HasPrefix(tok.String(), PointerTypePrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParsePointerType removes the pointer decorations from a token and returns its underlying type.
|
|
||||||
func ParsePointerType(tok Type) PointerType {
|
|
||||||
b := newTokenBuffer(tok)
|
|
||||||
ptr := parseNextPointerType(b)
|
|
||||||
if !b.Done() {
|
|
||||||
contract.Failf("Did not expect anything extra after the pointer type %v; got: '%v'", tok, b.Curr())
|
|
||||||
}
|
|
||||||
return ptr
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNextPointerType parses the next pointer type from the given buffer.
|
|
||||||
func parseNextPointerType(b *tokenBuffer) PointerType {
|
|
||||||
mark := b.Pos // remember where this token begins.
|
|
||||||
b.Eat(PointerTypePrefix) // eat the "*" part.
|
|
||||||
elem := parseNextType(b) // parse the required element type token.
|
|
||||||
contract.Assert(elem != "")
|
|
||||||
return PointerType{Tok: b.From(mark), Elem: elem}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ArrayType is a type token that decorates an element type token to turn it into an array: `"[]" <Elem>`.
|
|
||||||
type ArrayType struct {
|
|
||||||
Tok Type // the full array type token.
|
|
||||||
Elem Type // the element portion of the array type token.
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
ArrayTypeDecors = ArrayTypePrefix + "%v"
|
|
||||||
ArrayTypePrefix = "[]"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewArrayTypeName creates a new array type name from an element type.
|
|
||||||
func NewArrayTypeName(elem TypeName) TypeName {
|
|
||||||
return TypeName(fmt.Sprintf(ArrayTypeDecors, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewArrayTypeToken creates a new array type token from an element type.
|
|
||||||
func NewArrayTypeToken(elem Type) Type {
|
|
||||||
return Type(fmt.Sprintf(ArrayTypeDecors, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsArrayType returns true if the given type token represents an encoded pointer type.
|
|
||||||
func IsArrayType(tok Type) bool {
|
|
||||||
return strings.HasPrefix(tok.String(), ArrayTypePrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseArrayType removes the array decorations from a token and returns its underlying type.
|
|
||||||
func ParseArrayType(tok Type) ArrayType {
|
|
||||||
b := newTokenBuffer(tok)
|
|
||||||
arr := parseNextArrayType(b)
|
|
||||||
if !b.Done() {
|
|
||||||
contract.Failf("Did not expect anything extra after the array type %v; got: '%v'", tok, b.Curr())
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNextArrayType parses the next array type from the given buffer.
|
|
||||||
func parseNextArrayType(b *tokenBuffer) ArrayType {
|
|
||||||
mark := b.Pos // remember where this token begins.
|
|
||||||
b.Eat(ArrayTypePrefix) // eat the "[]" part.
|
|
||||||
elem := parseNextType(b) // parse the required element type token.
|
|
||||||
contract.Assert(elem != "")
|
|
||||||
return ArrayType{Tok: b.From(mark), Elem: elem}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapType is a type token that decorates a key and element type token to turn them into a map:
|
|
||||||
// `"map[" <Key> "]" <Elem>`.
|
|
||||||
type MapType struct {
|
|
||||||
Tok Type // the full map type token.
|
|
||||||
Key Type // the key portion of the map type token.
|
|
||||||
Elem Type // the element portion of the map type token.
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
MapTypeDecors = MapTypePrefix + "%v" + MapTypeSeparator + "%v"
|
|
||||||
MapTypePrefix = "map["
|
|
||||||
MapTypeSeparator = "]"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewMapTypeName creates a new map type name from an element type.
|
|
||||||
func NewMapTypeName(key TypeName, elem TypeName) TypeName {
|
|
||||||
return TypeName(fmt.Sprintf(MapTypeDecors, key, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMapTypeToken creates a new map type token from an element type.
|
|
||||||
func NewMapTypeToken(key Type, elem Type) Type {
|
|
||||||
return Type(fmt.Sprintf(MapTypeDecors, key, elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsMapType returns true if the given type token represents an encoded pointer type.
|
|
||||||
func IsMapType(tok Type) bool {
|
|
||||||
return strings.HasPrefix(tok.String(), MapTypePrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseMapType removes the map decorations from a token and returns its underlying type.
|
|
||||||
func ParseMapType(tok Type) MapType {
|
|
||||||
b := newTokenBuffer(tok)
|
|
||||||
mam := parseNextMapType(b)
|
|
||||||
if !b.Done() {
|
|
||||||
contract.Failf("Did not expect anything extra after the map type %v; got: '%v'", tok, b.Curr())
|
|
||||||
}
|
|
||||||
return mam
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNextMapType parses the next map type from the given buffer.
|
|
||||||
func parseNextMapType(b *tokenBuffer) MapType {
|
|
||||||
mark := b.Pos // remember where this token begins.
|
|
||||||
b.Eat(MapTypePrefix) // eat the "map[" prefix.
|
|
||||||
|
|
||||||
// Now parse the key part.
|
|
||||||
key := parseNextType(b)
|
|
||||||
contract.Assert(key != "")
|
|
||||||
|
|
||||||
// Next, we expect to find the "]" separator token; eat it.
|
|
||||||
b.Eat(MapTypeSeparator)
|
|
||||||
|
|
||||||
// Next, parse the element type part.
|
|
||||||
elem := parseNextType(b)
|
|
||||||
contract.Assert(elem != "")
|
|
||||||
return MapType{Tok: b.From(mark), Key: key, Elem: elem}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FunctionType is a type token that decorates a set of optional parameter and return tokens to turn them into a
|
|
||||||
// function type: `(" [ <Param1> [ "," <ParamN> ]* ] ")" [ <Return> ]`).
|
|
||||||
type FunctionType struct {
|
|
||||||
Tok Type // the full map type token.
|
|
||||||
Parameters []Type // the parameter parts of the type token.
|
|
||||||
Return *Type // the (optional) return part of the type token.
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
FunctionTypeDecors = FunctionTypePrefix + "%v" + FunctionTypeSeparator + "%v"
|
|
||||||
FunctionTypePrefix = "("
|
|
||||||
FunctionTypeParamSeparator = ","
|
|
||||||
FunctionTypeSeparator = ")"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewFunctionTypeName creates a new function type token from parameter and return types.
|
|
||||||
func NewFunctionTypeName(params []TypeName, ret *TypeName) TypeName {
|
|
||||||
// Stringify the parameters (if any).
|
|
||||||
sparams := ""
|
|
||||||
for i, param := range params {
|
|
||||||
if i > 0 {
|
|
||||||
sparams += FunctionTypeParamSeparator
|
|
||||||
}
|
|
||||||
sparams += string(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stringify the return type (if any).
|
|
||||||
sret := ""
|
|
||||||
if ret != nil {
|
|
||||||
sret = string(*ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
return TypeName(fmt.Sprintf(FunctionTypeDecors, sparams, sret))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFunctionTypeToken creates a new function type token from parameter and return types.
|
|
||||||
func NewFunctionTypeToken(params []Type, ret *Type) Type {
|
|
||||||
// Stringify the parameters (if any).
|
|
||||||
sparams := ""
|
|
||||||
for i, param := range params {
|
|
||||||
if i > 0 {
|
|
||||||
sparams += FunctionTypeParamSeparator
|
|
||||||
}
|
|
||||||
sparams += string(param)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stringify the return type (if any).
|
|
||||||
sret := ""
|
|
||||||
if ret != nil {
|
|
||||||
sret = string(*ret)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Type(fmt.Sprintf(FunctionTypeDecors, sparams, sret))
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsFunctionType returns true if the given type token represents an encoded pointer type.
|
|
||||||
func IsFunctionType(tok Type) bool {
|
|
||||||
return strings.HasPrefix(tok.String(), FunctionTypePrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseFunctionType removes the function decorations from a token and returns its underlying type.
|
|
||||||
func ParseFunctionType(tok Type) FunctionType {
|
|
||||||
b := newTokenBuffer(tok)
|
|
||||||
fnc := parseNextFunctionType(b)
|
|
||||||
if !b.Done() {
|
|
||||||
contract.Failf("Did not expect anything extra after the function type %v; got: '%v'", tok, b.Curr())
|
|
||||||
}
|
|
||||||
return fnc
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseNextFunctionType parses the next function type from the given token, returning any excess.
|
|
||||||
func parseNextFunctionType(b *tokenBuffer) FunctionType {
|
|
||||||
mark := b.Pos // remember the start of this token.
|
|
||||||
b.Eat(FunctionTypePrefix) // eat the function prefix "(".
|
|
||||||
|
|
||||||
// Parse out parameters until we encounter and eat a ")".
|
|
||||||
var params []Type
|
|
||||||
for !b.MayEat(FunctionTypeSeparator) {
|
|
||||||
next := parseNextType(b)
|
|
||||||
if next == "" {
|
|
||||||
contract.Assert(strings.HasPrefix(string(b.Curr()), FunctionTypeSeparator))
|
|
||||||
} else {
|
|
||||||
params = append(params, next)
|
|
||||||
|
|
||||||
// Eat the separator, if any, and keep going.
|
|
||||||
if !b.MayEat(FunctionTypeParamSeparator) {
|
|
||||||
contract.Assert(strings.HasPrefix(string(b.Curr()), FunctionTypeSeparator))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, if there is anything remaining, parse out the return type.
|
|
||||||
var ret *Type
|
|
||||||
if !b.Done() {
|
|
||||||
if rett := parseNextType(b); rett != "" {
|
|
||||||
ret = &rett
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FunctionType{Tok: b.From(mark), Parameters: params, Return: ret}
|
|
||||||
}
|
|
|
@ -1,250 +0,0 @@
|
||||||
// Copyright 2016-2018, Pulumi Corporation.
|
|
||||||
//
|
|
||||||
// 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 tokens
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newTestTypeToken(nm string) Type {
|
|
||||||
pkg := NewPackageToken("test/package")
|
|
||||||
mod := NewModuleToken(pkg, "test/module")
|
|
||||||
return NewTypeToken(mod, TypeName(nm))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestArrayTypes(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Test simple primitives.
|
|
||||||
for _, prim := range []string{"any", "bool", "string", "number"} {
|
|
||||||
ptr := NewArrayTypeToken(Type(prim))
|
|
||||||
assert.True(t, ptr.Array(), "Expected array type token to be an array")
|
|
||||||
parsed := ParseArrayType(ptr)
|
|
||||||
assert.Equal(t, prim, string(parsed.Elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test more complex array type elements.
|
|
||||||
class := newTestTypeToken("ArrayTest")
|
|
||||||
ptr := NewArrayTypeToken(class)
|
|
||||||
assert.True(t, ptr.Array(), "Expected array type token to be an array")
|
|
||||||
parsed := ParseArrayType(ptr)
|
|
||||||
assert.Equal(t, string(class), string(parsed.Elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPointerTypes(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Test simple primitives.
|
|
||||||
for _, prim := range []string{"any", "bool", "string", "number"} {
|
|
||||||
ptr := NewPointerTypeToken(Type(prim))
|
|
||||||
assert.True(t, ptr.Pointer(), "Expected pointer type token to be a pointer")
|
|
||||||
parsed := ParsePointerType(ptr)
|
|
||||||
assert.Equal(t, prim, string(parsed.Elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test more complex pointer type elements.
|
|
||||||
class := newTestTypeToken("PointerTest")
|
|
||||||
ptr := NewPointerTypeToken(class)
|
|
||||||
assert.True(t, ptr.Pointer(), "Expected pointer type token to be a pointer")
|
|
||||||
parsed := ParsePointerType(ptr)
|
|
||||||
assert.Equal(t, string(class), string(parsed.Elem))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMapTypes(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Test simple primitives.
|
|
||||||
for _, key := range []string{"string", "bool", "number"} {
|
|
||||||
for _, elem := range []string{"any", "bool", "string", "number"} {
|
|
||||||
ptr := NewMapTypeToken(Type(key), Type(elem))
|
|
||||||
assert.True(t, ptr.Map(), "Expected map type token to be a map")
|
|
||||||
parsed := ParseMapType(ptr)
|
|
||||||
assert.Equal(t, key, string(parsed.Key))
|
|
||||||
assert.Equal(t, elem, string(parsed.Elem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test more complex map type elements.
|
|
||||||
for _, key := range []string{"string", "bool", "number"} {
|
|
||||||
class := newTestTypeToken("MapTest")
|
|
||||||
ptr := NewMapTypeToken(Type(key), class)
|
|
||||||
assert.True(t, ptr.Map(), "Expected map type token to be a map")
|
|
||||||
parsed := ParseMapType(ptr)
|
|
||||||
assert.Equal(t, key, string(parsed.Key))
|
|
||||||
assert.Equal(t, string(class), string(parsed.Elem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFunctionTypes(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
class := newTestTypeToken("FuncTest")
|
|
||||||
types := []string{"any", "bool", "string", "number", string(class)}
|
|
||||||
rtypes := append([]string{""}, types...)
|
|
||||||
for _, retty := range rtypes {
|
|
||||||
// If the return exists, use it.
|
|
||||||
var ret *Type
|
|
||||||
if retty != "" {
|
|
||||||
r := Type(retty)
|
|
||||||
ret = &r
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do [0...4) parameter counts.
|
|
||||||
for i := 0; i < 4; i++ {
|
|
||||||
ixs := make([]int, i)
|
|
||||||
for {
|
|
||||||
// Append the current set to the params.
|
|
||||||
var params []Type
|
|
||||||
for _, ix := range ixs {
|
|
||||||
params = append(params, Type(types[ix]))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the result.
|
|
||||||
fnc := NewFunctionTypeToken(params, ret)
|
|
||||||
assert.True(t, fnc.Function(), "Expected function type token to be a function")
|
|
||||||
parsed := ParseFunctionType(fnc)
|
|
||||||
assert.Equal(t, len(params), len(parsed.Parameters))
|
|
||||||
for i, param := range parsed.Parameters {
|
|
||||||
assert.Equal(t, string(params[i]), string(param))
|
|
||||||
}
|
|
||||||
if ret == nil {
|
|
||||||
assert.Nil(t, parsed.Return)
|
|
||||||
} else {
|
|
||||||
assert.NotNil(t, parsed.Return)
|
|
||||||
assert.Equal(t, string(*ret), string(*parsed.Return))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now rotate the parameters (or break if done).
|
|
||||||
done := (i == 0)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
ixs[j]++
|
|
||||||
if ixs[j] == len(types) {
|
|
||||||
// Reset the counter, and keep incrementing.
|
|
||||||
ixs[j] = 0
|
|
||||||
if j == i-1 {
|
|
||||||
// Done altogether; break break break!
|
|
||||||
done = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// The lower indices aren't exhausted, stop incrementing.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if done {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestComplexTypes(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Create a crazy nested type and make sure they parse correctly; essentially:
|
|
||||||
// *[]map[string]map[()*(bool,string,Crazy)number][][]Crazy
|
|
||||||
// or, in the fully qualified form:
|
|
||||||
// *[]map[string]map[()*(bool,string,test/package:test/module/Crazy)number][][]test/package:test/module/Crazy
|
|
||||||
// which should parse as
|
|
||||||
// Pointer
|
|
||||||
// Elem=Array
|
|
||||||
// Elem=Map
|
|
||||||
// Key=string
|
|
||||||
// Elem=Map
|
|
||||||
// Key=Func
|
|
||||||
// Params=()
|
|
||||||
// Return=Pointer
|
|
||||||
// Func
|
|
||||||
// Params=
|
|
||||||
// bool
|
|
||||||
// string
|
|
||||||
// Crazy
|
|
||||||
// Return=number
|
|
||||||
// Elem=Array
|
|
||||||
// Elem=Array
|
|
||||||
// Elem=Crazy
|
|
||||||
crazy := newTestTypeToken("Crazy")
|
|
||||||
|
|
||||||
number := Type("number")
|
|
||||||
ptrret := NewPointerTypeToken(NewFunctionTypeToken([]Type{"bool", "string", crazy}, &number))
|
|
||||||
|
|
||||||
ptr := NewPointerTypeToken(
|
|
||||||
NewArrayTypeToken(
|
|
||||||
NewMapTypeToken(
|
|
||||||
Type("string"),
|
|
||||||
NewMapTypeToken(
|
|
||||||
NewFunctionTypeToken(
|
|
||||||
[]Type{},
|
|
||||||
&ptrret,
|
|
||||||
),
|
|
||||||
NewArrayTypeToken(
|
|
||||||
NewArrayTypeToken(
|
|
||||||
crazy,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
assert.True(t, ptr.Pointer(), "Expected pointer type token to be an pointer")
|
|
||||||
p1 := ParsePointerType(ptr) // Pointer<Array>
|
|
||||||
{
|
|
||||||
assert.True(t, p1.Elem.Array())
|
|
||||||
p2 := ParseArrayType(p1.Elem) // Array<Map>
|
|
||||||
{
|
|
||||||
assert.True(t, p2.Elem.Map())
|
|
||||||
p3 := ParseMapType(p2.Elem) // Map<string, Map>
|
|
||||||
{
|
|
||||||
assert.Equal(t, "string", string(p3.Key))
|
|
||||||
assert.True(t, p3.Elem.Map())
|
|
||||||
p4 := ParseMapType(p3.Elem) // Map<Func, Array>
|
|
||||||
{
|
|
||||||
assert.True(t, p4.Key.Function())
|
|
||||||
p5 := ParseFunctionType(p4.Key) // Func<(), Pointer>
|
|
||||||
{
|
|
||||||
assert.Equal(t, 0, len(p5.Parameters))
|
|
||||||
assert.NotNil(t, p5.Return)
|
|
||||||
assert.True(t, (*p5.Return).Pointer())
|
|
||||||
p6 := ParsePointerType(*p5.Return) // Pointer<Func>
|
|
||||||
{
|
|
||||||
assert.True(t, p6.Elem.Function())
|
|
||||||
p7 := ParseFunctionType(p6.Elem) // Func<(bool,string,Crazy), number>
|
|
||||||
{
|
|
||||||
assert.Equal(t, 3, len(p7.Parameters))
|
|
||||||
assert.Equal(t, "bool", string(p7.Parameters[0]))
|
|
||||||
assert.Equal(t, "string", string(p7.Parameters[1]))
|
|
||||||
assert.Equal(t, string(crazy), string(p7.Parameters[2]))
|
|
||||||
assert.NotNil(t, p7.Return)
|
|
||||||
assert.Equal(t, "number", string(*p7.Return))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert.True(t, p4.Elem.Array())
|
|
||||||
p8 := ParseArrayType(p4.Elem) // Array<Array>
|
|
||||||
{
|
|
||||||
assert.True(t, p8.Elem.Array())
|
|
||||||
p9 := ParseArrayType(p8.Elem) // Array<Crazy>
|
|
||||||
{
|
|
||||||
assert.Equal(t, string(crazy), string(p9.Elem))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -63,7 +63,6 @@ const TokenDelimiter string = ":" // the character delimiting portions of a qual
|
||||||
func (tok Token) Delimiters() int { return strings.Count(string(tok), TokenDelimiter) }
|
func (tok Token) Delimiters() int { return strings.Count(string(tok), TokenDelimiter) }
|
||||||
func (tok Token) HasModule() bool { return tok.Delimiters() > 0 }
|
func (tok Token) HasModule() bool { return tok.Delimiters() > 0 }
|
||||||
func (tok Token) HasModuleMember() bool { return tok.Delimiters() > 1 }
|
func (tok Token) HasModuleMember() bool { return tok.Delimiters() > 1 }
|
||||||
func (tok Token) HasClassMember() bool { return tok.Delimiters() > 2 }
|
|
||||||
func (tok Token) Simple() bool { return tok.Delimiters() == 0 }
|
func (tok Token) Simple() bool { return tok.Delimiters() == 0 }
|
||||||
func (tok Token) String() string { return string(tok) }
|
func (tok Token) String() string { return string(tok) }
|
||||||
|
|
||||||
|
@ -98,7 +97,7 @@ func (tok Token) Name() Name {
|
||||||
|
|
||||||
// Package extracts the package from the token, assuming one exists.
|
// Package extracts the package from the token, assuming one exists.
|
||||||
func (tok Token) Package() Package {
|
func (tok Token) Package() Package {
|
||||||
if t := Type(tok); t.Decorated() || t.Primitive() {
|
if t := Type(tok); t.Primitive() {
|
||||||
return "" // decorated and primitive types are built-in (and hence have no package).
|
return "" // decorated and primitive types are built-in (and hence have no package).
|
||||||
}
|
}
|
||||||
if tok.HasModule() {
|
if tok.HasModule() {
|
||||||
|
@ -121,22 +120,11 @@ func (tok Token) Module() Module {
|
||||||
// ModuleMember extracts the module member portion from the token, assuming one exists.
|
// ModuleMember extracts the module member portion from the token, assuming one exists.
|
||||||
func (tok Token) ModuleMember() ModuleMember {
|
func (tok Token) ModuleMember() ModuleMember {
|
||||||
if tok.HasModuleMember() {
|
if tok.HasModuleMember() {
|
||||||
if tok.HasClassMember() {
|
|
||||||
return ModuleMember(tok[:tok.delimiter(3)])
|
|
||||||
}
|
|
||||||
return ModuleMember(tok)
|
return ModuleMember(tok)
|
||||||
}
|
}
|
||||||
return ModuleMember("")
|
return ModuleMember("")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClassMember extracts the class member portion from the token, assuming one exists.
|
|
||||||
func (tok Token) ClassMember() ClassMember {
|
|
||||||
if tok.HasClassMember() {
|
|
||||||
return ClassMember(tok)
|
|
||||||
}
|
|
||||||
return ClassMember("")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Package is a token representing just a package. It uses a much simpler grammar:
|
// Package is a token representing just a package. It uses a much simpler grammar:
|
||||||
// Package = <PackageName>
|
// Package = <PackageName>
|
||||||
// Note that a package name of "." means "current package", to simplify emission and lookups.
|
// Note that a package name of "." means "current package", to simplify emission and lookups.
|
||||||
|
@ -213,38 +201,6 @@ func (tok ModuleMember) Name() ModuleMemberName {
|
||||||
|
|
||||||
func (tok ModuleMember) String() string { return string(tok) }
|
func (tok ModuleMember) String() string { return string(tok) }
|
||||||
|
|
||||||
// ClassMember is a token representing a class's member. It uses the following grammar. Unlike ModuleMember, this
|
|
||||||
// cannot use a slash for delimiting names, because we use often ClassMember and ModuleMember interchangeably:
|
|
||||||
// ClassMember = <ModuleMember> "." <ClassMemberName>
|
|
||||||
type ClassMember Token
|
|
||||||
|
|
||||||
func NewClassMemberToken(class Type, nm ClassMemberName) ClassMember {
|
|
||||||
contract.Assertf(IsName(string(nm)), "Class '%v' member name '%v' is not a legal name", class, nm)
|
|
||||||
return ClassMember(string(class) + TokenDelimiter + string(nm))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok ClassMember) Package() Package {
|
|
||||||
return tok.Module().Package()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok ClassMember) Module() Module {
|
|
||||||
return tok.Class().Module()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok ClassMember) Class() Type {
|
|
||||||
t := Token(tok)
|
|
||||||
contract.Assertf(t.HasClassMember(), "Class member token '%v' missing class member delimiter", tok)
|
|
||||||
return Type(tok[:t.delimiter(3)])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok ClassMember) Name() ClassMemberName {
|
|
||||||
t := Token(tok)
|
|
||||||
contract.Assertf(t.HasClassMember(), "Class member token '%v' missing class member delimiter", tok)
|
|
||||||
return ClassMemberName(tok[t.delimiter(3)+1:])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok ClassMember) String() string { return string(tok) }
|
|
||||||
|
|
||||||
// Type is a token representing a type. It is either a primitive type name, reference to a module class, or decorated:
|
// Type is a token representing a type. It is either a primitive type name, reference to a module class, or decorated:
|
||||||
// Type = <Name> | <ModuleMember> | <DecoratedType>
|
// Type = <Name> | <ModuleMember> | <DecoratedType>
|
||||||
type Type Token
|
type Type Token
|
||||||
|
@ -255,21 +211,21 @@ func NewTypeToken(mod Module, nm TypeName) Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tok Type) Package() Package {
|
func (tok Type) Package() Package {
|
||||||
if tok.Primitive() || tok.Decorated() {
|
if tok.Primitive() {
|
||||||
return Package("")
|
return Package("")
|
||||||
}
|
}
|
||||||
return ModuleMember(tok).Package()
|
return ModuleMember(tok).Package()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tok Type) Module() Module {
|
func (tok Type) Module() Module {
|
||||||
if tok.Primitive() || tok.Decorated() {
|
if tok.Primitive() {
|
||||||
return Module("")
|
return Module("")
|
||||||
}
|
}
|
||||||
return ModuleMember(tok).Module()
|
return ModuleMember(tok).Module()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tok Type) Name() TypeName {
|
func (tok Type) Name() TypeName {
|
||||||
if tok.Primitive() || tok.Decorated() {
|
if tok.Primitive() {
|
||||||
return TypeName(tok)
|
return TypeName(tok)
|
||||||
}
|
}
|
||||||
return TypeName(ModuleMember(tok).Name())
|
return TypeName(ModuleMember(tok).Name())
|
||||||
|
@ -279,40 +235,9 @@ func (tok Type) Member() ModuleMember {
|
||||||
return ModuleMember(tok)
|
return ModuleMember(tok)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decorated indicates whether this token represents a decorated type.
|
|
||||||
func (tok Type) Decorated() bool {
|
|
||||||
return tok.Pointer() || tok.Array() || tok.Map() || tok.Function()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tok Type) Pointer() bool { return IsPointerType(tok) }
|
|
||||||
func (tok Type) Array() bool { return IsArrayType(tok) }
|
|
||||||
func (tok Type) Map() bool { return IsMapType(tok) }
|
|
||||||
func (tok Type) Function() bool { return IsFunctionType(tok) }
|
|
||||||
|
|
||||||
// Primitive indicates whether this type is a primitive type name (i.e., not qualified with a module, etc).
|
// Primitive indicates whether this type is a primitive type name (i.e., not qualified with a module, etc).
|
||||||
func (tok Type) Primitive() bool {
|
func (tok Type) Primitive() bool {
|
||||||
return !tok.Decorated() && !Token(tok).HasModule()
|
return !Token(tok).HasModule()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tok Type) String() string { return string(tok) }
|
func (tok Type) String() string { return string(tok) }
|
||||||
|
|
||||||
// Variable is a token representing a variable (module property, class property, or local variable (including
|
|
||||||
// parameters)). It can be a simple name for the local cases, or a true token for others:
|
|
||||||
// Variable = <Name> | <ModuleMember> | <ClassMember>
|
|
||||||
type Variable Token
|
|
||||||
|
|
||||||
func (tok Variable) String() string { return string(tok) }
|
|
||||||
|
|
||||||
// Function is a token representing a variable (module method or class method). Its grammar is as follows:
|
|
||||||
// Variable = <ModuleMember> | <ClassMember>
|
|
||||||
type Function Token
|
|
||||||
|
|
||||||
func (tok Function) String() string { return string(tok) }
|
|
||||||
|
|
||||||
// ByName implements sort.Interface to allow an array of tokens to be
|
|
||||||
// sorted based on string order.
|
|
||||||
type ByName []Token
|
|
||||||
|
|
||||||
func (ts ByName) Len() int { return len(ts) }
|
|
||||||
func (ts ByName) Less(i int, j int) bool { return ts[i] < ts[j] }
|
|
||||||
func (ts ByName) Swap(i int, j int) { ts[i], ts[j] = ts[j], ts[i] }
|
|
||||||
|
|
|
@ -55,15 +55,4 @@ func TestTokens(t *testing.T) {
|
||||||
assert.Equal(t, m, modm.Module().Name().String())
|
assert.Equal(t, m, modm.Module().Name().String())
|
||||||
assert.Equal(t, p, modm.Module().Package().Name().String())
|
assert.Equal(t, p, modm.Module().Package().Name().String())
|
||||||
assert.Equal(t, p+TokenDelimiter+m+TokenDelimiter+mm, modm.String())
|
assert.Equal(t, p+TokenDelimiter+m+TokenDelimiter+mm, modm.String())
|
||||||
|
|
||||||
// Class member tokens/names.
|
|
||||||
cm := "property"
|
|
||||||
assert.True(t, IsName(cm))
|
|
||||||
assert.True(t, IsQName(cm))
|
|
||||||
clm := NewClassMemberToken(Type(modm), ClassMemberName(cm))
|
|
||||||
assert.Equal(t, cm, clm.Name().String())
|
|
||||||
assert.Equal(t, mm, clm.Class().Name().String())
|
|
||||||
assert.Equal(t, m, clm.Class().Module().Name().String())
|
|
||||||
assert.Equal(t, p, clm.Class().Module().Package().Name().String())
|
|
||||||
assert.Equal(t, p+TokenDelimiter+m+TokenDelimiter+mm+TokenDelimiter+cm, clm.String())
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue