Use dot notation for enum variants

This commit is contained in:
pavel 2026-08-27 18:05:28 +02:00
commit 117d188194
13 changed files with 162 additions and 154 deletions

View file

@ -109,9 +109,9 @@ enum PaymentResult {
fun describe(result: PaymentResult): String {
return match (result) {
PaymentResult::Accepted(id) -> id
PaymentResult::Rejected(reason) -> reason
PaymentResult::Pending -> "pending"
PaymentResult.Accepted(id) -> id
PaymentResult.Rejected(reason) -> reason
PaymentResult.Pending -> "pending"
}
}
```

View file

@ -646,7 +646,7 @@ func indexSymbols(text string, program *lang.Program) []symbol {
}
symbols = append(symbols, symbol{Name: decl.Name, Kind: symbolKindEnum, Detail: "enum " + decl.Name, Range: r})
for _, variant := range decl.Variants {
symbols = append(symbols, symbol{Name: variant.Name, Kind: symbolKindVariable, Detail: decl.Name + "::" + variant.Name, Range: r, Targets: []string{decl.Name}})
symbols = append(symbols, symbol{Name: variant.Name, Kind: symbolKindVariable, Detail: decl.Name + "." + variant.Name, Range: r, Targets: []string{decl.Name}})
}
}

View file

@ -8,13 +8,13 @@ enum PaymentResult {
fun describe(result: PaymentResult): String {
return match (result) {
PaymentResult::Accepted(id) -> "accepted " + id
PaymentResult::Rejected(reason) -> "rejected " + reason
PaymentResult::Pending -> "pending"
PaymentResult.Accepted(id) -> "accepted " + id
PaymentResult.Rejected(reason) -> "rejected " + reason
PaymentResult.Pending -> "pending"
}
}
fun main() {
val result = PaymentResult::Accepted("payment-1")
val result = PaymentResult.Accepted("payment-1")
println(describe(result))
}

View file

@ -29,12 +29,12 @@ data class AccountResponse(
)
fun main() {
val entity = AccountEntity("account-1", AddressEntity("Berlin"), listOf("active"), EntityState::Active)
val entity = AccountEntity("account-1", AddressEntity("Berlin"), listOf("active"), EntityState.Active)
val response = entity.mapTo<AccountResponse>()
println(response.address.city)
match (response.state) {
ResponseState::Active -> { println("active") }
ResponseState::Failed(reason) -> { println(reason) }
ResponseState::Pending -> { println("pending") }
ResponseState.Active -> { println("active") }
ResponseState.Failed(reason) -> { println(reason) }
ResponseState.Pending -> { println("pending") }
}
}

View file

@ -12,13 +12,13 @@ enum PaymentResult { Accepted(String), Rejected(String), Pending }
fun describe(result: PaymentResult): String {
var description = ""
match (result) {
PaymentResult::Accepted(id) -> { description = id }
PaymentResult::Rejected(reason) -> { description = reason }
PaymentResult::Pending -> { description = "pending" }
PaymentResult.Accepted(id) -> { description = id }
PaymentResult.Rejected(reason) -> { description = reason }
PaymentResult.Pending -> { description = "pending" }
}
return description
}
fun main() { println(describe(PaymentResult::Accepted("p1"))) }
fun main() { println(describe(PaymentResult.Accepted("p1"))) }
`)
if err != nil {
t.Fatal(err)
@ -37,7 +37,7 @@ fun main() { println(describe(PaymentResult::Accepted("p1"))) }
func TestRejectNonExhaustiveEnumMatch(t *testing.T) {
prog, err := Parse(`package demo
enum Result { Ok, Error(String) }
fun use(result: Result) { match (result) { Result::Ok -> { println("ok") } } }`)
fun use(result: Result) { match (result) { Result.Ok -> { println("ok") } } }`)
if err != nil {
t.Fatal(err)
}
@ -50,7 +50,7 @@ fun use(result: Result) { match (result) { Result::Ok -> { println("ok") } } }`)
func TestRejectWrongVariantPayloadCount(t *testing.T) {
prog, err := Parse(`package demo
enum Outcome { Ok(String) }
fun main() { val result = Outcome::Ok() }`)
fun main() { val result = Outcome.Ok() }`)
if err != nil {
t.Fatal(err)
}
@ -60,10 +60,17 @@ fun main() { val result = Outcome::Ok() }`)
}
}
func TestRejectDoubleColonEnumSyntax(t *testing.T) {
_, err := Parse(`package demo enum State { Ready } fun main() { println(State::Ready) }`)
if err == nil {
t.Fatal("deprecated double-colon enum syntax parsed")
}
}
func TestPayloadlessEnumUsesExactVariantStrings(t *testing.T) {
prog, err := Parse(`package demo
enum Status { PendingReservation, Initiated }
fun main() { println(Status::PendingReservation) }`)
fun main() { println(Status.PendingReservation) }`)
if err != nil {
t.Fatal(err)
}
@ -83,8 +90,8 @@ func TestGenerateExhaustiveMatchExpression(t *testing.T) {
enum AccountType { BASIC, SAVINGS }
fun interestRate(accountType: AccountType): Double {
return match (accountType) {
AccountType::BASIC -> 0.0
AccountType::SAVINGS -> 0.02
AccountType.BASIC -> 0.0
AccountType.SAVINGS -> 0.02
}
}`)
if err != nil {
@ -106,8 +113,8 @@ func TestGeneratePayloadMatchExpression(t *testing.T) {
enum Outcome { Success(String), Failure(String) }
fun message(outcome: Outcome): String {
return match (outcome) {
Outcome::Success(value) -> value
Outcome::Failure(reason) -> reason
Outcome.Success(value) -> value
Outcome.Failure(reason) -> reason
}
}`)
if err != nil {
@ -129,8 +136,8 @@ func TestRejectInvalidMatchExpression(t *testing.T) {
source string
want string
}{
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State::On -> 1 } }`, "missing Off"},
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State::On -> 1 State::Off -> "off" } }`, "has type String, expected Int"},
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State.On -> 1 } }`, "missing Off"},
{`package demo enum State { On, Off } fun value(state: State): Int { return match (state) { State.On -> 1 State.Off -> "off" } }`, "has type String, expected Int"},
} {
prog, err := Parse(test.source)
if err != nil {

View file

@ -1051,18 +1051,18 @@ func (g *goGenerator) stmt(stmt Stmt, tail []Stmt) error {
seen := map[string]bool{}
for _, c := range s.Cases {
if c.EnumName != enumName {
return fmt.Errorf("match case %s::%s does not match enum %s", c.EnumName, c.VariantName, enumName)
return fmt.Errorf("match case %s.%s does not match enum %s", c.EnumName, c.VariantName, enumName)
}
if seen[c.VariantName] {
return fmt.Errorf("duplicate match case %s::%s", enumName, c.VariantName)
return fmt.Errorf("duplicate match case %s.%s", enumName, c.VariantName)
}
seen[c.VariantName] = true
variant := enumVariant(decl, c.VariantName)
if variant == nil {
return fmt.Errorf("unknown variant %s::%s", enumName, c.VariantName)
return fmt.Errorf("unknown variant %s.%s", enumName, c.VariantName)
}
if len(c.Bindings) != len(variant.PayloadTypes) {
return fmt.Errorf("match case %s::%s expects %d bindings", enumName, c.VariantName, len(variant.PayloadTypes))
return fmt.Errorf("match case %s.%s expects %d bindings", enumName, c.VariantName, len(variant.PayloadTypes))
}
}
for _, variant := range decl.Variants {
@ -1250,6 +1250,16 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
}
return fmt.Sprintf("%s %s %s", left, e.Op, right), nil
case CallExpr:
if selector, ok := e.Callee.(SelectorExpr); ok {
if receiver, ok := selector.Receiver.(IdentExpr); ok {
if receiver.Name == "Result" {
return g.expr(EnumVariantExpr{EnumName: receiver.Name, VariantName: selector.Name, Values: e.Args}, expectedType)
}
if _, ok := g.enums[receiver.Name]; ok {
return g.expr(EnumVariantExpr{EnumName: receiver.Name, VariantName: selector.Name, Values: e.Args}, expectedType)
}
}
}
if ident, ok := e.Callee.(IdentExpr); ok && coroutineBuiltins[ident.Name] {
switch ident.Name {
case "runBlocking":
@ -1607,6 +1617,18 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
}
return call, nil
case SelectorExpr:
if receiver, ok := e.Receiver.(IdentExpr); ok {
if decl, ok := g.enums[receiver.Name]; ok {
variant := enumVariant(decl, e.Name)
if variant == nil {
return "", fmt.Errorf("unknown variant %s.%s", receiver.Name, e.Name)
}
if len(variant.PayloadTypes) != 0 {
return "", fmt.Errorf("variant %s.%s requires %d values", receiver.Name, e.Name, len(variant.PayloadTypes))
}
return g.expr(EnumVariantExpr{EnumName: receiver.Name, VariantName: e.Name}, expectedType)
}
}
if receiverType := g.exprType(e.Receiver); strings.HasSuffix(receiverType, "?") {
return "", fmt.Errorf("nullable receiver %s requires ?. or !! before .%s", receiverType, e.Name)
}
@ -1685,11 +1707,11 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
if e.EnumName == "Result" {
base, args, ok := parseGenericType(expectedType)
if !ok || base != "Result" || len(args) != 2 {
return "", fmt.Errorf("Result::%s requires an expected Result<T, Error> type", e.VariantName)
return "", fmt.Errorf("Result.%s requires an expected Result<T, Error> type", e.VariantName)
}
if e.VariantName == "Ok" {
if len(e.Values) != 1 {
return "", fmt.Errorf("Result::Ok expects one value")
return "", fmt.Errorf("Result.Ok expects one value")
}
value, err := g.expr(e.Values[0], args[0])
if err != nil {
@ -1699,7 +1721,7 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
}
if e.VariantName == "Err" {
if len(e.Values) != 1 {
return "", fmt.Errorf("Result::Err expects one error")
return "", fmt.Errorf("Result.Err expects one error")
}
value, err := g.expr(e.Values[0], "Error")
if err != nil {
@ -1721,10 +1743,10 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
}
}
if variant == nil {
return "", fmt.Errorf("unknown variant %s::%s", e.EnumName, e.VariantName)
return "", fmt.Errorf("unknown variant %s.%s", e.EnumName, e.VariantName)
}
if len(e.Values) != len(variant.PayloadTypes) {
return "", fmt.Errorf("variant %s::%s expects %d values", e.EnumName, e.VariantName, len(variant.PayloadTypes))
return "", fmt.Errorf("variant %s.%s expects %d values", e.EnumName, e.VariantName, len(variant.PayloadTypes))
}
if enumIsString(decl) {
return e.EnumName + e.VariantName, nil
@ -1757,18 +1779,18 @@ func (g *goGenerator) valueMatch(match MatchExpr, expectedType string) (string,
seen := map[string]bool{}
for _, c := range match.Cases {
if c.EnumName != enumName {
return "", fmt.Errorf("match case %s::%s does not match enum %s", c.EnumName, c.VariantName, enumName)
return "", fmt.Errorf("match case %s.%s does not match enum %s", c.EnumName, c.VariantName, enumName)
}
if seen[c.VariantName] {
return "", fmt.Errorf("duplicate match case %s::%s", enumName, c.VariantName)
return "", fmt.Errorf("duplicate match case %s.%s", enumName, c.VariantName)
}
seen[c.VariantName] = true
variant := enumVariant(decl, c.VariantName)
if variant == nil {
return "", fmt.Errorf("unknown variant %s::%s", enumName, c.VariantName)
return "", fmt.Errorf("unknown variant %s.%s", enumName, c.VariantName)
}
if len(c.Bindings) != len(variant.PayloadTypes) {
return "", fmt.Errorf("match case %s::%s expects %d bindings", enumName, c.VariantName, len(variant.PayloadTypes))
return "", fmt.Errorf("match case %s.%s expects %d bindings", enumName, c.VariantName, len(variant.PayloadTypes))
}
}
for _, variant := range decl.Variants {
@ -1804,7 +1826,7 @@ func (g *goGenerator) valueMatch(match MatchExpr, expectedType string) (string,
armType := g.exprType(c.Value)
g.popScope()
if armType != "" && armType != resultType {
return "", fmt.Errorf("match expression arm %s::%s has type %s, expected %s", enumName, c.VariantName, armType, resultType)
return "", fmt.Errorf("match expression arm %s.%s has type %s, expected %s", enumName, c.VariantName, armType, resultType)
}
}
value, err := g.expr(match.Value, enumName)
@ -3110,6 +3132,13 @@ func (g *goGenerator) exprType(expr Expr) string {
case BoolExpr:
return "Boolean"
case CallExpr:
if selector, ok := e.Callee.(SelectorExpr); ok {
if receiver, ok := selector.Receiver.(IdentExpr); ok {
if _, ok := g.enums[receiver.Name]; ok {
return receiver.Name
}
}
}
if ident, ok := e.Callee.(IdentExpr); ok && ident.Name == "keys" && len(e.Args) == 1 {
if _, args, ok := parseGenericType(g.exprType(e.Args[0])); ok && len(args) == 2 {
return "List<" + args[0] + ">"
@ -3173,6 +3202,11 @@ func (g *goGenerator) exprType(expr Expr) string {
}
}
case SelectorExpr:
if receiver, ok := e.Receiver.(IdentExpr); ok {
if _, ok := g.enums[receiver.Name]; ok {
return receiver.Name
}
}
if class, ok := g.classForType(g.exprType(e.Receiver)); ok {
for _, field := range class.Fields {
if field.Name == e.Name {

View file

@ -93,9 +93,6 @@ func (l *lexer) next() (token, error) {
case '.':
return token{kind: tokenDot, lexeme: ".", pos: start}, nil
case ':':
if l.match(':') {
return token{kind: tokenDoubleColon, lexeme: "::", pos: start}, nil
}
return token{kind: tokenColon, lexeme: ":", pos: start}, nil
case ';':
return token{kind: tokenSemicolon, lexeme: ";", pos: start}, nil

View file

@ -97,7 +97,7 @@ func (g *goGenerator) validateMapping(source, target, path string, seen map[stri
}
for _, sourceVariant := range sourceEnum.Variants {
targetVariant := enumVariant(targetEnum, sourceVariant.Name)
variantPath := path + "::" + sourceVariant.Name
variantPath := path + "." + sourceVariant.Name
if targetVariant == nil {
return fmt.Errorf("cannot map %s: target enum %s has no compatible variant", variantPath, targetEnum.Name)
}
@ -158,7 +158,7 @@ func (g *goGenerator) emitMapping(pair mappingPair) error {
g.indentLevel++
fields := make([]string, 0, len(sourceVariant.PayloadTypes))
for i := range sourceVariant.PayloadTypes {
expr, err := g.mappingExpr(fmt.Sprintf("value.Value%d", i), sourceVariant.PayloadTypes[i], targetVariant.PayloadTypes[i], sourceEnum.Name+"::"+sourceVariant.Name)
expr, err := g.mappingExpr(fmt.Sprintf("value.Value%d", i), sourceVariant.PayloadTypes[i], targetVariant.PayloadTypes[i], sourceEnum.Name+"."+sourceVariant.Name)
if err != nil {
return err
}

View file

@ -751,7 +751,7 @@ func (p *parser) parseMatch() (Stmt, error) {
if err != nil {
return nil, err
}
if _, err := p.expect(tokenDoubleColon, "expected '::' in match case"); err != nil {
if _, err := p.expect(tokenDot, "expected '.' in match case"); err != nil {
return nil, err
}
variant, err := p.expect(tokenIdent, "expected variant name")
@ -813,7 +813,7 @@ func (p *parser) parseMatchExpr() (Expr, error) {
if err != nil {
return nil, err
}
if _, err := p.expect(tokenDoubleColon, "expected '::' in match case"); err != nil {
if _, err := p.expect(tokenDot, "expected '.' in match case"); err != nil {
return nil, err
}
variant, err := p.expect(tokenIdent, "expected variant name")
@ -1029,31 +1029,6 @@ func (p *parser) parsePrefix() (Expr, error) {
tok := p.advance()
switch tok.kind {
case tokenIdent:
if p.match(tokenDoubleColon) {
variant, err := p.expect(tokenIdent, "expected enum variant")
if err != nil {
return nil, err
}
var values []Expr
if p.match(tokenLParen) {
if !p.check(tokenRParen) {
for {
value, err := p.parseExpr(0)
if err != nil {
return nil, err
}
values = append(values, value)
if !p.match(tokenComma) {
break
}
}
}
if _, err := p.expect(tokenRParen, "expected ')' after variant values"); err != nil {
return nil, err
}
}
return p.parsePostfix(EnumVariantExpr{EnumName: tok.lexeme, VariantName: variant.lexeme, Values: values})
}
return p.parsePostfix(IdentExpr{Name: tok.lexeme})
case tokenInt:
return IntExpr{Value: tok.lexeme}, nil

View file

@ -10,7 +10,7 @@ func TestResultQuestionPropagatesGoError(t *testing.T) {
import strconv
fun parse(value: String): Result<Int, Error> {
val parsed = strconv.atoi(value)?
return Result::Ok(parsed)
return Result.Ok(parsed)
}`)
if err != nil {
t.Fatal(err)
@ -74,8 +74,8 @@ fun changeDirectory(path: String): Result<Unit, Error> { return os.chdir(path) }
func TestResultQuestionPropagatesGotlinResult(t *testing.T) {
prog, err := Parse(`package demo
import errors
fun inner(ok: Boolean): Result<String, Error> { if (!ok) { return Result::Err(errors.new("failed")) }; return Result::Ok("ok") }
fun outer(): Result<String, Error> { val value = inner(true)?; return Result::Ok(value) }`)
fun inner(ok: Boolean): Result<String, Error> { if (!ok) { return Result.Err(errors.new("failed")) }; return Result.Ok("ok") }
fun outer(): Result<String, Error> { val value = inner(true)?; return Result.Ok(value) }`)
if err != nil {
t.Fatal(err)
}
@ -127,7 +127,7 @@ import strconv
fun parse(value: String): Result<Int, Error> {
val input = value
val parsed = strconv.atoi(input)?
return Result::Ok(parsed)
return Result.Ok(parsed)
}`)
if err != nil {
t.Fatal(err)

View file

@ -3,73 +3,72 @@ package lang
type tokenKind string
const (
tokenEOF tokenKind = "EOF"
tokenIdent tokenKind = "IDENT"
tokenInt tokenKind = "INT"
tokenFloat tokenKind = "FLOAT"
tokenString tokenKind = "STRING"
tokenTrue tokenKind = "TRUE"
tokenFalse tokenKind = "FALSE"
tokenNull tokenKind = "NULL"
tokenImport tokenKind = "IMPORT"
tokenPackage tokenKind = "PACKAGE"
tokenClass tokenKind = "CLASS"
tokenData tokenKind = "DATA"
tokenWorker tokenKind = "WORKER"
tokenInterface tokenKind = "INTERFACE"
tokenEnum tokenKind = "ENUM"
tokenMatch tokenKind = "MATCH"
tokenFun tokenKind = "FUN"
tokenSuspend tokenKind = "SUSPEND"
tokenOverride tokenKind = "OVERRIDE"
tokenPrivate tokenKind = "PRIVATE"
tokenVal tokenKind = "VAL"
tokenVar tokenKind = "VAR"
tokenIf tokenKind = "IF"
tokenElse tokenKind = "ELSE"
tokenWhile tokenKind = "WHILE"
tokenFor tokenKind = "FOR"
tokenIn tokenKind = "IN"
tokenSelect tokenKind = "SELECT"
tokenReturn tokenKind = "RETURN"
tokenGo tokenKind = "GO"
tokenDefer tokenKind = "DEFER"
tokenTry tokenKind = "TRY"
tokenCatch tokenKind = "CATCH"
tokenThrow tokenKind = "THROW"
tokenLParen tokenKind = "("
tokenRParen tokenKind = ")"
tokenLBrace tokenKind = "{"
tokenRBrace tokenKind = "}"
tokenLBracket tokenKind = "["
tokenRBracket tokenKind = "]"
tokenComma tokenKind = ","
tokenDot tokenKind = "."
tokenColon tokenKind = ":"
tokenDoubleColon tokenKind = "::"
tokenSemicolon tokenKind = ";"
tokenPlus tokenKind = "+"
tokenMinus tokenKind = "-"
tokenStar tokenKind = "*"
tokenSlash tokenKind = "/"
tokenPercent tokenKind = "%"
tokenBang tokenKind = "!"
tokenAssign tokenKind = "="
tokenPlusAssign tokenKind = "+="
tokenEq tokenKind = "=="
tokenNeq tokenKind = "!="
tokenLt tokenKind = "<"
tokenLte tokenKind = "<="
tokenGt tokenKind = ">"
tokenGte tokenKind = ">="
tokenAnd tokenKind = "&&"
tokenAmp tokenKind = "&"
tokenAt tokenKind = "@"
tokenQuestion tokenKind = "?"
tokenSafeDot tokenKind = "?."
tokenDoubleBang tokenKind = "!!"
tokenOr tokenKind = "||"
tokenArrow tokenKind = "->"
tokenEOF tokenKind = "EOF"
tokenIdent tokenKind = "IDENT"
tokenInt tokenKind = "INT"
tokenFloat tokenKind = "FLOAT"
tokenString tokenKind = "STRING"
tokenTrue tokenKind = "TRUE"
tokenFalse tokenKind = "FALSE"
tokenNull tokenKind = "NULL"
tokenImport tokenKind = "IMPORT"
tokenPackage tokenKind = "PACKAGE"
tokenClass tokenKind = "CLASS"
tokenData tokenKind = "DATA"
tokenWorker tokenKind = "WORKER"
tokenInterface tokenKind = "INTERFACE"
tokenEnum tokenKind = "ENUM"
tokenMatch tokenKind = "MATCH"
tokenFun tokenKind = "FUN"
tokenSuspend tokenKind = "SUSPEND"
tokenOverride tokenKind = "OVERRIDE"
tokenPrivate tokenKind = "PRIVATE"
tokenVal tokenKind = "VAL"
tokenVar tokenKind = "VAR"
tokenIf tokenKind = "IF"
tokenElse tokenKind = "ELSE"
tokenWhile tokenKind = "WHILE"
tokenFor tokenKind = "FOR"
tokenIn tokenKind = "IN"
tokenSelect tokenKind = "SELECT"
tokenReturn tokenKind = "RETURN"
tokenGo tokenKind = "GO"
tokenDefer tokenKind = "DEFER"
tokenTry tokenKind = "TRY"
tokenCatch tokenKind = "CATCH"
tokenThrow tokenKind = "THROW"
tokenLParen tokenKind = "("
tokenRParen tokenKind = ")"
tokenLBrace tokenKind = "{"
tokenRBrace tokenKind = "}"
tokenLBracket tokenKind = "["
tokenRBracket tokenKind = "]"
tokenComma tokenKind = ","
tokenDot tokenKind = "."
tokenColon tokenKind = ":"
tokenSemicolon tokenKind = ";"
tokenPlus tokenKind = "+"
tokenMinus tokenKind = "-"
tokenStar tokenKind = "*"
tokenSlash tokenKind = "/"
tokenPercent tokenKind = "%"
tokenBang tokenKind = "!"
tokenAssign tokenKind = "="
tokenPlusAssign tokenKind = "+="
tokenEq tokenKind = "=="
tokenNeq tokenKind = "!="
tokenLt tokenKind = "<"
tokenLte tokenKind = "<="
tokenGt tokenKind = ">"
tokenGte tokenKind = ">="
tokenAnd tokenKind = "&&"
tokenAmp tokenKind = "&"
tokenAt tokenKind = "@"
tokenQuestion tokenKind = "?"
tokenSafeDot tokenKind = "?."
tokenDoubleBang tokenKind = "!!"
tokenOr tokenKind = "||"
tokenArrow tokenKind = "->"
)
var keywords = map[string]tokenKind{

View file

@ -67,13 +67,13 @@
"prefix": "match",
"body": [
"match (${1:result}) {",
" ${2:Result}::${3:Success}(${4:value}) -> {",
" ${2:Result}.${3:Success}(${4:value}) -> {",
" $5",
" }",
" ${2:Result}::${6:Failure}(${7:reason}) -> {",
" ${2:Result}.${6:Failure}(${7:reason}) -> {",
" $8",
" }",
" ${2:Result}::${9:Pending} -> {",
" ${2:Result}.${9:Pending} -> {",
" $0",
" }",
"}"
@ -84,8 +84,8 @@
"prefix": "matchvalue",
"body": [
"val ${1:value} = match (${2:result}) {",
" ${3:Result}::${4:Success}(${5:item}) -> ${5:item}",
" ${3:Result}::${6:Failure}(${7:reason}) -> ${7:reason}",
" ${3:Result}.${4:Success}(${5:item}) -> ${5:item}",
" ${3:Result}.${6:Failure}(${7:reason}) -> ${7:reason}",
" $0",
"}"
],
@ -111,7 +111,7 @@
"body": [
"fun ${1:name}(${2}): Result<${3:Value}, Error> {",
" val ${4:value} = ${5:operation}()?",
" return Result::Ok(${4:value})",
" return Result.Ok(${4:value})",
"}"
],
"description": "Function with Rust-style Result propagation"
@ -120,8 +120,8 @@
"prefix": "resultmatch",
"body": [
"match (${1:result}) {",
" Result::Ok(${2:value}) -> { $3 }",
" Result::Err(${4:error}) -> { $0 }",
" Result.Ok(${2:value}) -> { $3 }",
" Result.Err(${4:error}) -> { $0 }",
"}"
],
"description": "Match a Result value"

View file

@ -356,10 +356,6 @@
"name": "keyword.operator.arrow.gotlin",
"match": "->"
},
{
"name": "punctuation.accessor.enum.gotlin",
"match": "::"
},
{
"name": "keyword.operator.arithmetic.gotlin",
"match": "[+\\-*/%<>]"