Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,17 @@ Typewriter is a new solution for generating code files using the GraphODataTempl
* **-g**, **-generationmode**: Specifies the generation mode. The values can be: `Full`, `Metadata`, or `Files`. `Full` (default) generation mode produces the output code files by cleaning the input metadata, parsing the documentation, and adding annotations before generating the output files. `Metadata` generation mode produces an output metadata file by cleaning metadata, documentation parsing, and adding documentation annotations. `Files` generation mode produces code files from an input metadata and bypasses the cleaning, documentation parsing, and adding documentation annotations.
* **-f**, **-outputMetadataFileName**: The base output metadata filename. Only applicable for `-generationmode Metadata`. The default value is `cleanMetadataWithDescriptions` which is used with the value of the `-endpointVersion` to generate a metadata file named `cleanMetadataWithDescriptionsv1.0.xml`.
* **-e**, **-endpointVersion**: The endpoint version used when naming a metadata file. Expected values are `v1.0` and `beta`. Only applicable for `-generationmode Metadata`.
* **-p**, **-properties**: Specify properties to support generation logic in the T4 templates. Properties must take the form of *key-string:value-string*. Multiple properties can be specified by setting a space in between property. The only property currently supported is the *php.namespace* property to specify the generated model file namespace. This property is optional.

### Example typewriter usage

#### Generate TypeScript typings from a CSDL (metadata) file without cleaning or annotating the CSDL.
#### Generate TypeScript typings from a CSDL (metadata) file without cleaning or annotating the CSDL.

The output will go in to the `outputTypeScript` directory.

`.\typewriter.exe -v Info -m D:\cleanMetadataWithDescriptions_v10.xml -o outputTypeScript -l TypeScript -g Files`

#### Clean and annotate a metadata file with documentation annotations sourced from the documentation repo
#### Clean and annotate a metadata file with documentation annotations sourced from the documentation repo

The output metadata file will go in to the `output2` directory. The output metadata file will be named `cleanMetadataWithDescriptionsv1.0.xml` based on the default values.

Expand Down Expand Up @@ -144,7 +145,7 @@ The type of template.

#### Template Name

To set the name of the template using the `Name` format string. You can insert `<Class>`, `<Property>`, `<Method>`, and `<Container>` the values will be replaced by the names of the corresponding object. If you insert an item that doesn't exist it will be replaced with an empty string.
To set the name of the template using the `Name` format string. You can insert `<Class>`, `<Property>`, `<Method>`, and `<Container>` the values will be replaced by the names of the corresponding object. If you insert an item that doesn't exist it will be replaced with an empty string.
Note: You can also set the template name from inside the template by : `host.SetTemplateName("foo");`

#### Template Editing
Expand Down Expand Up @@ -174,9 +175,9 @@ There are currently several steps we take to form the metadata into one that wil
- Remove HasStream properties from ```onenotePage``` and ```onenoteEntityBaseModel```
- Add ```ContainsTarget="true"``` to navigation properties that do not have a corresponding EntitySet. This currently applies to navigation properties that contain plannerBucket, plannerTask, plannerPlan, and plannerDelta.
- Add long descriptions to types and properties from [docs](https://developer.microsoft.com/en-us/graph/docs/concepts/overview)

In order to build against metadata other than that stored in the [metadata](https://github.com/microsoftgraph/MSGraph-SDK-Code-Generator/tree/master/metadata) directory, you will need to perform the first four on this list.

## Contributing

Before we can accept your pull request, you'll need to electronically complete Microsoft's [Contributor License Agreement](https://cla.microsoft.com/). If you've done this for other Microsoft projects, then you're already covered.
Expand Down
14 changes: 12 additions & 2 deletions Templates/PHP/Model/ComplexType.php.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,24 @@
CustomT4Host host = (CustomT4Host) Host;
OdcmModel model = host.CurrentModel;
CodeWriterPHP writer = (CodeWriterPHP) host.CodeWriter;
TemplateWriterSettings settings = ConfigurationService.Settings;
OdcmClass complex = (OdcmClass)host.CurrentType;
String complexName = complex.Name.SanitizeEntityName();
string targetNamespace = @"Microsoft\Graph\Model";
String complexBaseName = "";
if (complex.Base != null)
complexBaseName = complex.Base.Name.SanitizeEntityName();

// TemplateWriterSettings.Properties are set at the Typewriter command line. Check the command line
// documentation for more information on how the TemplateWriterSettings.Properties is used.
if (settings.Properties.ContainsKey("php.namespace"))
{
targetNamespace = settings.Properties["php.namespace"];
}

#>
<#=writer.WriteHeader(writer.GetDocBlock(complexName.ToCheckedCase()))#>
namespace Microsoft\Graph\Model;
namespace <#=targetNamespace#>;
<#=writer.GetClassBlock(complexName.ToCheckedCase().ToString(), "Model")#>
<#
if (complex.Base != null) {
Expand Down Expand Up @@ -118,7 +128,7 @@ foreach(var property in complex.Properties.Where(prop => prop.Type.GetTypeString
public function get<#=propertyName.ToCheckedCase()#>()
{
if (array_key_exists("<#=property.Name.ToCamelize()#>", $this->_propDict)) {
if (is_a($this->_propDict["<#=property.Name.ToCamelize()#>"], "Microsoft\Graph\Model\<#=property.Type.GetTypeString()#>")) {
if (is_a($this->_propDict["<#=property.Name.ToCamelize()#>"], "<#=targetNamespace#>\<#=property.Type.GetTypeString()#>")) {
return $this->_propDict["<#=property.Name.ToCamelize()#>"];
} else {
<# if (property.Type.GetTypeString() == "\\GuzzleHttp\\Psr7\\Stream") { #>
Expand Down
14 changes: 12 additions & 2 deletions Templates/PHP/Model/EntityType.php.tt
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@ CodeWriterPHP writer = (CodeWriterPHP) host.CodeWriter;
OdcmClass entity = host.CurrentType.AsOdcmClass();
TemplateWriterSettings settings = ConfigurationService.Settings;
String entityName = entity.Name.SanitizeEntityName();
string targetNamespace = @"Microsoft\Graph\Model";
String entityBaseName = "";

if (entity.Base != null)
entityBaseName = entity.Base.Name.SanitizeEntityName();

// TemplateWriterSettings.Properties are set at the Typewriter command line. Check the command line
// documentation for more information on how the TemplateWriterSettings.Properties is used.
if (settings.Properties.ContainsKey("php.namespace"))
{
targetNamespace = settings.Properties["php.namespace"];
}

#>
<#=writer.WriteHeader(writer.GetDocBlock(entityName.ToCheckedCase()))#>
namespace Microsoft\Graph\Model;
namespace <#=targetNamespace#>;

<#=writer.GetClassBlock(entityName.ToCheckedCase().ToString(), "Model")#>
<#
Expand Down Expand Up @@ -122,7 +132,7 @@ foreach(var property in entity.Properties.Where(prop => prop.Type.GetTypeString(
if (property.Type.GetTypeString()[0] == '\\') { #>
if (is_a($this->_propDict["<#=property.Name.ToCamelize()#>"], "<#=property.Type.GetTypeString()#>")) {
<# } else { #>
if (is_a($this->_propDict["<#=property.Name.ToCamelize()#>"], "Microsoft\Graph\Model\<#=property.Type.GetTypeString()#>")) {
if (is_a($this->_propDict["<#=property.Name.ToCamelize()#>"], "<#=targetNamespace#>\<#=property.Type.GetTypeString()#>")) {
<# } #>
return $this->_propDict["<#=property.Name.ToCamelize()#>"];
} else {
Expand Down
19 changes: 14 additions & 5 deletions Templates/PHP/Model/EnumType.php.tt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@
<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension="\\" #>
<#
CustomT4Host host = (CustomT4Host) Host;
OdcmModel model = host.CurrentModel;
CodeWriterPHP writer = (CodeWriterPHP) host.CodeWriter;
CustomT4Host host = (CustomT4Host) Host;
OdcmModel model = host.CurrentModel;
CodeWriterPHP writer = (CodeWriterPHP) host.CodeWriter;
TemplateWriterSettings settings = ConfigurationService.Settings;
string targetNamespace = @"Microsoft\Graph\Model";
var enumT = host.CurrentType.AsOdcmEnum();

// TemplateWriterSettings.Properties are set at the Typewriter command line. Check the command line
// documentation for more information on how the TemplateWriterSettings.Properties is used.
if (settings.Properties.ContainsKey("php.namespace"))
{
targetNamespace = settings.Properties["php.namespace"];
}

var enumT = host.CurrentType.AsOdcmEnum();
#>
<#=writer.WriteHeader(writer.GetDocBlock(enumT.Name.ToCheckedCase()))#>
namespace Microsoft\Graph\Model;
namespace <#=targetNamespace#>;

use Microsoft\Graph\Core\Enum;

Expand Down
33 changes: 31 additions & 2 deletions src/GraphODataTemplateWriter/Settings/ConfigurationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,46 @@
namespace Microsoft.Graph.ODataTemplateWriter.Settings
{
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using Vipr.Core;

/// <summary>
/// The ConfigurationService configures the template writer with the target language and
/// other properties used to direct how the code files are generated.
/// </summary>
public static class ConfigurationService
{
private static IConfigurationProvider _configurationProvider;
private static TemplateWriterSettings templateWriterSettings = null;
private static string targetLanguage = null;
public static void Initialize(IConfigurationProvider configurationProvider, string targetLanguage = null)
private static Dictionary<string, string> properties = null;

public static void Initialize(IConfigurationProvider configurationProvider, string targetLanguage = null, IEnumerable<string> properties = null)
{
_configurationProvider = configurationProvider;
if (!String.IsNullOrEmpty(targetLanguage))
{
ConfigurationService.targetLanguage = targetLanguage;
}
if (properties != null)
{
Dictionary<string, string> propertyDictionary = new Dictionary<string, string>();
foreach (string property in properties)
{
string[] props = property.Split(':');

if (props.Length != 2)
{
throw new ArgumentException("A property was set in a unexpected form from the typewriter commandline.", "-p -properties");
}

propertyDictionary.Add(props[0],props[1]);
}

ConfigurationService.properties = propertyDictionary;
}
}

private static TemplateWriterSettings LoadSettingsForLanguage()
Expand All @@ -29,6 +53,11 @@ private static TemplateWriterSettings LoadSettingsForLanguage()
{
mainTWS.TargetLanguage = targetLanguage;
}
if (properties != null)
{
mainTWS.Properties = properties;
}


TemplateWriterSettings.mainSettingsObject = mainTWS;

Expand Down Expand Up @@ -72,7 +101,7 @@ public static TemplateWriterSettings Settings
{
get
{
if (templateWriterSettings == null)
if (templateWriterSettings == null || templateWriterSettings.TargetLanguage != ConfigurationService.targetLanguage)
{
templateWriterSettings = _configurationProvider != null
? LoadSettingsForLanguage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ public Dictionary<string, List<Dictionary<string, string>>> TemplateMapping

private readonly List<Dictionary<string, string>> templateConfiguration;

/// <summary>
/// A dictionary of strings that represent a property. These properties can be provided from the command line
/// and used in the templates.
/// </summary>
public Dictionary<string, string> Properties { get; set; }

/// <summary>
/// The dictionary created by combining the "Shared" and current language mapping.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,11 @@ public class TemplateProcessor : ITemplateProcessor

protected static CustomT4Host Host(ITemplateInfo templateInfo, string templatesDirectory, OdcmObject odcmObject, OdcmModel odcmModel)
{
if (_host == null)
{
_host = new CustomT4Host(templateInfo, templatesDirectory, odcmObject, odcmModel);
}
else
{
_host.Reset(templateInfo, templatesDirectory, odcmObject, odcmModel);
}
// Need to always set the host. Typically, this is run against a single platform when generating codefiels.
// In test cases, we need to target multiple platforms. Since much of this code is static, we need to make sure
// reset the information provided to the template processor. This change fixes a bug when targeting
// multiple platforms in a test.
_host = new CustomT4Host(templateInfo, templatesDirectory, odcmObject, odcmModel);

return _host;
}
Expand Down
33 changes: 20 additions & 13 deletions src/GraphODataTemplateWriter/TemplateProcessor/TemplateWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ public class TemplateWriter : IConfigurable, IOdcmWriter
private static Logger logger = LogManager.GetCurrentClassLogger();

private string pathWriterClassNameFormatString;

private string targetLanguage;
private IEnumerable<string> properties;

public TemplateWriter()
{
}

public TemplateWriter(string targetLanguage)
{
this.targetLanguage = targetLanguage;
}

public TemplateWriter(string targetLanguage, IEnumerable<string> properties)
{
this.targetLanguage = targetLanguage;
this.properties = properties;
}

private string PathWriterClassNameFormatString
{
get {
Expand Down Expand Up @@ -76,22 +95,10 @@ IEnumerable<TextFile> ProcessTemplates()
}
}

private string targetLanguage;

public TemplateWriter()
{

}

public TemplateWriter(string targetLanguage)
{
this.targetLanguage = targetLanguage;
}

// IConfigurationProvider
public void SetConfigurationProvider(IConfigurationProvider configurationProvider)
{
ConfigurationService.Initialize(configurationProvider, this.targetLanguage);
ConfigurationService.Initialize(configurationProvider, this.targetLanguage, this.properties);
FileNameCasing nameCasing;
if(!Enum.TryParse(ConfigurationService.Settings.DefaultFileCasing, out nameCasing))
{
Expand Down
6 changes: 3 additions & 3 deletions src/Typewriter/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal static class Generator
/// <param name="options">The options bag</param>
static internal void GenerateFiles(string csdlContents, Options options)
{
var filesToWrite = MetadataToClientSource(csdlContents, options.Language);
var filesToWrite = MetadataToClientSource(csdlContents, options.Language, options.Properties);
FileWriter.WriteAsync(filesToWrite, options.Output);
}

Expand Down Expand Up @@ -65,13 +65,13 @@ static private string CleanMetadata(string csdlContents, Options options)
/// <param name="edmxString">The EDMX file as a string.</param>
/// <param name="targetLanguage">Specifies the target language. Possible values are csharp, php, etc.</param>
/// <returns></returns>
static private IEnumerable<TextFile> MetadataToClientSource(string edmxString, string targetLanguage)
static private IEnumerable<TextFile> MetadataToClientSource(string edmxString, string targetLanguage, IEnumerable<string> properties)
{
if (String.IsNullOrEmpty(edmxString))
throw new ArgumentNullException("edmxString", "The EDMX file string contains no content.");

var reader = new OdcmReader();
var writer = new TemplateWriter(targetLanguage);
var writer = new TemplateWriter(targetLanguage, properties);
writer.SetConfigurationProvider(new ConfigurationProvider());

var model = reader.GenerateOdcmModel(new List<TextFile> { new TextFile("$metadata", edmxString) });
Expand Down
6 changes: 6 additions & 0 deletions src/Typewriter/Options.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CommandLine;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("GraphODataTemplateWriter.Test")]
Expand Down Expand Up @@ -60,5 +61,10 @@ public class Options

[Option('e', "endpointVersion", Default = "v1.0", HelpText = "The endpoint version. Expected values are 'v1.0' and 'beta'. Only applicable for GenerationMode.Metadata.")]
public string EndpointVersion { get; set; }

[Option('p', "properties", HelpText = "A space separated list of properties in the form of 'key:value'. These properties can be accessed in the " +
"templates from the TemplateWriterSettings object returned by ConfigurationService.Settings. The suggested convention for specifying a key should be " +
"the targeted template language name and the property name. For example, php.namespace:Microsoft\\Graph\\Beta\\Model would be a property to be consumed in the PHP templates.")]
public IEnumerable<string> Properties { get; set; }
}
}
38 changes: 0 additions & 38 deletions test/Typewriter.Test/GeneratorTests.cs

This file was deleted.

Loading