Skip to content

Commit

Permalink
Add feature: exclude type names in separate Window for C# client code…
Browse files Browse the repository at this point in the history
… generation.
  • Loading branch information
Chebotov Nikolay committed Feb 27, 2020
1 parent 4d09a8b commit 3a11cdf
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

These are the changes to each version that has been released on the official [Visual Studio extension gallery](https://marketplace.visualstudio.com/items?itemName=unchase.UnchaseOpenAPIConnectedService).

## v1.4.0 `(2020-02-27)`

- [x] Add feature: exclude type names in separate Window for C# client code generation

## v1.3.18 `(2020-02-13)`

- [x] Update dependencies: add support for [NSwag.Commands v13.2.3](https://github.com/RicoSuter/NSwag/pull/2661)
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ Meaning of the Unchase [OpenAPI (Swagger) Connected Service](https://marketplace

![Unchase OpenAPI (Swagger) Connected Service settings meaning](img/Unchase-OpenAPI-Swagger-Connected-Service-Settings-Meaning.png)

## Exclude type names

Since [v1.4.0](https://github.com/unchase/Unchase.OpenAPI.Connectedservice/releases/tag/v1.4.0) you can exclude type names in separate Window for C# client code generation:

![Unchase OpenAPI (Swagger) Connected Service - exclude type names](img/Csharp-Client-Generation-Exclude-Type-Names.png)

## Custom Commands

### `Open in NSwagStudio` Command
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 1.3.{build}
version: 1.4.{build}
pull_requests:
do_not_increment_build_number: true
skip_tags: true
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions src/CodeGeneration/NSwagCodeGenDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.VisualStudio.ConnectedServices;
using NSwag.Commands;
using NSwag.Commands.Generation;
using Unchase.OpenAPI.ConnectedService.Common;
using Unchase.OpenAPI.ConnectedService.Views;

namespace Unchase.OpenAPI.ConnectedService.CodeGeneration
{
Expand Down Expand Up @@ -173,6 +176,29 @@ internal async Task<string> GenerateCodeAsync(ConnectedServiceHandlerContext con
nswagJsonOutputPath = await context.HandlerHelper.AddFileAsync(nswagJsonTempFileName, nswagJsonOutputPath, new AddFileOptions { OpenOnComplete = instance.ServiceConfig.OpenGeneratedFilesOnComplete });
if (document.CodeGenerators?.OpenApiToCSharpClientCommand != null)
{
if (instance.ServiceConfig.ExcludeTypeNamesLater)
{
var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(File.ReadAllText(csharpClientTempFileName), CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Latest));
var root = await parsedSyntaxTree.GetRootAsync();
var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>().Where(c =>
c.AttributeLists.Any(a => a.Attributes.Any(at =>
at.ArgumentList.Arguments.Any(arg =>
arg.GetText().ToString().Contains("\"NJsonSchema\"")))));
var classNames = classes.Select(c => c.Identifier.Text);
var excludedClasses = new CSharpClientExcludedClasses(classNames);
if (excludedClasses.ShowDialog() == true)
{
var excludedClassNames = excludedClasses.Classes.Where(c => c.Excluded).Select(c => c.Name).ToArray();
if (excludedClassNames.Any())
{
await this.Context.Logger.WriteMessageAsync(LoggerMessageCategory.Information, "Regenerating client code with excluded classes...");
document.CodeGenerators.OpenApiToCSharpClientCommand.ExcludedTypeNames = excludedClassNames;
await document.ExecuteAsync();
await this.Context.Logger.WriteMessageAsync(LoggerMessageCategory.Information, "Generating client code with excluded classes is completed.");
}
}
}

await context.HandlerHelper.AddFileAsync(csharpClientTempFileName, csharpClientOutputPath,
new AddFileOptions { OpenOnComplete = instance.ServiceConfig.OpenGeneratedFilesOnComplete });
}
Expand Down
2 changes: 2 additions & 0 deletions src/Models/ServiceConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ internal class ServiceConfiguration

public OpenApiToCSharpClientCommand OpenApiToCSharpClientCommand { get; set; }

public bool ExcludeTypeNamesLater { get; set; }

public OpenApiToTypeScriptClientCommand OpenApiToTypeScriptClientCommand { get; set; }

public OpenApiToCSharpControllerCommand OpenApiToCSharpControllerCommand { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions src/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.2.*")]
[assembly: AssemblyVersion("1.3.18")]
[assembly: AssemblyFileVersion("1.3.18.0")]
[assembly: AssemblyVersion("1.4.0")]
[assembly: AssemblyFileVersion("1.4.0.0")]
[assembly: NeutralResourcesLanguage("en-US")]

24 changes: 21 additions & 3 deletions src/Unchase.OpenAPI.ConnectedService.csproj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\build\Microsoft.CodeAnalysis.Analyzers.props" Condition="Exists('packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\build\Microsoft.CodeAnalysis.Analyzers.props')" />
<Import Project="packages\Microsoft.Extensions.Configuration.UserSecrets.3.0.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props" Condition="Exists('packages\Microsoft.Extensions.Configuration.UserSecrets.3.0.0\build\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.props')" />
<Import Project="packages\Microsoft.VSSDK.BuildTools.15.9.3039\build\Microsoft.VSSDK.BuildTools.props" Condition="Exists('packages\Microsoft.VSSDK.BuildTools.15.9.3039\build\Microsoft.VSSDK.BuildTools.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -110,6 +111,9 @@
<Compile Include="ViewModels\ConfigOpenApiEndpointViewModel.cs" />
<Compile Include="ViewModels\CSharpControllerSettingsViewModel.cs" />
<Compile Include="ViewModels\TypeScriptClientSettingsViewModel.cs" />
<Compile Include="Views\CSharpClientExcludedClasses.xaml.cs">
<DependentUpon>CSharpClientExcludedClasses.xaml</DependentUpon>
</Compile>
<Compile Include="Views\CSharpClientSettings.xaml.cs">
<DependentUpon>CSharpClientSettings.xaml</DependentUpon>
</Compile>
Expand All @@ -132,6 +136,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Analyzer Include="packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\analyzers\dotnet\cs\Microsoft.CodeAnalysis.Analyzers.dll" />
<Analyzer Include="packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\analyzers\dotnet\cs\Microsoft.CodeAnalysis.CSharp.Analyzers.dll" />
<Analyzer Include="packages\Microsoft.VisualStudio.SDK.Analyzers.15.8.36\analyzers\cs\Microsoft.VisualStudio.SDK.Analyzers.dll" />
<Analyzer Include="packages\Microsoft.VisualStudio.Threading.Analyzers.15.8.168\analyzers\cs\Microsoft.VisualStudio.Threading.Analyzers.dll" />
</ItemGroup>
Expand Down Expand Up @@ -256,6 +262,12 @@
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.Bcl.AsyncInterfaces.1.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis, Version=3.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.CodeAnalysis.Common.3.4.0\lib\netstandard2.0\Microsoft.CodeAnalysis.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CodeAnalysis.CSharp, Version=3.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.CodeAnalysis.CSharp.3.4.0\lib\netstandard2.0\Microsoft.CodeAnalysis.CSharp.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.DotNet.PlatformAbstractions, Version=3.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.DotNet.PlatformAbstractions.3.0.0\lib\net45\Microsoft.DotNet.PlatformAbstractions.dll</HintPath>
Expand Down Expand Up @@ -509,9 +521,7 @@
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Collections.Immutable.1.6.0\lib\netstandard2.0\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Collections.Immutable, Version=1.2.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<Reference Include="System.ComponentModel.Annotations, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.ComponentModel.Annotations.4.6.0\lib\net461\System.ComponentModel.Annotations.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -574,6 +584,9 @@
<Reference Include="System.Security.Principal.Windows, Version=4.1.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Security.Principal.Windows.4.6.0\lib\net461\System.Security.Principal.Windows.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encoding.CodePages, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>packages\System.Text.Encoding.CodePages.4.5.1\lib\net461\System.Text.Encoding.CodePages.dll</HintPath>
</Reference>
<Reference Include="System.Text.Encodings.Web, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>packages\System.Text.Encodings.Web.4.6.0\lib\netstandard2.0\System.Text.Encodings.Web.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -637,6 +650,10 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Page Include="Views\CSharpClientExcludedClasses.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\CSharpClientSettings.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
Expand Down Expand Up @@ -684,6 +701,7 @@
<Error Condition="!Exists('packages\Microsoft.AspNetCore.Server.IISIntegration.2.2.1\build\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.AspNetCore.Server.IISIntegration.2.2.1\build\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.targets'))" />
<Error Condition="!Exists('packages\Microsoft.VisualStudio.SDK.EmbedInteropTypes.15.0.27\build\Microsoft.VisualStudio.SDK.EmbedInteropTypes.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.VisualStudio.SDK.EmbedInteropTypes.15.0.27\build\Microsoft.VisualStudio.SDK.EmbedInteropTypes.targets'))" />
<Error Condition="!Exists('packages\Microsoft.VisualStudio.SDK.VsixSuppression.14.1.37\build\Microsoft.VisualStudio.SDK.VsixSuppression.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.VisualStudio.SDK.VsixSuppression.14.1.37\build\Microsoft.VisualStudio.SDK.VsixSuppression.targets'))" />
<Error Condition="!Exists('packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\build\Microsoft.CodeAnalysis.Analyzers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.CodeAnalysis.Analyzers.2.9.6\build\Microsoft.CodeAnalysis.Analyzers.props'))" />
</Target>
<Import Project="packages\NuGet.VisualStudio.4.9.4\build\NuGet.VisualStudio.targets" Condition="Exists('packages\NuGet.VisualStudio.4.9.4\build\NuGet.VisualStudio.targets')" />
<Import Project="packages\Microsoft.VisualStudio.Threading.Analyzers.15.8.168\build\Microsoft.VisualStudio.Threading.Analyzers.targets" Condition="Exists('packages\Microsoft.VisualStudio.Threading.Analyzers.15.8.168\build\Microsoft.VisualStudio.Threading.Analyzers.targets')" />
Expand Down
2 changes: 2 additions & 0 deletions src/ViewModels/CSharpClientSettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ internal class CSharpClientSettingsViewModel : ConnectedServiceWizardPage
public CSharpClassStyle[] ClassStyles { get; } = Enum.GetNames(typeof(CSharpClassStyle))
.Select(t => (CSharpClassStyle)Enum.Parse(typeof(CSharpClassStyle), t))
.ToArray();

public bool ExcludeTypeNamesLater { get; set; }
#endregion

#region Constructors
Expand Down
46 changes: 46 additions & 0 deletions src/Views/CSharpClientExcludedClasses.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<Window x:Class="Unchase.OpenAPI.ConnectedService.Views.CSharpClientExcludedClasses"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Title="Exclude types from generation"
mc:Ignorable="d"
Width="400"
Height="370"
MaxHeight="370"
MaxWidth="400"
WindowStartupLocation="CenterOwner"
d:DesignHeight="370" d:DesignWidth="400">
<StackPanel>
<TextBlock Margin="5" Text="Choose types to exclude from generation : "/>
<ListBox
x:Name="ExcludedClassesListBox"
MinHeight="275"
MaxHeight="275"
VerticalContentAlignment="Center"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Visibility="Visible">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel VerticalAlignment="Center" Orientation="Horizontal">
<CheckBox
Width="16"
Margin="0,5,8,0"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
IsChecked="{Binding Path=Excluded, Mode=TwoWay}" />
<TextBlock
Margin="0,5,8,0"
FontSize="12"
Foreground="CornflowerBlue"
Text="{Binding Path=Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="ApplyButton" Margin="5" Width="100" HorizontalAlignment="Right" Click="ApplyButton_Click">
<TextBlock Text="Apply"/>
</Button>
</StackPanel>
</Window>
50 changes: 50 additions & 0 deletions src/Views/CSharpClientExcludedClasses.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//-----------------------------------------------------------------------
// <copyright file="CSharpClientExcludedClasses.cs" company="Unchase">
// Copyright (c) Nikolay Chebotov (Unchase). All rights reserved.
// </copyright>
// <license>https://github.com/unchase/Unchase.OpenAPI.Connectedservice/blob/master/LICENSE.md</license>
// <author>Nickolay Chebotov (Unchase), spiritkola@hotmail.com</author>
//-----------------------------------------------------------------------

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace Unchase.OpenAPI.ConnectedService.Views
{
/// <summary>
/// Логика взаимодействия для CSharpClientExcludedClasses.xaml
/// </summary>
public partial class CSharpClientExcludedClasses : Window
{
public ObservableCollection<Class> Classes { get; set; }

public class Class
{
public string Name { get; set; }

public bool Excluded { get; set; }
}

public CSharpClientExcludedClasses(IEnumerable<string> classNames)
{
InitializeComponent();
Classes = new ObservableCollection<Class>();
foreach (var className in classNames)
{
Classes.Add(new Class
{
Name = className,
Excluded = false
});
}
ExcludedClassesListBox.ItemsSource = Classes;
}

private void ApplyButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
this.Close();
}
}
}
4 changes: 4 additions & 0 deletions src/Views/CSharpClientSettings.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@
<TextBlock Text="Generate DTO Types (e.g. request and response classes)" ToolTip="GenerateDtoTypes" TextWrapping="Wrap" />
</CheckBox>
<StackPanel Visibility="{Binding Command.GenerateDtoTypes, Converter={StaticResource VisibilityConverter}}" Margin="20,0,0,0">
<CheckBox IsChecked="{Binding ExcludeTypeNamesLater, Mode=TwoWay}"
ToolTip="ExcludeTypeNamesLater" Margin="0, 5, 10, 5">
<TextBlock Text="Exclude type names later (in a separated window)." TextWrapping="Wrap" />
</CheckBox>
<TextBlock TextWrapping="WrapWithOverflow" Text="Excluded Type Names (comma separated, must be defined in another namespace) :" FontWeight="Bold" Margin="0, 5, 0, 0"/>
<TextBox Text="{Binding Command.ExcludedTypeNames, Mode=TwoWay, Converter={StaticResource StringArrayConverter}, ConverterParameter=','}"
ToolTip="ExcludedTypeNames"
Expand Down
1 change: 0 additions & 1 deletion src/Views/CSharpClientSettings.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Windows.Controls;
using Unchase.OpenAPI.ConnectedService.ViewModels;

namespace Unchase.OpenAPI.ConnectedService.Views
{
Expand Down
4 changes: 4 additions & 0 deletions src/Wizard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ public Wizard(ConnectedServiceProviderContext context)
}

CSharpClientSettingsViewModel.Command = serviceConfig.OpenApiToCSharpClientCommand;
CSharpClientSettingsViewModel.ExcludeTypeNamesLater = serviceConfig.ExcludeTypeNamesLater;
CSharpClientSettingsViewModel.Description = "Settings for generating CSharp client (regenerated)";
TypeScriptClientSettingsViewModel.Command = serviceConfig.OpenApiToTypeScriptClientCommand;
TypeScriptClientSettingsViewModel.Description = "Settings for generating TypeScript client (regenerated)";
Expand Down Expand Up @@ -186,7 +187,10 @@ private ServiceConfiguration CreateServiceConfiguration()
UseRelativePath = ConfigOpenApiEndpointViewModel.UserSettings.UseRelativePath
};
if (serviceConfiguration.GenerateCSharpClient && CSharpClientSettingsViewModel.Command != null)
{
serviceConfiguration.OpenApiToCSharpClientCommand = CSharpClientSettingsViewModel.Command;
serviceConfiguration.ExcludeTypeNamesLater = CSharpClientSettingsViewModel.ExcludeTypeNamesLater;
}

if (serviceConfiguration.GenerateTypeScriptClient && TypeScriptClientSettingsViewModel.Command != null)
serviceConfiguration.OpenApiToTypeScriptClientCommand = TypeScriptClientSettingsViewModel.Command;
Expand Down
Loading

0 comments on commit 3a11cdf

Please sign in to comment.