23 Commits

Author SHA1 Message Date
Christian Resma Helle b3e385577f Merge pull request #3 from christianhelle/vs2017
Visual Studio 2017 Support
2017-11-09 23:55:20 +01:00
Christian Helle 2e0257cc25 Generate sealed class for windows runtime library compatibility 2017-11-09 23:42:13 +01:00
Christian Helle 0559618286 Change project URL since Codeplex is shutting down 2017-11-09 21:53:58 +01:00
Christian Helle 576430e2f0 Create new Visual Studio 2017 solution 2017-11-09 09:53:29 +01:00
Christian Helle 5c9966f004 Add Visual Studio .gitignore 2017-11-09 09:50:31 +01:00
Christian Helle 0d3cfefad5 Remove packages folder from source repo 2017-11-09 09:48:23 +01:00
Christian Helle 7856f0465d Move legacy VS2013 solution folder 2017-11-09 09:47:38 +01:00
Christian Resma Helle 3cdf0c0f7e Delete .hgignore 2017-11-09 08:27:55 +01:00
Christian Resma Helle e6840a916c Update README.md 2017-11-08 09:50:19 +01:00
Christian Resma Helle dacf37f0cf Update README.md 2017-11-08 09:49:38 +01:00
Christian Resma Helle 6e2077d23e Update README.md 2017-11-08 09:46:25 +01:00
Christian Resma Helle 98e0c1a891 Create README.md 2017-11-08 09:43:17 +01:00
Christian Resma Helle d1e8535fe4 Update VSIX manifest. Update version number and use version 14 to represent Visual Studio 2015 2015-05-16 21:28:43 +02:00
Christian Resma Helle 483c80d810 Use version 14 for Visual Studio 2015 2015-05-16 21:28:06 +02:00
Christian Resma Helle 622b5e979a Fix strings 2015-05-16 21:25:32 +02:00
Christian Resma Helle 8596be7e07 Add support for Visual Studio 2015 2015-03-10 07:56:41 +01:00
Christian Resma Helle 5c96d8c0c9 Initial effort for supporting for Visual Studio 2015 (experimental) 2015-03-08 21:48:52 +01:00
Christian Resma Helle 88e43bc7e8 Add Ignore rule for UpdateLog.htm 2014-04-24 10:03:30 +02:00
Christian Resma Helle 416616e8f0 Added tag v1.3 for changeset be8dca5b02ff 2014-04-24 10:03:05 +02:00
Christian Resma Helle 072e33e997 v1.3 2014-04-24 10:02:54 +02:00
Christian Resma Helle 8002e34eca Tests 2014-04-24 10:02:35 +02:00
Christian Resma Helle d189fb69d6 Add support for detecting the Visual Studio version 2014-04-24 10:02:14 +02:00
Christian Resma Helle ebb510ea2e Added tag v1.2 for changeset 6548c4df20be 2013-10-24 00:08:42 +02:00
116 changed files with 2686 additions and 16085 deletions
+305
View File
@@ -0,0 +1,305 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
-8
View File
@@ -1,8 +0,0 @@
syntax: glob
*/bin/*
*/obj/*
*/TestResults/*
*.suo
*.user
*ReSharper*
*/Setup/Setup/*
+189
View File
@@ -0,0 +1,189 @@
# ResW File Code Generator
A Visual Studio Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.
**Features**
- Define custom namespace for the generated file
- Auto-updating of generated code file when changes are made to the .ResW Resource file
- XML documentation style comments like "Localized resource similar to '[the value]'"
**Custom Tools**
- ReswFileCodeGenerator - Generates a public class
- InternalReswFileCodeGenerator - Generates an internal (C#) / friend (VB) class
**Supported Languages**
- C#
- Visual Basic
**Screenshots**
![alt text](http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=527605)
- Visual Studio Custom Tool (C#)
![alt text](http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=528704)
- Visual Studio Custom Tool (VB)
![alt text](http://www.codeplex.com/Download?ProjectName=reswcodegen&DownloadId=527606)
- Resource File Contents
**C# Usage**
string test1, test2, test3;
void LoadLocalizedStrings()
{
test1 = App1.LocalizedResources.Resources.Test1;
test2 = App1.LocalizedResources.Resources.Test2;
test3 = App1.LocalizedResources.Resources.Test3;
}
**VB Usage**
Dim test1, test2, test3
Private Sub LoadLocalizedStrings()
test1 = AppVb.LocalizedStrings.Resources.Test1
test2 = AppVb.LocalizedStrings.Resources.Test2
test3 = AppVb.LocalizedStrings.Resources.Test3
End Sub
**Generated C# Code**
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18010
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------
// <auto-generatedInfo>
// This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
// ResW File Code Generator was written by Christian Resma Helle
// and is under GNU General Public License version 2 (GPLv2)
//
// This code contains a helper class exposing property representations
// of the string resources defined in the specified .ResW file
//
// Generated: 11/08/2012 22:41:22
// </auto-generatedInfo>
// --------------------------------------------------------------------------------------------------
namespace App1.LocalizedResources
{
using Windows.ApplicationModel.Resources;
public partial class Resources
{
private static ResourceLoader resourceLoader = new ResourceLoader();
/// <summary>
/// Localized resource similar to "Test 1 value"
/// </summary>
public static string Test1
{
get
{
return resourceLoader.GetString("Test1");
}
}
/// <summary>
/// Localized resource similar to "Test 2 value"
/// </summary>
public static string Test2
{
get
{
return resourceLoader.GetString("Test2");
}
}
/// <summary>
/// Localized resource similar to "Test 3 value"
/// </summary>
public static string Test3
{
get
{
return resourceLoader.GetString("Test3");
}
}
}
}
**Generated Visual Basic Code**
' <auto-generated>
' This code was generated by a tool.
' Runtime Version:4.0.30319.18010
'
' Changes to this file may cause incorrect behavior and will be lost if
' the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------
Option Strict Off
Option Explicit On
Imports Windows.ApplicationModel.Resources
'--------------------------------------------------------------------------------------------------
'<auto-generatedInfo>
' This code was generated by ResW File Code Generator (http://reswcodegen.codeplex.com)
' ResW File Code Generator was written by Christian Resma Helle
' and is under GNU General Public License version 2 (GPLv2)
'
' This code contains a helper class exposing property representations
' of the string resources defined in the specified .ResW file
'
' Generated: 11/12/2012 21:30:52
'</auto-generatedInfo>
'--------------------------------------------------------------------------------------------------
Namespace AppVb.LocalizedStrings
Partial Public Class Resources
Private Shared resourceLoader As ResourceLoader = New ResourceLoader()
'''<summary>
'''Localized resource similar to "Test 1 value"
'''</summary>
Public Shared ReadOnly Property Test1() As String
Get
Return resourceLoader.GetString("Test1")
End Get
End Property
'''<summary>
'''Localized resource similar to "Test 2 value"
'''</summary>
Public Shared ReadOnly Property Test2() As String
Get
Return resourceLoader.GetString("Test2")
End Get
End Property
'''<summary>
'''Localized resource similar to "Test 3 value"
'''</summary>
Public Shared ReadOnly Property Test3() As String
Get
Return resourceLoader.GetString("Test3")
End Get
End Property
End Class
End Namespace
@@ -1,14 +0,0 @@
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeGeneratorFactory
{
public ICodeGenerator Create(string className, string defaultNamespace, string inputFileContents, CodeDomProvider codeDomProvider = null, TypeAttributes? classAccessibility = null)
{
return new CodeDomCodeGenerator(new ResourceParser(inputFileContents), className, defaultNamespace, codeDomProvider, classAccessibility);
}
}
}
@@ -1,39 +0,0 @@
Copyright (c) 2007. Clarius Consulting, Manas Technology Solutions, InSTEDD
http://code.google.com/p/moq/
All rights reserved.
Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:
* Redistributions of source code must retain the
above copyright notice, this list of conditions and
the following disclaimer.
* Redistributions in binary form must reproduce
the above copyright notice, this list of conditions
and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of Clarius Consulting, Manas Technology Solutions or InSTEDD nor the
names of its contributors may be used to endorse
or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
[This is the BSD license, see
http://www.opensource.org/licenses/bsd-license.php]
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<repositories>
<repository path="..\ReswCodeGen.Tests\packages.config" />
</repositories>
@@ -1,18 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReswCodeGen.Tests", "ReswCodeGen.Tests\ReswCodeGen.Tests.csproj", "{B56DDC92-E86D-46AA-BE28-7ACA670EE9CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage", "VSPackage\VSPackage.csproj", "{2451352F-1CB8-494A-920B-024B8B486185}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage_IntegrationTests", "VSPackage\VSPackage_IntegrationTests\VSPackage_IntegrationTests.csproj", "{D03690D8-EE17-4284-9403-F3F277CF4580}"
EndProject
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{91EF78EF-DAB6-4031-AA01-3D127F1E0BCD}"
ProjectSection(SolutionItems) = preProject
IntegrationTests.testsettings = IntegrationTests.testsettings
UnitTests.testsettings = UnitTests.testsettings
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReswCodeGen.Tests", "ReswCodeGen.Tests\ReswCodeGen.Tests.csproj", "{B56DDC92-E86D-46AA-BE28-7ACA670EE9CE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage", "VSPackage\VSPackage.csproj", "{2451352F-1CB8-494A-920B-024B8B486185}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage_IntegrationTests", "VSPackage\VSPackage_IntegrationTests\VSPackage_IntegrationTests.csproj", "{D03690D8-EE17-4284-9403-F3F277CF4580}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage_UnitTests", "VSPackage\VSPackage_UnitTests\VSPackage_UnitTests.csproj", "{64F7EAFB-9AF1-4DA4-A4DA-013B4DF10306}"
EndProject
Global
@@ -0,0 +1,33 @@
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeGeneratorFactory
{
public ICodeGenerator Create(string className, string defaultNamespace, string inputFileContents, CodeDomProvider codeDomProvider = null, TypeAttributes? classAccessibility = null)
{
return new CodeDomCodeGenerator(new ResourceParser(inputFileContents), className, defaultNamespace, codeDomProvider, classAccessibility, VisualStudioHelper.GetVersion());
}
}
public static class VisualStudioHelper
{
public static VisualStudioVersion GetVersion()
{
var dte = Package.GetGlobalService(typeof(SDTE)) as DTE;
var vsVersion = VisualStudioVersion.VS2012;
if (dte != null)
{
Version dteVersion;
if (Version.TryParse(dte.Version, out dteVersion) && dteVersion >= new Version(12, 0))
vsVersion = VisualStudioVersion.VS2013;
}
return vsVersion;
}
}
}
@@ -0,0 +1,9 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public enum VisualStudioVersion
{
VS2012,
VS2013,
Unknown
}
}
@@ -29,7 +29,7 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.2.0.*")]
[assembly: AssemblyVersion("1.3.0.*")]
[assembly: InternalsVisibleTo("VSPackage_IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010045bd05a5b24c74b83f069df52e138682c2fb8b1ee65cb9d351fd7e8d622308aeb588b2a2975d75da4fe8a392510528baa26a3317809ec064d3cc852f0df94752ad2228d9f2a048ee2858c1e9d505b05f7fb4ede02f34154f75ea50445741c84f5ab1c814358f5fd6a6f08bb3d94284cff0524d5ca9d888c8648bcbc7a1e0a3c8")]
[assembly: InternalsVisibleTo("VSPackage_UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010045bd05a5b24c74b83f069df52e138682c2fb8b1ee65cb9d351fd7e8d622308aeb588b2a2975d75da4fe8a392510528baa26a3317809ec064d3cc852f0df94752ad2228d9f2a048ee2858c1e9d505b05f7fb4ede02f34154f75ea50445741c84f5ab1c814358f5fd6a6f08bb3d94284cff0524d5ca9d888c8648bcbc7a1e0a3c8")]
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.18033
// Runtime Version:4.0.30319.34014
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -1,9 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
<MinimumVisualStudioVersion>12.0</MinimumVisualStudioVersion>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>4.0</OldToolsVersion>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
@@ -120,6 +140,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CustomTool\VisualStudioVersion.cs" />
<Compile Include="VisualStudio2015Package.cs" />
<Compile Include="VisualStudio2013Package.cs" />
<Compile Include="CustomTool\ClassNameExtractor.cs" />
<Compile Include="CustomTool\CodeDomCodeGenerator.cs" />
@@ -174,6 +195,23 @@
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<PropertyGroup>
<UseCodebase>true</UseCodebase>
</PropertyGroup>
@@ -1,14 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
VS SDK Notes: This resx file contains the resources that will be consumed from your package by Visual Studio.
For example, Visual Studio will attempt to load resource '400' from this resource stream when it needs to
load your package's icon. Because Visual Studio will always look in the VSPackage.resources stream first for
resources it needs, you should put additional resources that Visual Studio will load directly into this resx
file.
Resources that you would like to access directly from your package in a strong-typed fashion should be stored
in Resources.resx or another resx file.
-->
<root>
<!--
Microsoft ResX Schema
@@ -127,13 +117,13 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="110" xml:space="preserve">
<value>ResW File Code Generator</value>
</data>
<data name="112" xml:space="preserve">
<value>Information about my packageA Visual Studio 2012 Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.</value>
<value>A Visual Studio Custom Tool for generating a strongly typed helper class for accessing localized resources from a .ResW file.</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="400" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\Package.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@@ -66,6 +66,7 @@
<Compile Include="SignOff-Tests\CSharpProjectTests.cs" />
<Compile Include="SignOff-Tests\SolutionTests.cs" />
<Compile Include="SignOff-Tests\VBProjectTests.cs" />
<Compile Include="VisualStudioVersionHelperTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Key.snk" />
@@ -0,0 +1,16 @@
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace VSPackage_IntegrationTests
{
[TestClass]
public class VisualStudioHelperTests
{
[TestMethod]
public void GetVersionTests()
{
var actual = VisualStudioHelper.GetVersion();
Assert.AreNotEqual(VisualStudioVersion.Unknown, actual);
}
}
}
@@ -0,0 +1,70 @@
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Design.Serialization;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage
{
/// <summary>
/// This is the class that implements the package exposed by this assembly.
///
/// The minimum requirement for a class to be considered a valid package for Visual Studio
/// is to implement the IVsPackage interface and register itself with the shell.
/// This package uses the helper classes defined inside the Managed Package Framework (MPF)
/// to do it: it derives from the Package class that provides the implementation of the
/// IVsPackage interface and uses the registration attributes defined in the framework to
/// register itself and its components with the shell.
/// </summary>
// This attribute tells the PkgDef creation utility (CreatePkgDef.exe) that this class is
// a package.
[PackageRegistration(UseManagedResourcesOnly = true)]
// This attribute is used to register the information needed to show this package
// in the Help/About dialog of Visual Studio.
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[Guid(GuidList.guidVSPackagePkgString)]
[DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\14.0")]
[ProvideObject(typeof(ReswFileCSharpCodeGenerator))]
[ProvideObject(typeof(ReswFileVisualBasicCodeGenerator))]
[ProvideObject(typeof(ReswFileCSharpCodeGeneratorInternal))]
[ProvideObject(typeof(ReswFileVisualBasicCodeGeneratorInternal))]
[ProvideGeneratorAttribute(typeof(ReswFileCSharpCodeGenerator), "ReswFileCodeGenerator", "ResW File Code Generator for C#", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", true)] // csharp
[ProvideGeneratorAttribute(typeof(ReswFileVisualBasicCodeGenerator), "ReswFileCodeGenerator", "ResW File Code Generator for VB", "{164B10B9-B200-11D0-8C61-00A0C91E29D5}", true)] // visual basic
[ProvideGeneratorAttribute(typeof(ReswFileCSharpCodeGenerator), "PublicReswFileCodeGenerator", "ResW File Code Generator for C#", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", true)] // csharp
[ProvideGeneratorAttribute(typeof(ReswFileVisualBasicCodeGenerator), "PublicReswFileCodeGenerator", "ResW File Code Generator for VB", "{164B10B9-B200-11D0-8C61-00A0C91E29D5}", true)] // visual basic
[ProvideGeneratorAttribute(typeof(ReswFileCSharpCodeGeneratorInternal), "InternalReswFileCodeGenerator", "ResW File Code Generator for C#", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", true)] // csharp
[ProvideGeneratorAttribute(typeof(ReswFileVisualBasicCodeGeneratorInternal), "InternalReswFileCodeGenerator", "ResW File Code Generator for VB", "{164B10B9-B200-11D0-8C61-00A0C91E29D5}", true)] // visual basic
public sealed class VisualStudio2015Package : Package
{
/// <summary>
/// Default constructor of the package.
/// Inside this method you can place any initialization code that does not require
/// any Visual Studio service because at this point the package object is created but
/// not sited yet inside Visual Studio environment. The place to do all the other
/// initialization is the Initialize method.
/// </summary>
public VisualStudio2015Package()
{
Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
/////////////////////////////////////////////////////////////////////////////
// Overridden Package Implementation
#region Package Members
/// <summary>
/// Initialization of the package; this method is called right after the package is sited, so this is the place
/// where you can put all the initialization code that rely on services provided by VisualStudio.
/// </summary>
protected override void Initialize()
{
Debug.WriteLine (string.Format(CultureInfo.CurrentCulture, "Entering Initialize() of: {0}", this.ToString()));
base.Initialize();
}
#endregion
}
}
@@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="6a4c1726-440f-4b2d-a2e5-711277da6099"
Version="1.1"
Version="1.4"
Language="en-US"
Publisher="Christian Resma Helle" />
<DisplayName>ResW File Code Generator</DisplayName>
@@ -13,7 +13,7 @@
<License>License.txt</License>
</Metadata>
<Installation InstalledByMsi="false">
<InstallationTarget Version="[11.0,12.0]" Id="Microsoft.VisualStudio.IntegratedShell" />
<InstallationTarget Version="[11.0,14.0]" Id="Microsoft.VisualStudio.IntegratedShell" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP"
+31
View File
@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2006
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage", "VSPackage\VSPackage.csproj", "{05F77BFB-CE11-4948-8174-F938C5B7F31C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSPackage.Tests", "VSPackage.Tests\VSPackage.Tests.csproj", "{F2B82735-4AE9-4365-8C0D-8391564359AB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{05F77BFB-CE11-4948-8174-F938C5B7F31C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05F77BFB-CE11-4948-8174-F938C5B7F31C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05F77BFB-CE11-4948-8174-F938C5B7F31C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05F77BFB-CE11-4948-8174-F938C5B7F31C}.Release|Any CPU.Build.0 = Release|Any CPU
{F2B82735-4AE9-4365-8C0D-8391564359AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F2B82735-4AE9-4365-8C0D-8391564359AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F2B82735-4AE9-4365-8C0D-8391564359AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F2B82735-4AE9-4365-8C0D-8391564359AB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FEC256E9-B961-4967-9948-F508DA7BF817}
EndGlobalSection
EndGlobal
@@ -0,0 +1,74 @@
using System.IO;
using System.Linq;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class CSharpCodeGeneratorTests
{
private string reswFileContents;
private const string FILE_PATH = "Resources.resw";
private string actual;
private ICodeGenerator target;
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText(FILE_PATH);
target = new CodeGeneratorFactory().Create(FILE_PATH.Replace(".resw", string.Empty), "TestApp", reswFileContents);
actual = target.GenerateCode();
}
[TestMethod]
public void GenerateCodeDoesNotReturnNull()
{
Assert.IsNotNull(actual);
}
[TestMethod]
public void GeneratedCodeIsAPublicClass()
{
Assert.IsTrue(actual.Contains("public sealed partial class"));
}
[TestMethod]
public void GeneratedCodeContainsPropertiesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("public static string " + item.Name));
}
[TestMethod]
public void GeneratedCodePropertiesContainsCommentsSimilarToValuesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Localized resource similar to \"" + item.Value + "\""));
}
[TestMethod]
public void ClassNameEqualsFileNameWithoutExtension()
{
Assert.IsTrue(actual.Contains("class Resources"));
}
[TestMethod]
public void ResourceLoaderInitializedWithClassName()
{
Assert.IsTrue(actual.Contains("new ResourceLoader(currentAssemblyName + \"/Resources\");"));
}
[TestMethod]
public void ContainsProjectUrl()
{
Assert.IsTrue(actual.Contains("http://bit.ly/reswcodegen"));
}
}
}
@@ -0,0 +1,75 @@
using System.IO;
using System.Linq;
using System.Reflection;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class CSharpCodeGeneratorTestsInternal
{
private string reswFileContents;
private const string FILE_PATH = "Resources.resw";
private string actual;
private ICodeGenerator target;
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText(FILE_PATH);
target = new CodeGeneratorFactory().Create(FILE_PATH.Replace(".resw", string.Empty), "TestApp", reswFileContents, classAccessibility: TypeAttributes.NestedAssembly);
actual = target.GenerateCode();
}
[TestMethod]
public void GenerateCodeDoesNotReturnNull()
{
Assert.IsNotNull(actual);
}
[TestMethod]
public void GeneratedCodeIsAnInternalClass()
{
Assert.IsTrue(actual.Contains("internal sealed partial class"));
}
[TestMethod]
public void GeneratedCodeContainsPropertiesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("public static string " + item.Name));
}
[TestMethod]
public void GeneratedCodePropertiesContainsCommentsSimilarToValuesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Localized resource similar to \"" + item.Value + "\""));
}
[TestMethod]
public void ClassNameEqualsFileNameWithoutExtension()
{
Assert.IsTrue(actual.Contains("class Resources"));
}
[TestMethod]
public void ResourceLoaderInitializedWithClassName()
{
Assert.IsTrue(actual.Contains("new ResourceLoader(currentAssemblyName + \"/Resources\");"));
}
[TestMethod]
public void ContainsProjectUrl()
{
Assert.IsTrue(actual.Contains("http://bit.ly/reswcodegen"));
}
}
}
@@ -0,0 +1,34 @@
using System.IO;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class ClassNameExtractorTests
{
private const string ClassName = "Resources.resw";
[TestMethod]
public void DoesNotReturnNull()
{
var actual = ClassNameExtractor.GetClassName(ClassName);
Assert.IsNotNull(actual);
}
[TestMethod]
public void ReturnsFileNameWithoutExtension()
{
var actual = ClassNameExtractor.GetClassName(ClassName);
Assert.AreEqual("Resources", actual);
}
[TestMethod]
[ExpectedException(typeof(FileNotFoundException))]
public void ThrowsFileNotFoundException()
{
ClassNameExtractor.GetClassName("C:\\Test\\Resources\\Strings.resw");
}
}
}
@@ -0,0 +1,28 @@
using System.IO;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Valid/Resources.resw")]
public class CodeGeneratorFactoryTests
{
private string reswFileContents;
private const string CLASS_NAME = "C:\\Test\\Resources\\Strings.resw";
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText("Resources.resw");
}
[TestMethod]
public void CodeGeneratorFactoryReturnsValidInstance()
{
var target = new CodeGeneratorFactory();
var actual = target.Create(CLASS_NAME, "TestApp", reswFileContents);
Assert.IsNotNull(actual);
}
}
}
@@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("VSPackage.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VSPackage.Tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("f2b82735-4ae9-4365-8c0d-8391564359ab")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,62 @@
using System.IO;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/ResourcesWithoutValues.resw")]
[DeploymentItem("Resources/ResourcesWithoutComments.resw")]
public class ResourceParserErrorHandlingTests
{
[TestMethod]
public void ParseHandlesMissingResourceItemValues()
{
var reswFileContents = File.ReadAllText("ResourcesWithoutValues.resw");
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual);
}
[TestMethod]
public void ParseWithMissingResourceItemValuesSetsValueNull()
{
var reswFileContents = File.ReadAllText("ResourcesWithoutValues.resw");
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual);
foreach (var item in actual)
Assert.IsTrue(string.IsNullOrEmpty(item.Value));
}
[TestMethod]
public void ParseHandlesMissingResourceItemComments()
{
var reswFileContents = File.ReadAllText("ResourcesWithoutComments.resw");
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual);
}
[TestMethod]
public void ParseWithMissingResourceItemCommentsSetsCommentsNull()
{
var reswFileContents = File.ReadAllText("ResourcesWithoutComments.resw");
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
Assert.IsNotNull(actual);
CollectionAssert.AllItemsAreNotNull(actual);
foreach (var item in actual)
Assert.IsTrue(string.IsNullOrEmpty(item.Comment));
}
}
}
@@ -0,0 +1,88 @@
using System.IO;
using System.Linq;
using System.Xml.Linq;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class ResourceParserTests
{
private string reswFileContents;
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText("Resources.resw");
}
[TestMethod]
public void CanLoadTestReswFileContents()
{
Assert.IsNotNull(reswFileContents);
}
[TestMethod]
public void CanTestReswFileContentsLoadToXDocument()
{
var doc = XDocument.Parse(reswFileContents);
Assert.IsNotNull(doc);
}
[TestMethod]
public void CanParseTestReswFileContents()
{
var doc = XDocument.Parse(reswFileContents);
var resourcs = doc.Descendants("data");
Assert.IsNotNull(resourcs);
Assert.AreNotEqual(0, resourcs.Count());
}
[TestMethod]
public void ConstructorSetsReswFileContents()
{
var target = new ResourceParser(reswFileContents);
Assert.IsNotNull(target.ReswFileContents);
}
[TestMethod]
public void ParseReturnsResourceItems()
{
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
Assert.IsNotNull(actual);
}
[TestMethod]
public void ParseReturnedResourceItemsContainsName()
{
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
foreach (var item in actual)
Assert.IsNotNull(item.Name);
}
[TestMethod]
public void ParseReturnedResourceItemsContainsValue()
{
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
foreach (var item in actual)
Assert.IsNotNull(item.Value);
}
[TestMethod]
public void ParseReturnedResourceItemsContainsComment()
{
var target = new ResourceParser(reswFileContents);
var actual = target.Parse();
foreach (var item in actual)
Assert.IsNotNull(item.Comment);
}
}
}
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Test1" xml:space="preserve">
<value>Test 1 value</value>
<comment>Test 1 comment</comment>
</data>
<data name="Test2" xml:space="preserve">
<value>Test 2 value</value>
<comment>Test 2 comment</comment>
</data>
<data name="Test3" xml:space="preserve">
<value>Test 3 value</value>
<comment>Test 3 comment</comment>
</data>
<data name="TestControl.Text" xml:space="preserve">
<value>TestControl.Text value</value>
<comment>TestControl.Test comment</comment>
</data>
</root>
@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Test1" xml:space="preserve">
<value>Test 1 value</value>
</data>
<data name="Test2" xml:space="preserve">
<value>Test 2 value</value>
</data>
<data name="Test3" xml:space="preserve">
<value>Test 3 value</value>
</data>
<data name="TestControl.Text" xml:space="preserve">
<value>TestControl.Text value</value>
</data>
</root>
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Test1" xml:space="preserve">
<value />
<comment>Test 1 comment</comment>
</data>
<data name="Test2" xml:space="preserve">
<value />
<comment>Test 2 comment</comment>
</data>
<data name="Test3" xml:space="preserve">
<value />
<comment>Test 3 comment</comment>
</data>
<data name="TestControl.Text" xml:space="preserve">
<value />
<comment>TestControl.Test comment</comment>
</data>
</root>
@@ -0,0 +1,39 @@
using System;
using System.Runtime.InteropServices;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class StringExtensionTests
{
const string TEXT = "test";
[TestMethod]
public void ConvertToIntPtrDoesNotReturnZero()
{
uint len;
var ptr = TEXT.ConvertToIntPtr(out len);
Assert.AreNotEqual(IntPtr.Zero, ptr);
}
[TestMethod]
public void ConvertToIntPtrReturnsStringLengthAsParameter()
{
uint len;
TEXT.ConvertToIntPtr(out len);
Assert.AreNotEqual(TEXT.Length, len);
}
[TestMethod]
public void ConvertToIntPtrConvertsCorrectString()
{
uint len;
var ptr = TEXT.ConvertToIntPtr(out len);
var str = Marshal.PtrToStringAnsi(ptr, (int) len);
Assert.AreEqual(TEXT, str);
}
}
}
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F2B82735-4AE9-4365-8C0D-8391564359AB}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests</RootNamespace>
<AssemblyName>VSPackage.Tests</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="ClassNameExtractorTests.cs" />
<Compile Include="CodeGeneratorFactoryTests.cs" />
<Compile Include="CSharpCodeGeneratorTests.cs" />
<Compile Include="CSharpCodeGeneratorTestsInternal.cs" />
<Compile Include="ResourceParserErrorHandlingTests.cs" />
<Compile Include="ResourceParserTests.cs" />
<Compile Include="StringExtensionTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VisualBasicCodeGeneratorInternalTests.cs" />
<Compile Include="VisualBasicCodeGeneratorTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<Content Include="Resources\Resources.resw">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\ResourcesWithoutComments.resw">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\ResourcesWithoutValues.resw">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VSPackage\VSPackage.csproj">
<Project>{05f77bfb-ce11-4948-8174-f938c5b7f31c}</Project>
<Name>VSPackage</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.targets'))" />
</Target>
<Import Project="..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\packages\MSTest.TestAdapter.1.1.18\build\net45\MSTest.TestAdapter.targets')" />
</Project>
@@ -0,0 +1,76 @@
using System.IO;
using System.Linq;
using System.Reflection;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualBasic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class VisualBasicCodeGeneratorInternalTests
{
private const string FILE_PATH = "Resources.resw";
private string actual;
private string reswFileContents;
private ICodeGenerator target;
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText(FILE_PATH);
target = new CodeGeneratorFactory().Create(FILE_PATH.Replace(".resw", string.Empty), "TestApp", reswFileContents, new VBCodeProvider(), TypeAttributes.NestedAssembly);
actual = target.GenerateCode();
}
[TestMethod]
public void GenerateCodeDoesNotReturnNull()
{
Assert.IsNotNull(actual);
}
[TestMethod]
public void GeneratedCodeIsFriendClass()
{
Assert.IsTrue(actual.Contains("Partial Friend NotInheritable Class"));
}
[TestMethod]
public void GeneratedCodeContainsPropertiesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Public Shared ReadOnly Property " + item.Name + "() As String"));
}
[TestMethod]
public void GeneratedCodePropertiesContainsCommentsSimilarToValuesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Localized resource similar to \"" + item.Value + "\""));
}
[TestMethod]
public void ClassNameEqualsFileNameWithoutExtension()
{
Assert.IsTrue(actual.Contains("Class Resources"));
}
[TestMethod]
public void ResourceLoaderInitializedWithClassName()
{
Assert.IsTrue(actual.Contains("New ResourceLoader(currentAssemblyName + \"/Resources\")"));
}
[TestMethod]
public void ContainsProjectUrl()
{
Assert.IsTrue(actual.Contains("http://bit.ly/reswcodegen"));
}
}
}
@@ -0,0 +1,69 @@
using System.IO;
using System.Linq;
using ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool;
using Microsoft.VisualBasic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.CustomTool.Tests
{
[TestClass]
[DeploymentItem("Resources/Resources.resw")]
public class VisualBasicCodeGeneratorTests
{
private const string FILE_PATH = "Resources.resw";
private string actual;
private string reswFileContents;
private ICodeGenerator target;
[TestInitialize]
public void Initialize()
{
reswFileContents = File.ReadAllText(FILE_PATH);
target = new CodeGeneratorFactory().Create(FILE_PATH.Replace(".resw", string.Empty), "TestApp", reswFileContents, new VBCodeProvider());
actual = target.GenerateCode();
}
[TestMethod]
public void GenerateCodeDoesNotReturnNull()
{
Assert.IsNotNull(actual);
}
[TestMethod]
public void GeneratedCodeContainsPropertiesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Public Shared ReadOnly Property " + item.Name + "() As String"));
}
[TestMethod]
public void GeneratedCodePropertiesContainsCommentsSimilarToValuesDefinedInResources()
{
var resourceItems = target.ResourceParser.Parse();
foreach (var item in resourceItems.Where(item => !item.Name.Contains(".")))
Assert.IsTrue(actual.Contains("Localized resource similar to \"" + item.Value + "\""));
}
[TestMethod]
public void ClassNameEqualsFileNameWithoutExtension()
{
Assert.IsTrue(actual.Contains("Class Resources"));
}
[TestMethod]
public void ResourceLoaderInitializedWithClassName()
{
Assert.IsTrue(actual.Contains("New ResourceLoader(currentAssemblyName + \"/Resources\")"));
}
[TestMethod]
public void ContainsProjectUrl()
{
Assert.IsTrue(actual.Contains("http://bit.ly/reswcodegen"));
}
}
}
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.1.18" targetFramework="net461" />
<package id="MSTest.TestFramework" version="1.1.18" targetFramework="net461" />
</packages>
@@ -0,0 +1,16 @@
using System.IO;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public static class ClassNameExtractor
{
public static string GetClassName(string wszInputFilePath)
{
if (!File.Exists(wszInputFilePath))
throw new FileNotFoundException();
var fileInfo = new FileInfo(wszInputFilePath);
return fileInfo.Name.Replace(fileInfo.Extension, string.Empty);
}
}
}
@@ -0,0 +1,207 @@
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.CSharp;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeDomCodeGenerator : CodeGenerator, IDisposable
{
private readonly TypeAttributes? classAccessibility;
private readonly VisualStudioVersion visualStudioVersion;
private readonly string className;
private readonly CodeNamespace codeNamespace;
private readonly CodeCompileUnit compileUnit;
private readonly CodeDomProvider provider;
public CodeDomCodeGenerator(IResourceParser resourceParser,
string className,
string defaultNamespace,
CodeDomProvider codeDomProvider = null,
TypeAttributes? classAccessibility = null,
VisualStudioVersion visualStudioVersion = VisualStudioVersion.VS2012)
: base(resourceParser, defaultNamespace)
{
this.className = className;
this.classAccessibility = classAccessibility;
this.visualStudioVersion = visualStudioVersion;
compileUnit = new CodeCompileUnit();
provider = codeDomProvider ?? new CSharpCodeProvider();
codeNamespace = new CodeNamespace(defaultNamespace);
}
public override string GenerateCode()
{
codeNamespace.Comments.Add(
new CodeCommentStatement("--------------------------------------------------------------------------------------------------"));
codeNamespace.Comments.Add(new CodeCommentStatement("<auto-generatedInfo>"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code was generated by ResW File Code Generator (http://bit.ly/reswcodegen)"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tResW File Code Generator was written by Christian Resma Helle"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tand is under GNU General Public License version 2 (GPLv2)"));
codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty));
codeNamespace.Comments.Add(new CodeCommentStatement("\tThis code contains a helper class exposing property representations"));
codeNamespace.Comments.Add(new CodeCommentStatement("\tof the string resources defined in the specified .ResW file"));
codeNamespace.Comments.Add(new CodeCommentStatement(string.Empty));
codeNamespace.Comments.Add(new CodeCommentStatement("\tGenerated: " + DateTime.Now.ToString(CultureInfo.InvariantCulture)));
codeNamespace.Comments.Add(new CodeCommentStatement("</auto-generatedInfo>"));
codeNamespace.Comments.Add(
new CodeCommentStatement("--------------------------------------------------------------------------------------------------"));
codeNamespace.Imports.Add(new CodeNamespaceImport("Windows.ApplicationModel.Resources"));
var targetClass = new CodeTypeDeclaration(className)
{
IsClass = true,
IsPartial = true,
TypeAttributes = TypeAttributes.Sealed | (classAccessibility ?? TypeAttributes.Public),
Attributes = MemberAttributes.Public | MemberAttributes.Static | MemberAttributes.Final
};
const string resourceLoaderType = "ResourceLoader";
var resourceLoaderField = new CodeMemberField(resourceLoaderType, "resourceLoader")
{
Attributes = MemberAttributes.Private | MemberAttributes.Static | MemberAttributes.Final
};
targetClass.Members.Add(resourceLoaderField);
var constructor = new CodeTypeConstructor();
var executingAssemblyVar = new CodeVariableDeclarationStatement(typeof (string), "executingAssemblyName");
var executingAssemblyInit = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblyName"),
new CodeSnippetExpression("Windows.UI.Xaml.Application.Current.GetType().AssemblyQualifiedName"));
var executingAssemblySplit = new CodeVariableDeclarationStatement(typeof (string[]), "executingAssemblySplit");
var executingAssemblyInit2 = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblySplit"),
new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("executingAssemblyName"),
"Split",
new CodePrimitiveExpression(',')));
var executingAssemblyInit3 = new CodeAssignStatement(new CodeVariableReferenceExpression("executingAssemblyName"),
new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("executingAssemblySplit"),
new CodePrimitiveExpression(1)));
var currentAssemblyVar = new CodeVariableDeclarationStatement(typeof (string), "currentAssemblyName");
var currentAssemblyInit = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblyName"),
new CodePropertyReferenceExpression(new CodeTypeOfExpression(className), "AssemblyQualifiedName"));
var currentAssemblySplit = new CodeVariableDeclarationStatement(typeof (string[]), "currentAssemblySplit");
var currentAssemblyInit2 = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblySplit"),
new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("currentAssemblyName"),
"Split",
new CodePrimitiveExpression(',')));
var currentAssemblyInit3 = new CodeAssignStatement(new CodeVariableReferenceExpression("currentAssemblyName"),
new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("currentAssemblySplit"),
new CodePrimitiveExpression(1)));
var createResourceLoader = new CodeConditionStatement(
new CodeSnippetExpression("executingAssemblyName.Equals(currentAssemblyName)"),
new CodeStatement[] // true
{
visualStudioVersion == VisualStudioVersion.VS2013
? new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("ResourceLoader"),
"GetForCurrentView",
new CodeSnippetExpression("\"" + className + "\"")))
: new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"),
new CodeSnippetExpression("\"" + className + "\"")))
},
new CodeStatement[] // false
{
visualStudioVersion == VisualStudioVersion.VS2013
? new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("ResourceLoader"),
"GetForCurrentView",
new CodeSnippetExpression("currentAssemblyName + \"/" + className + "\"")))
: new CodeAssignStatement(new CodeFieldReferenceExpression(null, "resourceLoader"),
new CodeObjectCreateExpression(new CodeTypeReference("ResourceLoader"),
new CodeSnippetExpression("currentAssemblyName + \"/" + className + "\"")))
});
constructor.Statements.Add(executingAssemblyVar);
constructor.Statements.Add(executingAssemblyInit);
constructor.Statements.Add(executingAssemblySplit);
constructor.Statements.Add(executingAssemblyInit2);
constructor.Statements.Add(executingAssemblyInit3);
constructor.Statements.Add(currentAssemblyVar);
constructor.Statements.Add(currentAssemblyInit);
constructor.Statements.Add(currentAssemblySplit);
constructor.Statements.Add(currentAssemblyInit2);
constructor.Statements.Add(currentAssemblyInit3);
constructor.Statements.Add(createResourceLoader);
targetClass.Members.Add(constructor);
var resources = ResourceParser.Parse();
foreach (var item in resources)
{
if (string.IsNullOrEmpty(item.Name) || item.Name.Contains("."))
continue;
var property = new CodeMemberProperty
{
Name = item.Name.Trim(),
Attributes = MemberAttributes.Public | MemberAttributes.Static,
HasGet = true,
Type = new CodeTypeReference(typeof (string))
};
property.Comments.Add(new CodeCommentStatement("<summary>", true));
property.Comments.Add(new CodeCommentStatement("Localized resource similar to \"" + (item.Value ?? item.Name) + "\"", true));
property.Comments.Add(new CodeCommentStatement("</summary>", true));
property.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeMethodInvokeExpression(
new CodeFieldReferenceExpression(null, "resourceLoader"),
"GetString",
new CodePrimitiveExpression(item.Name))));
targetClass.Members.Add(property);
}
codeNamespace.Types.Add(targetClass);
compileUnit.Namespaces.Add(codeNamespace);
return GenerateCodeFromCompileUnit();
}
private string GenerateCodeFromCompileUnit()
{
var options = new CodeGeneratorOptions {BracingStyle = "C"};
var code = new StringBuilder();
using (var writer = new StringWriter(code))
provider.GenerateCodeFromCompileUnit(compileUnit, writer, options);
return code.ToString();
}
#region IDisposable
private bool disposed;
public void Dispose()
{
Dispose(true);
}
~CodeDomCodeGenerator()
{
Dispose(false);
}
protected virtual void Dispose(bool dispose)
{
if (disposed)
return;
disposed = true;
if (dispose)
provider.Dispose();
}
#endregion
}
}
@@ -0,0 +1,16 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public abstract class CodeGenerator : ICodeGenerator
{
protected CodeGenerator(IResourceParser resourceParser, string defaultNamespace)
{
ResourceParser = resourceParser;
Namespace = defaultNamespace;
}
public IResourceParser ResourceParser { get; set; }
public string Namespace { get; set; }
public abstract string GenerateCode();
}
}
@@ -0,0 +1,33 @@
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public class CodeGeneratorFactory
{
public ICodeGenerator Create(string className, string defaultNamespace, string inputFileContents, CodeDomProvider codeDomProvider = null, TypeAttributes? classAccessibility = null)
{
return new CodeDomCodeGenerator(new ResourceParser(inputFileContents), className, defaultNamespace, codeDomProvider, classAccessibility, VisualStudioHelper.GetVersion());
}
}
public static class VisualStudioHelper
{
public static VisualStudioVersion GetVersion()
{
var dte = Package.GetGlobalService(typeof(SDTE)) as DTE;
var vsVersion = VisualStudioVersion.VS2012;
if (dte != null)
{
Version dteVersion;
if (Version.TryParse(dte.Version, out dteVersion) && dteVersion >= new Version(12, 0))
vsVersion = VisualStudioVersion.VS2013;
}
return vsVersion;
}
}
}
@@ -0,0 +1,9 @@
namespace ChristianHelle.DeveloperTools.CodeGenerators.Resw.VSPackage.CustomTool
{
public interface ICodeGenerator
{
IResourceParser ResourceParser { get; set; }
string Namespace { get; set; }
string GenerateCode();
}
}

Some files were not shown because too many files have changed in this diff Show More