Source File
js_ast.go
Belonging Package
github.com/evanw/esbuild/internal/js_ast
package js_ast
import (
)
const (
LLowest L = iota
LComma
LSpread
LYield
LAssign
LConditional
LNullishCoalescing
LLogicalOr
LLogicalAnd
LBitwiseOr
LBitwiseXor
LBitwiseAnd
LEquals
LCompare
LShift
LAdd
LMultiply
LExponentiation
LPrefix
LPostfix
LNew
LCall
LMember
)
type OpCode int
func ( OpCode) () bool {
return < UnOpPostDec
}
func ( OpCode) () AssignTarget {
if >= UnOpPreDec && <= UnOpPostInc {
return AssignTargetUpdate
}
return AssignTargetNone
}
func ( OpCode) () bool {
return >= BinOpAdd && < BinOpComma && != BinOpPow
}
func ( OpCode) () bool {
return >= BinOpAssign || == BinOpPow
}
func ( OpCode) () AssignTarget {
if == BinOpAssign {
return AssignTargetReplace
}
if > BinOpAssign {
return AssignTargetUpdate
}
return AssignTargetNone
}
func ( OpCode) () bool {
switch {
case BinOpLogicalOr, BinOpLogicalOrAssign,
BinOpLogicalAnd, BinOpLogicalAndAssign,
BinOpNullishCoalescing, BinOpNullishCoalescingAssign:
return true
}
return false
}
type AssignTarget uint8
const (
AssignTargetNone AssignTarget = iota
AssignTargetReplace // "a = b"
AssignTargetUpdate // "a += b"
)
BinOpAssign
BinOpAddAssign
BinOpSubAssign
BinOpMulAssign
BinOpDivAssign
BinOpRemAssign
BinOpPowAssign
BinOpShlAssign
BinOpShrAssign
BinOpUShrAssign
BinOpBitwiseOrAssign
BinOpBitwiseAndAssign
BinOpBitwiseXorAssign
BinOpNullishCoalescingAssign
BinOpLogicalOrAssign
BinOpLogicalAndAssign
)
type opTableEntry struct {
Text string
Level L
IsKeyword bool
}
{"+", LAdd, false},
{"-", LAdd, false},
{"*", LMultiply, false},
{"/", LMultiply, false},
{"%", LMultiply, false},
{"**", LExponentiation, false}, // Right-associative
{"<", LCompare, false},
{"<=", LCompare, false},
{">", LCompare, false},
{">=", LCompare, false},
{"in", LCompare, true},
{"instanceof", LCompare, true},
{"<<", LShift, false},
{">>", LShift, false},
{">>>", LShift, false},
{"==", LEquals, false},
{"!=", LEquals, false},
{"===", LEquals, false},
{"!==", LEquals, false},
{"??", LNullishCoalescing, false},
{"||", LLogicalOr, false},
{"&&", LLogicalAnd, false},
{"|", LBitwiseOr, false},
{"&", LBitwiseAnd, false},
{"^", LBitwiseXor, false},
{"=", LAssign, false},
{"+=", LAssign, false},
{"-=", LAssign, false},
{"*=", LAssign, false},
{"/=", LAssign, false},
{"%=", LAssign, false},
{"**=", LAssign, false},
{"<<=", LAssign, false},
{">>=", LAssign, false},
{">>>=", LAssign, false},
{"|=", LAssign, false},
{"&=", LAssign, false},
{"^=", LAssign, false},
{"??=", LAssign, false},
{"||=", LAssign, false},
{"&&=", LAssign, false},
}
type LocRef struct {
Loc logger.Loc
Ref Ref
}
type Comment struct {
Loc logger.Loc
Text string
}
type Span struct {
Text string
Range logger.Range
}
type PropertyKind int
const (
PropertyNormal PropertyKind = iota
PropertyGet
PropertySet
PropertySpread
)
type Property struct {
TSDecorators []Expr
Key Expr
Initializer *Expr
Kind PropertyKind
IsComputed bool
IsMethod bool
IsStatic bool
WasShorthand bool
}
type PropertyBinding struct {
IsComputed bool
IsSpread bool
Key Expr
Value Binding
DefaultValue *Expr
}
type Arg struct {
TSDecorators []Expr
Binding Binding
Default *Expr
IsTypeScriptCtorField bool
}
type Fn struct {
Name *LocRef
OpenParenLoc logger.Loc
Args []Arg
Body FnBody
ArgumentsRef Ref
IsAsync bool
IsGenerator bool
HasRestArg bool
HasIfScope bool
IsUniqueFormalParameters bool
}
type FnBody struct {
Loc logger.Loc
Stmts []Stmt
}
type Class struct {
ClassKeyword logger.Range
TSDecorators []Expr
Name *LocRef
Extends *Expr
BodyLoc logger.Loc
Properties []Property
}
type ArrayBinding struct {
Binding Binding
DefaultValue *Expr
}
type Binding struct {
Loc logger.Loc
Data B
}
type B interface{ isBinding() }
type BMissing struct{}
type BIdentifier struct{ Ref Ref }
type BArray struct {
Items []ArrayBinding
HasSpread bool
IsSingleLine bool
}
type BObject struct {
Properties []PropertyBinding
IsSingleLine bool
}
func (*BMissing) () {}
func (*BIdentifier) () {}
func (*BArray) () {}
func (*BObject) () {}
type Expr struct {
Loc logger.Loc
Data E
}
type E interface{ isExpr() }
type EArray struct {
Items []Expr
CommaAfterSpread logger.Loc
IsSingleLine bool
IsParenthesized bool
}
type EUnary struct {
Op OpCode
Value Expr
}
type EBinary struct {
Left Expr
Right Expr
Op OpCode
}
type EBoolean struct{ Value bool }
type ESuper struct{}
type ENull struct{}
type EUndefined struct{}
type EThis struct{}
type ENew struct {
Target Expr
Args []Expr
CanBeUnwrappedIfUnused bool
}
type ENewTarget struct{}
type EImportMeta struct{}
type OptionalChain uint8
OptionalChainContinue
)
type ECall struct {
Target Expr
Args []Expr
OptionalChain OptionalChain
IsDirectEval bool
CanBeUnwrappedIfUnused bool
}
func ( *ECall) ( *ECall) bool {
return .OptionalChain == .OptionalChain &&
.IsDirectEval == .IsDirectEval &&
.CanBeUnwrappedIfUnused == .CanBeUnwrappedIfUnused
}
type EDot struct {
Target Expr
Name string
NameLoc logger.Loc
OptionalChain OptionalChain
CallCanBeUnwrappedIfUnused bool
}
func ( *EDot) ( *EDot) bool {
return .OptionalChain == .OptionalChain &&
.CanBeRemovedIfUnused == .CanBeRemovedIfUnused &&
.CallCanBeUnwrappedIfUnused == .CallCanBeUnwrappedIfUnused
}
type EIndex struct {
Target Expr
Index Expr
OptionalChain OptionalChain
}
func ( *EIndex) ( *EIndex) bool {
return .OptionalChain == .OptionalChain
}
type EArrow struct {
Args []Arg
Body FnBody
IsAsync bool
HasRestArg bool
PreferExpr bool // Use shorthand if true and "Body" is a single return statement
}
type EFunction struct{ Fn Fn }
type EClass struct{ Class Class }
type EIdentifier struct {
Ref Ref
type EImportIdentifier struct {
Ref Ref
type EPrivateIdentifier struct {
Ref Ref
}
type EJSXElement struct {
Tag *Expr
Properties []Property
Children []Expr
}
type EMissing struct{}
type ENumber struct{ Value float64 }
type EBigInt struct{ Value string }
type EObject struct {
Properties []Property
CommaAfterSpread logger.Loc
IsSingleLine bool
IsParenthesized bool
}
type ESpread struct{ Value Expr }
type EString struct {
Value []uint16
LegacyOctalLoc logger.Loc
PreferTemplate bool
}
type TemplatePart struct {
Value Expr
TailLoc logger.Loc
Tail []uint16
TailRaw string // This is only filled out for tagged template literals
}
type ETemplate struct {
Tag *Expr
Head []uint16
HeadRaw string // This is only filled out for tagged template literals
Parts []TemplatePart
LegacyOctalLoc logger.Loc
}
type ERegExp struct{ Value string }
type EAwait struct {
Value Expr
}
type EYield struct {
Value *Expr
IsStar bool
}
type EIf struct {
Test Expr
Yes Expr
No Expr
}
type ERequire struct {
ImportRecordIndex uint32
}
type ERequireResolve struct {
ImportRecordIndex uint32
}
type EImport struct {
Expr Expr
ImportRecordIndex ast.Index32
LeadingInteriorComments []Comment
}
func (*EArray) () {}
func (*EUnary) () {}
func (*EBinary) () {}
func (*EBoolean) () {}
func (*ESuper) () {}
func (*ENull) () {}
func (*EUndefined) () {}
func (*EThis) () {}
func (*ENew) () {}
func (*ENewTarget) () {}
func (*EImportMeta) () {}
func (*ECall) () {}
func (*EDot) () {}
func (*EIndex) () {}
func (*EArrow) () {}
func (*EFunction) () {}
func (*EClass) () {}
func (*EIdentifier) () {}
func (*EImportIdentifier) () {}
func (*EPrivateIdentifier) () {}
func (*EJSXElement) () {}
func (*EMissing) () {}
func (*ENumber) () {}
func (*EBigInt) () {}
func (*EObject) () {}
func (*ESpread) () {}
func (*EString) () {}
func (*ETemplate) () {}
func (*ERegExp) () {}
func (*EAwait) () {}
func (*EYield) () {}
func (*EIf) () {}
func (*ERequire) () {}
func (*ERequireResolve) () {}
func (*EImport) () {}
func ( Expr) bool {
switch e := .Data.(type) {
case *EDot:
return .OptionalChain != OptionalChainNone
case *EIndex:
return .OptionalChain != OptionalChainNone
case *ECall:
return .OptionalChain != OptionalChainNone
}
return false
}
func ( Expr, Expr) Expr {
return Expr{Loc: .Loc, Data: &EBinary{Op: BinOpAssign, Left: , Right: }}
}
func ( Expr, Expr) Stmt {
return Stmt{Loc: .Loc, Data: &SExpr{Value: Assign(, )}}
}
func ( Expr) (Expr, bool) {
switch e := .Data.(type) {
case *ENull, *EUndefined:
return Expr{Loc: .Loc, Data: &EBoolean{Value: true}}, true
case *EBoolean:
return Expr{Loc: .Loc, Data: &EBoolean{Value: !.Value}}, true
case *ENumber:
return Expr{Loc: .Loc, Data: &EBoolean{Value: .Value == 0 || math.IsNaN(.Value)}}, true
case *EBigInt:
return Expr{Loc: .Loc, Data: &EBoolean{Value: .Value == "0"}}, true
case *EString:
return Expr{Loc: .Loc, Data: &EBoolean{Value: len(.Value) == 0}}, true
case *EFunction, *EArrow, *ERegExp:
return Expr{Loc: .Loc, Data: &EBoolean{Value: false}}, true
switch .Op {
.Op = BinOpLooseNe
return , true
.Op = BinOpLooseEq
return , true
.Op = BinOpStrictNe
return , true
.Op = BinOpStrictEq
return , true
.Right = Not(.Right)
return , true
}
}
return Expr{}, false
}
func ( Expr) bool {
switch e := .Data.(type) {
case *EBoolean:
return true
case *EIf:
return (.Yes) && (.No)
case *EUnary:
return .Op == UnOpNot || .Op == UnOpDelete
case *EBinary:
switch .Op {
case BinOpStrictEq, BinOpStrictNe, BinOpLooseEq, BinOpLooseNe,
BinOpLt, BinOpGt, BinOpLe, BinOpGe,
BinOpInstanceof, BinOpIn:
return true
case BinOpLogicalOr, BinOpLogicalAnd:
return (.Left) && (.Right)
case BinOpNullishCoalescing:
return (.Left)
}
}
return false
}
func ( Expr) bool {
switch e := .Data.(type) {
case *ENumber:
return true
case *EIf:
return (.Yes) && (.No)
case *EUnary:
switch .Op {
case UnOpPos, UnOpNeg, UnOpCpl, UnOpPreDec, UnOpPreInc, UnOpPostDec, UnOpPostInc:
return true
}
case *EBinary:
switch .Op {
case BinOpAdd:
return (.Left) && (.Right)
case BinOpSub, BinOpMul, BinOpDiv, BinOpRem,
BinOpBitwiseAnd, BinOpBitwiseOr, BinOpBitwiseXor,
BinOpShl, BinOpShr, BinOpUShr:
return true
case BinOpSubAssign, BinOpMulAssign, BinOpDivAssign, BinOpRemAssign,
BinOpBitwiseAndAssign, BinOpBitwiseOrAssign, BinOpBitwiseXorAssign,
BinOpShlAssign, BinOpShrAssign, BinOpUShrAssign:
case BinOpAssign, BinOpComma:
return (.Right)
}
}
return false
}
func ( Expr) bool {
switch e := .Data.(type) {
case *EString:
return true
case *ETemplate:
return .Tag == nil
case *EIf:
return (.Yes) && (.No)
case *EUnary:
return .Op == UnOpTypeof
case *EBinary:
switch .Op {
case BinOpAdd:
return (.Left) || (.Right)
case BinOpAssign, BinOpAddAssign, BinOpComma:
return IsNumericValue(.Right)
}
}
return false
}
return Expr{Loc: .Loc, Data: &EBinary{Op: , Left: , Right: }}
}
func ( Expr, Expr) Expr {
return Expr{Loc: .Loc, Data: &EBinary{Op: BinOpComma, Left: , Right: }}
}
func ( []Expr) Expr {
:= [0]
for , := range [1:] {
= JoinWithComma(, )
}
return
}
type ExprOrStmt struct {
Expr *Expr
Stmt *Stmt
}
type Stmt struct {
Loc logger.Loc
Data S
}
type STypeScript struct{}
type SComment struct {
Text string
}
type SDebugger struct{}
type SDirective struct {
Value []uint16
LegacyOctalLoc logger.Loc
}
type SExportClause struct {
Items []ClauseItem
IsSingleLine bool
}
type SExportFrom struct {
Items []ClauseItem
NamespaceRef Ref
ImportRecordIndex uint32
IsSingleLine bool
}
type SExportDefault struct {
DefaultName LocRef
Value ExprOrStmt // May be a SFunction or SClass
}
type ExportStarAlias struct {
Loc logger.Loc
OriginalName string
}
type SExportStar struct {
NamespaceRef Ref
Alias *ExportStarAlias
ImportRecordIndex uint32
}
type SExportEquals struct {
Value Expr
}
DoesNotAffectTreeShaking bool
}
type EnumValue struct {
Loc logger.Loc
Ref Ref
Name []uint16
Value *Expr
}
type SEnum struct {
Name LocRef
Arg Ref
Values []EnumValue
IsExport bool
}
type SNamespace struct {
Name LocRef
Arg Ref
Stmts []Stmt
IsExport bool
}
type SFunction struct {
Fn Fn
IsExport bool
}
type SClass struct {
Class Class
IsExport bool
}
type SLabel struct {
Name LocRef
Stmt Stmt
}
type SIf struct {
Test Expr
Yes Stmt
No *Stmt
}
type SFor struct {
Init *Stmt // May be a SConst, SLet, SVar, or SExpr
Test *Expr
Update *Expr
Body Stmt
}
type SForIn struct {
Init Stmt // May be a SConst, SLet, SVar, or SExpr
Value Expr
Body Stmt
}
type SForOf struct {
IsAwait bool
Init Stmt // May be a SConst, SLet, SVar, or SExpr
Value Expr
Body Stmt
}
type SDoWhile struct {
Body Stmt
Test Expr
}
type SWhile struct {
Test Expr
Body Stmt
}
type SWith struct {
Value Expr
BodyLoc logger.Loc
Body Stmt
}
type Catch struct {
Loc logger.Loc
Binding *Binding
Body []Stmt
}
type Finally struct {
Loc logger.Loc
Stmts []Stmt
}
type STry struct {
BodyLoc logger.Loc
Body []Stmt
Catch *Catch
Finally *Finally
}
type Case struct {
Value *Expr
Body []Stmt
}
type SSwitch struct {
Test Expr
BodyLoc logger.Loc
Cases []Case
}
NamespaceRef Ref
DefaultName *LocRef
Items *[]ClauseItem
StarNameLoc *logger.Loc
ImportRecordIndex uint32
IsSingleLine bool
}
type SReturn struct {
Value *Expr
}
type SThrow struct {
Value Expr
}
type LocalKind uint8
const (
LocalVar LocalKind = iota
LocalLet
LocalConst
)
type SLocal struct {
Decls []Decl
Kind LocalKind
IsExport bool
WasTSImportEquals bool
}
type SBreak struct {
Label *LocRef
}
type SContinue struct {
Label *LocRef
}
func (*SBlock) () {}
func (*SComment) () {}
func (*SDebugger) () {}
func (*SDirective) () {}
func (*SEmpty) () {}
func (*STypeScript) () {}
func (*SExportClause) () {}
func (*SExportFrom) () {}
func (*SExportDefault) () {}
func (*SExportStar) () {}
func (*SExportEquals) () {}
func (*SLazyExport) () {}
func (*SExpr) () {}
func (*SEnum) () {}
func (*SNamespace) () {}
func (*SFunction) () {}
func (*SClass) () {}
func (*SLabel) () {}
func (*SIf) () {}
func (*SFor) () {}
func (*SForIn) () {}
func (*SForOf) () {}
func (*SDoWhile) () {}
func (*SWhile) () {}
func (*SWith) () {}
func (*STry) () {}
func (*SSwitch) () {}
func (*SImport) () {}
func (*SReturn) () {}
func (*SThrow) () {}
func (*SLocal) () {}
func (*SBreak) () {}
func (*SContinue) () {}
func ( Stmt) bool {
if , := .Data.(*SExpr); {
if , := .Value.Data.(*ECall); {
if , := .Target.Data.(*ESuper); {
return true
}
}
}
return false
}
type ClauseItem struct {
Alias string
AliasLoc logger.Loc
Name LocRef
OriginalName string
}
type Decl struct {
Binding Binding
Value *Expr
}
type SymbolKind uint8
SymbolOther
)
func ( SymbolKind) () bool {
return >= SymbolPrivateField && <= SymbolPrivateStaticGetSetPair
}
func ( SymbolKind) () compat.JSFeature {
switch {
case SymbolPrivateField:
return compat.ClassPrivateField
case SymbolPrivateMethod:
return compat.ClassPrivateMethod
case SymbolPrivateGet, SymbolPrivateSet, SymbolPrivateGetSetPair:
return compat.ClassPrivateAccessor
case SymbolPrivateStaticField:
return compat.ClassPrivateStaticField
case SymbolPrivateStaticMethod:
return compat.ClassPrivateStaticMethod
case SymbolPrivateStaticGet, SymbolPrivateStaticSet, SymbolPrivateStaticGetSetPair:
return compat.ClassPrivateStaticAccessor
default:
return 0
}
}
func ( SymbolKind) () bool {
return == SymbolHoisted || == SymbolHoistedFunction
}
func ( SymbolKind) () bool {
return .IsHoisted() || == SymbolGeneratorOrAsyncFunction
}
func ( SymbolKind) () bool {
return == SymbolHoistedFunction || == SymbolGeneratorOrAsyncFunction
}
var InvalidRef Ref = Ref{^uint32(0), ^uint32(0)}
type Ref struct {
OuterIndex uint32
InnerIndex uint32
}
type ImportItemStatus uint8
const (
ImportItemNone ImportItemStatus = iota
ImportItemStatus ImportItemStatus
}
type SlotNamespace uint8
const (
SlotDefault SlotNamespace = iota
SlotLabel
SlotPrivateName
SlotMustNotBeRenamed
)
func ( *Symbol) () SlotNamespace {
if .Kind == SymbolUnbound || .MustNotBeRenamed {
return SlotMustNotBeRenamed
}
if .Kind.IsPrivate() {
return SlotPrivateName
}
if .Kind == SymbolLabel {
return SlotLabel
}
return SlotDefault
}
type SlotCounts [3]uint32
func ( *SlotCounts) ( SlotCounts) {
for := range * {
:= &(*)[]
:= []
if * < {
* =
}
}
}
type NamespaceAlias struct {
NamespaceRef Ref
Alias string
}
type ScopeKind int
const (
ScopeBlock ScopeKind = iota
ScopeWith
ScopeLabel
ScopeClassName
ScopeClassBody
ScopeEntry // This is a module, TypeScript enum, or TypeScript namespace
ScopeFunctionArgs
ScopeFunctionBody
)
func ( ScopeKind) () bool {
return >= ScopeEntry
}
type ScopeMember struct {
Ref Ref
Loc logger.Loc
}
type Scope struct {
Kind ScopeKind
Parent *Scope
Children []*Scope
Members map[string]ScopeMember
Generated []Ref
ForbidArguments bool
StrictMode StrictModeKind
}
type StrictModeKind uint8
const (
SloppyMode StrictModeKind = iota
ExplicitStrictMode
ImplicitStrictModeImport
ImplicitStrictModeExport
ImplicitStrictModeTopLevelAwait
ImplicitStrictModeClass
)
func ( *Scope) ( StrictModeKind) {
if .StrictMode == SloppyMode {
.StrictMode =
for , := range .Children {
.()
}
}
}
Outer [][]Symbol
}
func ( int) SymbolMap {
return SymbolMap{make([][]Symbol, )}
}
func ( SymbolMap) ( Ref) *Symbol {
return &.Outer[.OuterIndex][.InnerIndex]
}
type AST struct {
ApproximateLineCount int32
NestedScopeSlotCounts SlotCounts
HasLazyExport bool
ImportKeyword logger.Range // Does not include TypeScript-specific syntax or "import()"
ExportKeyword logger.Range // Does not include TypeScript-specific syntax
TopLevelAwaitKeyword logger.Range
Hashbang string
Directive string
URLForCSS string
Parts []Part
Symbols []Symbol
ModuleScope *Scope
CharFreq *CharFreq
ExportsRef Ref
ModuleRef Ref
WrapperRef Ref
for , := 0, len(); < ; ++ {
:= []
switch {
case >= 'a' && <= 'z':
(*)[-'a'] +=
case >= 'A' && <= 'Z':
(*)[-('A'-26)] +=
case >= '0' && <= '9':
(*)[+(52-'0')] +=
case == '_':
(*)[62] +=
case == '$':
(*)[63] +=
}
}
}
func ( *CharFreq) ( *CharFreq) {
for := 0; < 64; ++ {
(*)[] += (*)[]
}
}
type NameMinifier struct {
head string
tail string
}
var DefaultNameMinifier = NameMinifier{
head: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$",
tail: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$",
}
type charAndCount struct {
index byte
count int32
char string
}
type charAndCountArray []charAndCount
func ( charAndCountArray) () int { return len() }
func ( charAndCountArray) ( int, int) { [], [] = [], [] }
func ( charAndCountArray) ( int, int) bool {
:= []
:= []
return .count > .count || (.count == .count && .index < .index)
}
:= make(charAndCountArray, 64)
for := 0; < len(DefaultNameMinifier.tail); ++ {
[] = charAndCount{
char: DefaultNameMinifier.tail[ : +1],
index: byte(),
count: [],
}
}
sort.Sort()
:= NameMinifier{}
for , := range {
if .char < "0" || .char > "9" {
.head += .char
}
.tail += .char
}
return
}
func ( *NameMinifier) ( int) string {
:= % 54
:= .head[ : +1]
= / 54
for > 0 {
--
:= % 64
+= .tail[ : +1]
= / 64
}
return
}
func ( *AST) () bool {
return .UsesCommonJSExports() || .HasTopLevelReturn
}
func ( *AST) () bool {
return .UsesExportsRef || .UsesModuleRef
}
func ( *AST) () bool {
return .ImportKeyword.Len > 0 || .ExportKeyword.Len > 0 || .TopLevelAwaitKeyword.Len > 0
}
IsExported bool
}
type NamedExport struct {
Ref Ref
AliasLoc logger.Loc
}
SymbolUses map[Ref]SymbolUse
ForceTreeShaking bool
}
type DeclaredSymbol struct {
Ref Ref
IsTopLevel bool
}
type SymbolUse struct {
CountEstimate uint32
IsAssigned bool
}
func ( SymbolMap, Ref, Ref) Ref {
if == {
return
}
:= .Get()
if .Link != InvalidRef {
.Link = (, .Link, )
return .Link
}
:= .Get()
if .Link != InvalidRef {
.Link = (, , .Link)
return .Link
}
.Link =
.UseCountEstimate += .UseCountEstimate
if .MustNotBeRenamed {
.OriginalName = .OriginalName
.MustNotBeRenamed = true
}
return
}
, , := logger.PlatformIndependentPathDirBaseExt()
if == "index" {
, , := logger.PlatformIndependentPathDirBaseExt()
if != "" {
=
}
}
return EnsureValidIdentifier()
}
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |