Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adds typescript support #4

Merged
merged 10 commits into from
Dec 29, 2020
6 changes: 3 additions & 3 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
"args": ["--openapi",
"C:/sources/github/msgraph-sdk-powershell/openApiDocs/v1.0/mail.yml",
"--language",
"java",
"typescript",
"-o",
"C:/Users/vibiret/Desktop/graphjavav4/utilities/src/main/java/graphjavav4/utilities",
"C:/Users/vibiret/Desktop/graphtypescriptv4/src",
"-n",
"graphjavav4.utilities" ],
"graphtypescriptv4.utilities" ],
"cwd": "${workspaceFolder}/src/kiota",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
Expand Down
18 changes: 16 additions & 2 deletions src/kiota.core/CodeDOM/CodeBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ namespace kiota.core
/// </summary>
public class CodeBlock : CodeElement
{
public CodeElement StartBlock;
public BlockDeclaration StartBlock = new BlockDeclaration();
public List<CodeElement> InnerChildElements = new List<CodeElement>();
public CodeElement EndBlock;
public BlockEnd EndBlock = new BlockEnd();

public override string Name
{
Expand All @@ -24,5 +24,19 @@ public override IList<CodeElement> GetChildElements()
elements.Add(EndBlock);
return elements;
}
public void AddUsing(params CodeUsing[] codeUsings)
{
StartBlock.Usings.AddRange(codeUsings);
}
public class BlockDeclaration : CodeTerminal
{
public override string Name { get; set; }
public List<CodeUsing> Usings = new List<CodeUsing>();
}

public class BlockEnd : CodeTerminal
{

}
}
}
4 changes: 2 additions & 2 deletions src/kiota.core/CodeDOM/CodeClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public void AddInnerClass(CodeClass codeClass)
this.InnerChildElements.Add(codeClass);
}

public class Declaration : CodeTerminal
public class Declaration : BlockDeclaration
{
/// <summary>
/// Class name
Expand All @@ -66,7 +66,7 @@ public override string Name
public CodeType Type;
}

public class End : CodeTerminal
public class End : BlockEnd
{
}
}
Expand Down
31 changes: 3 additions & 28 deletions src/kiota.core/CodeDOM/CodeNamespace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,21 @@ namespace kiota.core
public class CodeNamespace : CodeBlock
{
private string name;

public CodeNamespace()
{
StartBlock = new Declaration();
EndBlock = new End();
}
public override string Name
{
get { return name;
}
set {
name = value;
StartBlock = new Declaration() { Name = name };
if(StartBlock == null)
StartBlock = new BlockDeclaration();
StartBlock.Name = name;
}
}

public void AddClass(CodeClass codeClass)
{
this.InnerChildElements.Add(codeClass);
}
public void AddUsing(CodeUsing codeUsing)
{
((Declaration)this.StartBlock).Usings.Add(codeUsing);
}
public void AddUsing(IEnumerable<CodeUsing> codeUsings)
{
foreach (var codeUsing in codeUsings)
{
((Declaration)this.StartBlock).Usings.Add(codeUsing);
}
}
public class Declaration : CodeTerminal
{
public override string Name { get; set; }
public List<CodeUsing> Usings = new List<CodeUsing>();
}

public class End : CodeTerminal
{

}
}
}
6 changes: 6 additions & 0 deletions src/kiota.core/CodeDOM/CodeType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ public override string Name
{
get; set;
}
public CodeClass TypeDefinition
{
get;
set;
}

public bool ActionOf = false;

public OpenApiSchema Schema;
Expand Down
2 changes: 1 addition & 1 deletion src/kiota.core/CodeRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public static async Task RenderCodeNamespaceToFilePerClassAsync(LanguageWriter w
if (codeClass is not null)
{
var codeNamespace = new CodeNamespace() { Name = root.Name };
codeNamespace.AddUsing(((CodeNamespace.Declaration)root.StartBlock).Usings);
codeNamespace.AddUsing(root.StartBlock.Usings.ToArray());
codeNamespace.AddClass(codeClass);
await RenderCodeNamespaceToSingleFileAsync(writer, codeNamespace, Path.Combine(outputPath, codeClass.Name + writer.GetFileSuffix()));
}
Expand Down
32 changes: 30 additions & 2 deletions src/kiota.core/KiotaBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ public void ApplyLanguageRefinement(GenerationLanguage language, CodeNamespace g
case GenerationLanguage.CSharp:
generatedCode.AddUsing(new CodeUsing() { Name = "System" });
generatedCode.AddUsing(new CodeUsing() { Name = "System.Threading.Tasks" });
AddInnerClasses(generatedCode);
break;
case GenerationLanguage.TypeScript:
AddRelativeImports(generatedCode);
break;
default:
break; //Do nothing
Expand All @@ -147,6 +151,28 @@ public void ApplyLanguageRefinement(GenerationLanguage language, CodeNamespace g
logger.LogInformation("{timestamp}ms: Language refinement applied", stopwatch.ElapsedMilliseconds);
}

private void AddRelativeImports(CodeElement current) {
if(current is CodeClass currentClass) {
currentClass.AddUsing(current
.GetChildElements()
.OfType<CodeProperty>()
.Select(x =>x.Type.Name)
.Distinct()
.Select(x => new CodeUsing{Name = x})
.ToArray());
}
foreach(var childClass in current.GetChildElements().OfType<CodeClass>())
AddRelativeImports(childClass);
}
private void AddInnerClasses(CodeElement current) {
if(current is CodeClass currentClass) {
foreach(var parameter in current.GetChildElements().OfType<CodeMethod>().SelectMany(x =>x.Parameters).Where(x => x.Type.ActionOf))
currentClass.AddInnerClass(parameter.Type.TypeDefinition);
}
foreach(var childClass in current.GetChildElements().OfType<CodeClass>())
AddInnerClasses(childClass);
}

/// <summary>
/// Iterate through Url Space and create request builder classes for each node in the tree
/// </summary>
Expand All @@ -164,6 +190,9 @@ public async Task CreateLanguageSourceFilesAsync(GenerationLanguage language, Co
case GenerationLanguage.Java:
languageWriter = new JavaWriter();
break;
case GenerationLanguage.TypeScript:
languageWriter = new TypeScriptWriter();
break;
default:
throw new ArgumentException($"{language} language currently not supported.");
}
Expand Down Expand Up @@ -222,7 +251,6 @@ private void CreateClass(CodeNamespace codeNamespace, OpenApiUrlSpaceNode node)
foreach(var operation in node.PathItem.Operations)
{
var parameterClass = CreateOperationParameter(node, operation);
codeClass.AddInnerClass(parameterClass);

var method = CreateOperationMethod(operation.Key, operation.Value, parameterClass);
logger.LogDebug("Creating method {name} of {type}", method.Name, method.ReturnType);
Expand Down Expand Up @@ -284,7 +312,7 @@ private CodeMethod CreateOperationMethod(OperationType operationType, OpenApiOpe
var methodParameter = new CodeParameter()
{
Name = "q",
Type = new CodeType() { Name = parameterClass.Name, ActionOf = true }
Type = new CodeType() { Name = parameterClass.Name, ActionOf = true, TypeDefinition = parameterClass }
};
method.AddParameter(methodParameter);
return method;
Expand Down
4 changes: 2 additions & 2 deletions src/kiota.core/Writers/CSharpWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ namespace kiota.core
public class CSharpWriter : LanguageWriter
{

public override void WriteNamespaceEnd(CodeNamespace.End code)
public override void WriteNamespaceEnd(CodeNamespace.BlockEnd code)
{
DecreaseIndent();
WriteLine("}");
}

public override void WriteNamespaceDeclaration(CodeNamespace.Declaration code)
public override void WriteNamespaceDeclaration(CodeNamespace.BlockDeclaration code)
{
foreach (var codeUsing in code.Usings)
{
Expand Down
4 changes: 2 additions & 2 deletions src/kiota.core/Writers/JavaWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public override void WriteMethod(CodeMethod code)
WriteLine($"public java.util.concurrent.Future<{GetTypeString(code.ReturnType)}> {code.Name}({string.Join(',', code.Parameters.Select(p=> GetParameterSignature(p)).ToList())}) {{ return null; }}");
}

public override void WriteNamespaceDeclaration(CodeNamespace.Declaration code)
public override void WriteNamespaceDeclaration(CodeNamespace.BlockDeclaration code)
{
WriteLine($"package {code.Name};");
WriteLine();
Expand All @@ -85,7 +85,7 @@ public override void WriteNamespaceDeclaration(CodeNamespace.Declaration code)
}
}

public override void WriteNamespaceEnd(CodeNamespace.End code) => WriteLine();
public override void WriteNamespaceEnd(CodeNamespace.BlockEnd code) => WriteLine();

public override void WriteProperty(CodeProperty code)
{
Expand Down
16 changes: 8 additions & 8 deletions src/kiota.core/Writers/LanguageWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public void SetTextWriter(TextWriter writer)

public abstract string GetFileSuffix();

public void IncreaseIndent()
public void IncreaseIndent(int factor = 1)
{
currentIndent += indentSize;
currentIndent += indentSize * factor;
}

public void DecreaseIndent()
public void DecreaseIndent(int factor = 1)
{
currentIndent -= indentSize;
currentIndent -= indentSize * factor;
}

public string GetIndent()
Expand Down Expand Up @@ -61,10 +61,10 @@ public void Write(CodeElement code)
{
switch (code)
{
case CodeNamespace.Declaration c: WriteNamespaceDeclaration(c); break;
case CodeNamespace.End c: WriteNamespaceEnd(c); break;
case CodeClass.Declaration c: WriteCodeClassDeclaration(c); break;
case CodeClass.End c: WriteCodeClassEnd(c); break;
case CodeNamespace.BlockDeclaration c: WriteNamespaceDeclaration(c); break;
case CodeNamespace.BlockEnd c: WriteNamespaceEnd(c); break;
case CodeProperty c: WriteProperty(c); break;
case CodeIndexer c: WriteIndexer(c); break;
case CodeMethod c: WriteMethod(c); break;
Expand All @@ -84,8 +84,8 @@ public void Write(CodeElement code)
public abstract void WriteIndexer(CodeIndexer code);
public abstract void WriteMethod(CodeMethod code);
public abstract void WriteType(CodeType code);
public abstract void WriteNamespaceEnd(CodeNamespace.End code);
public abstract void WriteNamespaceDeclaration(CodeNamespace.Declaration code);
public abstract void WriteNamespaceEnd(CodeNamespace.BlockEnd code);
public abstract void WriteNamespaceDeclaration(CodeNamespace.BlockDeclaration code);
public abstract void WriteCodeClassDeclaration(CodeClass.Declaration code);
public abstract void WriteCodeClassEnd(CodeClass.End code);
}
Expand Down
102 changes: 102 additions & 0 deletions src/kiota.core/Writers/TypeScriptWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.OpenApi.Models;

namespace kiota.core
{
public class TypeScriptWriter : LanguageWriter
{
public override string GetFileSuffix() => ".ts";

public override string GetParameterSignature(CodeParameter parameter)
{
return $"{parameter.Name}{(parameter.Optional ? "?" : string.Empty)}: {GetTypeString(parameter.Type)}{(parameter.Optional ? " | undefined": string.Empty)}";
}

public override string GetTypeString(CodeType code)
{
var typeName = TranslateType(code.Name, code.Schema);
if (code.ActionOf)
{
var indentFactor = 4;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the indentfactor for? Why would some blocks have bigger indents than others? I understand that languages may have different indent values, but why allow it to be varied per language element.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's for the anonymous type declaration in the methods parameters. We don't absolutely need it, but it looks nicer.

IncreaseIndent(indentFactor);
var childElements = code.TypeDefinition
.InnerChildElements
.OfType<CodeProperty>()
.Select(x => $"{x.Name}?: {GetTypeString(x.Type)}");
var innerDeclaration = childElements.Any() ? childElements
.Aggregate((x, y) => $"{x};{Environment.NewLine}{GetIndent()}{y}")
: string.Empty;
DecreaseIndent(indentFactor);
return $"(options?: {{{innerDeclaration}}}) => void";
}
else
{
return typeName;
}
}

public override string TranslateType(string typeName, OpenApiSchema schema)
{
switch (typeName)
{//TODO we're probably missing a bunch of type mappings
case "integer": return "number";
case "array": return $"{TranslateType(schema.Items.Type, schema.Items)}[]";
} // string, boolean, object : same casing

return typeName;
}

public override void WriteCodeClassDeclaration(CodeClass.Declaration code)
{
foreach (var codeUsing in code.Usings)
{
WriteLine($"import {{{codeUsing.Name}}} from './{codeUsing.Name}';");
}
WriteLine();
WriteLine($"export class {code.Name} {{");
IncreaseIndent();
}

public override void WriteCodeClassEnd(CodeClass.End code)
{
DecreaseIndent();
WriteLine("}");
}

public override void WriteIndexer(CodeIndexer code)
{
WriteMethod(new CodeMethod {
Name = "get",
Parameters = new List<CodeParameter> {
new CodeParameter {
Name = "position",
Type = code.IndexType,
Optional = false,
}
},
ReturnType = code.IndexType
});
}

public override void WriteMethod(CodeMethod code)
{
WriteLine($"public readonly {code.Name} = ({string.Join(',', code.Parameters.Select(p=> GetParameterSignature(p)).ToList())}) : Promise<{GetTypeString(code.ReturnType)}> => {{ return Promise.resolve({(code.ReturnType.Name.Equals("string") ? "''" : "{}")}); }}");
}

public override void WriteNamespaceDeclaration(CodeNamespace.BlockDeclaration code) => WriteLine();

public override void WriteNamespaceEnd(CodeNamespace.BlockEnd code) => WriteLine();

public override void WriteProperty(CodeProperty code)
{
WriteLine($"public {code.Name}?: {GetTypeString(code.Type)}");
}

public override void WriteType(CodeType code)
{
Write(GetTypeString(code), includeIndent: false);
}
}
}