Skip to content

Commit

Permalink
Add support for argument spread operator
Browse files Browse the repository at this point in the history
Fix #57
  • Loading branch information
MangelMaxime committed Mar 24, 2024
1 parent 2742f30 commit dc1b1c7
Show file tree
Hide file tree
Showing 19 changed files with 102 additions and 78 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
abstract member error: string option with get, set
```

* Add support for argument spread operator ([GH-57](https://github.com/glutinum-org/cli/issues/57))

### Changed

* Replace `Boolean` with `bool`
Expand Down
2 changes: 2 additions & 0 deletions src/Glutinum.Converter/FsharpAST.fs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,11 @@ type FSharpAttribute =
| EmitIndexer
| Global
| ParamObject
| ParamArray

type FSharpParameter =
{
Attributes: FSharpAttribute list
Name: string
IsOptional: bool
Type: FSharpType
Expand Down
1 change: 1 addition & 0 deletions src/Glutinum.Converter/GlueAST.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type GlueParameter =
{
Name: string
IsOptional: bool
IsSpread: bool
Type: GlueType
}

Expand Down
2 changes: 1 addition & 1 deletion src/Glutinum.Converter/Glutinum.Converter.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<Compile Include="Reader/IndexedAccessType.fs" />
<Compile Include="Reader/InterfaceDeclaration.fs" />
<Compile Include="Reader/ModuleDeclaration.fs" />
<Compile Include="Reader/NamedDeclaration.fs" />
<Compile Include="Reader/Declaration.fs" />
<Compile Include="Reader/Node.fs" />
<Compile Include="Reader/Parameters.fs" />
<Compile Include="Reader/TypeAliasDeclaration.fs" />
Expand Down
25 changes: 25 additions & 0 deletions src/Glutinum.Converter/Printer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ let private sanitizeEnumCaseName (name: string) =
$"``{name}``"
| _ -> name

let private hasParamArrayAttribute (attributes: FSharpAttribute list) =
attributes
|> List.exists (
function
| FSharpAttribute.ParamArray -> true
| _ -> false
)

let private attributeToText (fsharpAttribute: FSharpAttribute) =
match fsharpAttribute with
| FSharpAttribute.Text text -> text
Expand Down Expand Up @@ -98,6 +106,7 @@ let private attributeToText (fsharpAttribute: FSharpAttribute) =
| FSharpAttribute.Global -> "[<Global>]"
| FSharpAttribute.ParamObject -> "[<ParamObject>]"
| FSharpAttribute.EmitSelf -> "[<Emit(\"$0\")>]"
| FSharpAttribute.ParamArray -> "[<ParamArray>]"

let private printInlineAttribute
(printer: Printer)
Expand Down Expand Up @@ -302,10 +311,15 @@ let private printInterface (printer: Printer) (interfaceInfo: FSharpInterface) =
if index <> 0 then
printer.WriteInline(", ")

printInlineAttributes printer p.Attributes

if p.IsOptional then
printer.WriteInline("?")

printer.WriteInline($"{p.Name}: {printType p.Type}")

if hasParamArrayAttribute p.Attributes then
printer.WriteInline(" []")
)

printer.WriteInline(")")
Expand All @@ -321,10 +335,15 @@ let private printInterface (printer: Printer) (interfaceInfo: FSharpInterface) =
if index <> 0 then
printer.WriteInline(" * ")

printInlineAttributes printer p.Attributes

if p.IsOptional then
printer.WriteInline("?")

printer.WriteInline($"{p.Name}: {printType p.Type}")

if hasParamArrayAttribute p.Attributes then
printer.WriteInline(" []")
)

if methodInfo.IsStatic then
Expand Down Expand Up @@ -436,6 +455,9 @@ let private printPrimaryConstructor
printer.Write("") // Empty string to have the correct indentation

printer.WriteInline($"{p.Name}: {printType p.Type}")

if hasParamArrayAttribute p.Attributes then
printer.WriteInline(" []")
)

printer.Unindent
Expand Down Expand Up @@ -469,6 +491,9 @@ let private printClass (printer: Printer) (classInfo: FSharpClass) =
printer.WriteInline("?")

printer.WriteInline($"{p.Name}: {printType p.Type}")

if hasParamArrayAttribute p.Attributes then
printer.WriteInline(" []")
)

printer.WriteInline(") =")
Expand Down
2 changes: 1 addition & 1 deletion src/Glutinum.Converter/Reader/ClassDeclaration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ let readClassDeclaration
| _ -> None
)

let members = members |> Seq.toList |> List.map reader.ReadNamedDeclaration
let members = members |> Seq.toList |> List.map reader.ReadDeclaration

{
Name = name.getText ()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
module Glutinum.Converter.Reader.NamedDeclaration
module Glutinum.Converter.Reader.Declaration

open Glutinum.Converter.GlueAST
open Glutinum.Converter.Reader.Types
open TypeScript
open Fable.Core.JsInterop

let readNamedDeclaration
let readDeclaration
(reader: ITypeScriptReader)
(declaration: Ts.Declaration)
: GlueMember
Expand Down
4 changes: 1 addition & 3 deletions src/Glutinum.Converter/Reader/InterfaceDeclaration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ let readInterfaceDeclaration
=

let members =
declaration.members
|> Seq.toList
|> List.map reader.ReadNamedDeclaration
declaration.members |> Seq.toList |> List.map reader.ReadDeclaration

{
Name = declaration.name.getText ()
Expand Down
2 changes: 2 additions & 0 deletions src/Glutinum.Converter/Reader/Parameters.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ open TypeScript
let readParameters
(reader: ITypeScriptReader)
(parameters: ResizeArray<Ts.ParameterDeclaration>)
: GlueParameter list
=
parameters
|> Seq.toList
Expand All @@ -16,6 +17,7 @@ let readParameters
{
Name = name.getText ()
IsOptional = parameter.questionToken.IsSome
IsSpread = parameter.dotDotDotToken.IsSome
Type = reader.ReadTypeNode parameter.``type``
}
)
63 changes: 3 additions & 60 deletions src/Glutinum.Converter/Reader/TypeNode.fs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ let readTypeNode
let members =
interfaceDeclaration.members
|> Seq.toList
|> List.map reader.ReadNamedDeclaration
|> List.map reader.ReadDeclaration

({
Name = interfaceDeclaration.name.getText ()
Expand Down Expand Up @@ -233,7 +233,7 @@ let readTypeNode
match property.declarations with
| Some declarations ->
if declarations.Count = 1 then
reader.ReadNamedDeclaration declarations.[0]
reader.ReadDeclaration declarations.[0]
else
generateReaderError
"type node"
Expand All @@ -248,70 +248,13 @@ let readTypeNode
)
|> GlueType.IntersectionType

// let properties =
// unionOrIntersectionType.getProperties()
// |> Seq.map (fun property ->
// match property.declarations with
// | Some declarations ->
// if declarations.Count = 1 then
// let declaration = declarations.[0]

// let x = reader.ReadNamedDeclaration declaration

// match declaration.kind with
// | Ts.SyntaxKind.PropertySignature ->
// let propertySignature = declaration :?> Ts.PropertySignature
// let name = unbox<Ts.Node> propertySignature.name

// let accessor =
// match propertySignature.modifiers with
// | Some modifiers ->
// modifiers
// |> Seq.exists (fun modifier ->
// modifier?kind = Ts.SyntaxKind.ReadonlyKeyword
// )
// |> function
// | true -> GlueAccessor.ReadOnly
// | false -> GlueAccessor.ReadWrite
// | None -> GlueAccessor.ReadWrite

// ({
// Name = name.getText ()
// Type = reader.ReadTypeNode propertySignature.``type``
// IsOptional = propertySignature.questionToken.IsSome
// IsStatic = false
// Accessor = accessor
// }
// : GlueProperty)
// |> GlueMember.Property
// else
// generateReaderError
// "type node"
// "Gutinum expects only one declaration for a type reference. Please report this issue, if you see this message."
// typeNode
// |> TypeScriptReaderException
// |> raise
// | None ->
// generateReaderError
// "type node"
// "Missing declarations"
// typeNode
// |> TypeScriptReaderException
// |> raise
// )

// // intersectionTypeNode.types
// // |> Seq.toList
// // |> List.map (Some >> reader.ReadTypeNode)
// // |> GlueType.IntersectionType

| Ts.SyntaxKind.TypeLiteral ->
let typeLiteralNode = typeNode :?> Ts.TypeLiteralNode

let members =
typeLiteralNode.members
|> Seq.toList
|> List.map reader.ReadNamedDeclaration
|> List.map reader.ReadDeclaration

({ Members = members }: GlueTypeLiteral) |> GlueType.TypeLiteral

Expand Down
9 changes: 3 additions & 6 deletions src/Glutinum.Converter/Reader/TypeScriptReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ open Glutinum.Converter.Reader.FunctionDeclaration
open Glutinum.Converter.Reader.IndexedAccessType
open Glutinum.Converter.Reader.InterfaceDeclaration
open Glutinum.Converter.Reader.ModuleDeclaration
open Glutinum.Converter.Reader.NamedDeclaration
open Glutinum.Converter.Reader.Declaration
open Glutinum.Converter.Reader.Node
open Glutinum.Converter.Reader.Parameters
open Glutinum.Converter.Reader.TypeAliasDeclaration
Expand Down Expand Up @@ -85,11 +85,8 @@ type TypeScriptReader(checker: Ts.TypeChecker) =
=
readVariableStatement this variableStatement

member this.ReadNamedDeclaration
(declaration: Ts.Declaration)
: GlueMember
=
readNamedDeclaration this declaration
member this.ReadDeclaration(declaration: Ts.Declaration) : GlueMember =
readDeclaration this declaration

member this.ReadParameters
(parameters: ResizeArray<Ts.ParameterDeclaration>)
Expand Down
2 changes: 1 addition & 1 deletion src/Glutinum.Converter/Reader/Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type ITypeScriptReader =
abstract ReadParameters:
parameters: ResizeArray<Ts.ParameterDeclaration> -> GlueParameter list

abstract ReadNamedDeclaration: declaration: Ts.Declaration -> GlueMember
abstract ReadDeclaration: declaration: Ts.Declaration -> GlueMember

abstract ReadUnionTypeNode: unionType: Ts.UnionTypeNode -> GlueType

Expand Down
12 changes: 11 additions & 1 deletion src/Glutinum.Converter/Transform.fs
Original file line number Diff line number Diff line change
Expand Up @@ -414,9 +414,14 @@ let private transformParameter
let context = context.PushScope(parameter.Name)

{
Attributes =
[
if parameter.IsSpread then
FSharpAttribute.ParamArray
]
Name = Naming.sanitizeName parameter.Name
IsOptional = parameter.IsOptional
Type = (transformType context) parameter.Type
Type = transformType context parameter.Type
}

let private transformAccessor (accessor: GlueAccessor) : FSharpAccessor =
Expand Down Expand Up @@ -540,6 +545,7 @@ module private TransformMembers =
sanitizeNameAndPushScope methodInfo.Name context

{
Attributes = []
Name = name
IsOptional = methodInfo.IsOptional
Type = transformType context methodInfo.Type
Expand All @@ -551,6 +557,7 @@ module private TransformMembers =
sanitizeNameAndPushScope propertyInfo.Name context

{
Attributes = []
Name = name
IsOptional = propertyInfo.IsOptional
Type = transformType context propertyInfo.Type
Expand All @@ -561,6 +568,7 @@ module private TransformMembers =
let name, context = sanitizeNameAndPushScope "Item" context

{
Attributes = []
Name = name
IsOptional = false
Type = transformType context indexSignature.Type
Expand All @@ -572,6 +580,7 @@ module private TransformMembers =
sanitizeNameAndPushScope methodSignature.Name context

{
Attributes = []
Name = name
IsOptional = false
Type = transformType context methodSignature.Type
Expand All @@ -582,6 +591,7 @@ module private TransformMembers =
let name, context = sanitizeNameAndPushScope "Invoke" context

{
Attributes = []
Name = name
IsOptional = false
Type = transformType context callSignatureInfo.Type
Expand Down
3 changes: 3 additions & 0 deletions src/Glutinum.Web/Pages/Editors.FSharpAST.FSharpASTViewer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ type FSharpASTViewer =

| FSharpAttribute.EmitSelf -> ASTViewer.renderValueOnly "EmitSelf"

| FSharpAttribute.ParamArray -> ASTViewer.renderValueOnly "ParamArray"

static member private Attributes(attributes: FSharpAttribute list) =
attributes
|> List.map FSharpASTViewer.FSharpAttribute
Expand Down Expand Up @@ -117,6 +119,7 @@ type FSharpASTViewer =
ASTViewer.renderNode "Parameter" [
FSharpASTViewer.Name parameter.Name
FSharpASTViewer.IsOptional parameter.IsOptional
FSharpASTViewer.Attributes parameter.Attributes
FSharpASTViewer.Type parameter.Type
]

Expand Down
9 changes: 6 additions & 3 deletions src/Glutinum.Web/Pages/Editors.GlueAST.GlueASTViewer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@ type GlueASTViewer =
static member private IsStatic(isStatic: bool) =
ASTViewer.renderKeyValue "IsStatic" (string isStatic)

static member private IsSpread(isSpread: bool) =
ASTViewer.renderKeyValue "IsSpread" (string isSpread)

static member private Parameters(parameters: GlueParameter list) =
parameters
|> List.map (fun parameter ->
ASTViewer.renderNode "Parameter" [
GlueASTViewer.Name parameter.Name
ASTViewer.renderNode "Type" [
GlueASTViewer.GlueType parameter.Type
]
GlueASTViewer.IsOptional parameter.IsOptional
GlueASTViewer.IsSpread parameter.IsSpread
GlueASTViewer.Type parameter.Type
]
)
|> ASTViewer.renderNode "Parameters"
Expand Down
5 changes: 5 additions & 0 deletions tests/specs/references/class/constructorsWithSpread.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export class Logger {
constructor()

constructor(...args: string)
}
Loading

0 comments on commit dc1b1c7

Please sign in to comment.