Skip to content

Commit

Permalink
Merge pull request #119 from 1Password/jane/annotations/override-type
Browse files Browse the repository at this point in the history
Parameter to override a field type on a per-language basis
  • Loading branch information
Lucretiel committed Jun 17, 2023
2 parents d7b37bf + f815982 commit 913c5c2
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 41 deletions.
29 changes: 29 additions & 0 deletions core/data/tests/can_override_types/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[typeshare]
#[serde(rename_all = "camelCase")]
struct OverrideStruct {
// These annotations are intentionally inconsistent across languages
#[typeshare(
swift(type = "Int"),
typescript(readonly, type = "any | undefined"),
kotlin(type = "Int"), go(type = "uint"),
scala(type = "Short")
)]
field_to_override: String,
}

#[typeshare]
#[serde(tag = "type", content = "content")]
enum OverrideEnum {
UnitVariant,
TupleVariant(String),
#[serde(rename_all = "camelCase")]
AnonymousStructVariant {
#[typeshare(
swift(type = "Int"),
typescript(readonly, type = "any | undefined"),
kotlin(type = "Int"), go(type = "uint"),
scala(type = "Short")
)]
field_to_override: String
}
}
87 changes: 87 additions & 0 deletions core/data/tests/can_override_types/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package proto

import "encoding/json"

type OverrideStruct struct {
FieldToOverride uint `json:"fieldToOverride"`
}
// Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum
type OverrideEnumAnonymousStructVariantInner struct {
FieldToOverride uint `json:"fieldToOverride"`
}
type OverrideEnumTypes string
const (
OverrideEnumTypeVariantUnitVariant OverrideEnumTypes = "UnitVariant"
OverrideEnumTypeVariantTupleVariant OverrideEnumTypes = "TupleVariant"
OverrideEnumTypeVariantAnonymousStructVariant OverrideEnumTypes = "AnonymousStructVariant"
)
type OverrideEnum struct{
Type OverrideEnumTypes `json:"type"`
content interface{}
}

func (o *OverrideEnum) UnmarshalJSON(data []byte) error {
var enum struct {
Tag OverrideEnumTypes `json:"type"`
Content json.RawMessage `json:"content"`
}
if err := json.Unmarshal(data, &enum); err != nil {
return err
}

o.Type = enum.Tag
switch o.Type {
case OverrideEnumTypeVariantUnitVariant:
return nil
case OverrideEnumTypeVariantTupleVariant:
var res string
o.content = &res
case OverrideEnumTypeVariantAnonymousStructVariant:
var res OverrideEnumAnonymousStructVariantInner
o.content = &res

}
if err := json.Unmarshal(enum.Content, &o.content); err != nil {
return err
}

return nil
}

func (o OverrideEnum) MarshalJSON() ([]byte, error) {
var enum struct {
Tag OverrideEnumTypes `json:"type"`
Content interface{} `json:"content,omitempty"`
}
enum.Tag = o.Type
enum.Content = o.content
return json.Marshal(enum)
}

func (o OverrideEnum) TupleVariant() string {
res, _ := o.content.(*string)
return *res
}
func (o OverrideEnum) AnonymousStructVariant() *OverrideEnumAnonymousStructVariantInner {
res, _ := o.content.(*OverrideEnumAnonymousStructVariantInner)
return res
}

func NewOverrideEnumTypeVariantUnitVariant() OverrideEnum {
return OverrideEnum{
Type: OverrideEnumTypeVariantUnitVariant,
}
}
func NewOverrideEnumTypeVariantTupleVariant(content string) OverrideEnum {
return OverrideEnum{
Type: OverrideEnumTypeVariantTupleVariant,
content: &content,
}
}
func NewOverrideEnumTypeVariantAnonymousStructVariant(content *OverrideEnumAnonymousStructVariantInner) OverrideEnum {
return OverrideEnum{
Type: OverrideEnumTypeVariantAnonymousStructVariant,
content: content,
}
}

31 changes: 31 additions & 0 deletions core/data/tests/can_override_types/output.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@file:NoLiveLiterals

package com.agilebits.onepassword

import androidx.compose.runtime.NoLiveLiterals
import kotlinx.serialization.*

@Serializable
data class OverrideStruct (
val fieldToOverride: Int
)

/// Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum
@Serializable
data class OverrideEnumAnonymousStructVariantInner (
val fieldToOverride: Int
)

@Serializable
sealed class OverrideEnum {
@Serializable
@SerialName("UnitVariant")
object UnitVariant: OverrideEnum()
@Serializable
@SerialName("TupleVariant")
data class TupleVariant(val content: String): OverrideEnum()
@Serializable
@SerialName("AnonymousStructVariant")
data class AnonymousStructVariant(val content: OverrideEnumAnonymousStructVariantInner): OverrideEnum()
}

29 changes: 29 additions & 0 deletions core/data/tests/can_override_types/output.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.agilebits

package onepassword {

case class OverrideStruct (
fieldToOverride: Short
)

// Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum
case class OverrideEnumAnonymousStructVariantInner (
fieldToOverride: Short
)

sealed trait OverrideEnum {
def serialName: String
}
object OverrideEnum {
case object UnitVariant extends OverrideEnum {
val serialName: String = "UnitVariant"
}
case class TupleVariant(content: String) extends OverrideEnum {
val serialName: String = "TupleVariant"
}
case class AnonymousStructVariant(content: OverrideEnumAnonymousStructVariantInner) extends OverrideEnum {
val serialName: String = "AnonymousStructVariant"
}
}

}
70 changes: 70 additions & 0 deletions core/data/tests/can_override_types/output.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import Foundation

public struct OverrideStruct: Codable {
public let fieldToOverride: Int

public init(fieldToOverride: Int) {
self.fieldToOverride = fieldToOverride
}
}


/// Generated type representing the anonymous struct variant `AnonymousStructVariant` of the `OverrideEnum` Rust enum
public struct OverrideEnumAnonymousStructVariantInner: Codable {
public let fieldToOverride: Int

public init(fieldToOverride: Int) {
self.fieldToOverride = fieldToOverride
}
}
public enum OverrideEnum: Codable {
case unitVariant
case tupleVariant(String)
case anonymousStructVariant(OverrideEnumAnonymousStructVariantInner)

enum CodingKeys: String, CodingKey, Codable {
case unitVariant = "UnitVariant",
tupleVariant = "TupleVariant",
anonymousStructVariant = "AnonymousStructVariant"
}

private enum ContainerCodingKeys: String, CodingKey {
case type, content
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: ContainerCodingKeys.self)
if let type = try? container.decode(CodingKeys.self, forKey: .type) {
switch type {
case .unitVariant:
self = .unitVariant
return
case .tupleVariant:
if let content = try? container.decode(String.self, forKey: .content) {
self = .tupleVariant(content)
return
}
case .anonymousStructVariant:
if let content = try? container.decode(OverrideEnumAnonymousStructVariantInner.self, forKey: .content) {
self = .anonymousStructVariant(content)
return
}
}
}
throw DecodingError.typeMismatch(OverrideEnum.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for OverrideEnum"))
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: ContainerCodingKeys.self)
switch self {
case .unitVariant:
try container.encode(CodingKeys.unitVariant, forKey: .type)
case .tupleVariant(let content):
try container.encode(CodingKeys.tupleVariant, forKey: .type)
try container.encode(content, forKey: .content)
case .anonymousStructVariant(let content):
try container.encode(CodingKeys.anonymousStructVariant, forKey: .type)
try container.encode(content, forKey: .content)
}
}
}
11 changes: 11 additions & 0 deletions core/data/tests/can_override_types/output.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface OverrideStruct {
readonly fieldToOverride: any | undefined;
}

export type OverrideEnum =
| { type: "UnitVariant", content?: undefined }
| { type: "TupleVariant", content: string }
| { type: "AnonymousStructVariant", content: {
readonly fieldToOverride: any | undefined;
}};

12 changes: 9 additions & 3 deletions core/src/language/go.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::io::Write;

use crate::language::SupportedLanguage;
use crate::parser::ParsedData;
use crate::rename::RenameExt;
use crate::rust_types::{RustItem, RustTypeFormatError, SpecialRustType};
Expand Down Expand Up @@ -401,9 +402,14 @@ func ({short_name} {full_name}) MarshalJSON() ([]byte, error) {{
}

write_comments(w, 1, &field.comments)?;
let type_name = self
.format_type(&field.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;

let type_name = match field.type_override(SupportedLanguage::Go) {
Some(type_override) => type_override.to_owned(),
None => self
.format_type(&field.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?,
};

let go_type = self.acronyms_to_uppercase(&type_name);
let is_optional = field.ty.is_optional() || field.has_default;
let formatted_renamed_id = format!("{:?}", &field.id.renamed);
Expand Down
11 changes: 8 additions & 3 deletions core/src/language/kotlin.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::Language;
use crate::language::SupportedLanguage;
use crate::rust_types::{RustTypeFormatError, SpecialRustType};
use crate::{
parser::remove_dash_from_identifier,
Expand Down Expand Up @@ -313,9 +314,13 @@ impl Kotlin {
if requires_serial_name {
writeln!(w, "\t@SerialName({:?})", &f.id.renamed)?;
}
let ty = self
.format_type(&f.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
let ty = match f.type_override(SupportedLanguage::Kotlin) {
Some(type_override) => type_override.to_owned(),
None => self
.format_type(&f.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?,
};

write!(
w,
"\tval {}: {}{}",
Expand Down
12 changes: 9 additions & 3 deletions core/src/language/scala.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::Language;
use crate::language::SupportedLanguage;
use crate::parser::ParsedData;
use crate::rust_types::{RustType, RustTypeFormatError, SpecialRustType};
use crate::{
Expand Down Expand Up @@ -342,9 +343,14 @@ impl Scala {
generic_types: &[String],
) -> std::io::Result<()> {
self.write_comments(w, 1, &f.comments)?;
let ty = self
.format_type(&f.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;

let ty = match f.type_override(SupportedLanguage::Scala) {
Some(type_override) => type_override.to_owned(),
None => self
.format_type(&f.ty, generic_types)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?,
};

write!(
w,
"\t{}: {}{}",
Expand Down
Loading

0 comments on commit 913c5c2

Please sign in to comment.