├── .gitignore ├── CodeAnalysisDictionary.xml ├── CommonAssemblyInfo.cs ├── LICENSE ├── LocalTestRun.testrunconfig ├── README.md ├── Settings.StyleCop ├── T4Toolbox.Common.props ├── T4Toolbox.Common.ruleset ├── T4Toolbox.sln ├── appveyor.yml ├── build ├── Module.psm1 └── Module.tests.ps1 ├── src ├── T4Toolbox.DirectiveProcessors │ ├── AssemblyInfo.cs │ ├── DirectiveProcessor.cs │ ├── T4Toolbox.DirectiveProcessors.csproj │ ├── TransformationContextProcessor.cs │ └── packages.config ├── T4Toolbox.TemplateAnalysis │ ├── AssemblyDirective.cs │ ├── Attribute.cs │ ├── AttributeDescriptor.cs │ ├── AttributeName.cs │ ├── AttributeValue.cs │ ├── BlockEnd.cs │ ├── CaptureNode.cs │ ├── ClassBlockStart.cs │ ├── Code.cs │ ├── CodeBlock.cs │ ├── CodeBlockStart.cs │ ├── CustomDirective.cs │ ├── Directive.cs │ ├── DirectiveBlockStart.cs │ ├── DirectiveDescriptor.cs │ ├── DirectiveName.cs │ ├── DoubleQuote.cs │ ├── EndOfFile.cs │ ├── Equals.cs │ ├── ExpressionBlockStart.cs │ ├── GlobalSuppressions.cs │ ├── HashCode.cs │ ├── ImportDirective.cs │ ├── IncludeDirective.cs │ ├── KnownValuesAttribute.cs │ ├── NonterminalNode.cs │ ├── OutputDirective.cs │ ├── ParameterDirective.cs │ ├── Position.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ShiftReduceParserCode.cs │ ├── StatementBlockStart.cs │ ├── SyntaxNode.cs │ ├── SyntaxNodeVisitor.cs │ ├── SyntaxToken.cs │ ├── T4Toolbox.TemplateAnalysis.csproj │ ├── Template.cs │ ├── TemplateDirective.cs │ ├── TemplateError.cs │ ├── TemplateLanguage.cs │ ├── TemplateParser.partial.cs │ ├── TemplateParser.y │ ├── TemplateScanner.lex │ ├── TemplateScanner.partial.cs │ ├── TemplateVisibility.cs │ ├── TerminalNode.cs │ ├── ValueDescriptor.cs │ └── packages.config ├── T4Toolbox.VisualStudio.Editor │ ├── ClassificationFormatDefinitions.cs │ ├── ClassificationTypeDefinitions.cs │ ├── ClassificationTypeName.cs │ ├── ITemplateEditorOptions.cs │ ├── T4Toolbox.VisualStudio.Editor.csproj │ ├── TemplateAnalysis.cs │ ├── TemplateAnalyzer.cs │ ├── TemplateClassificationTagger.cs │ ├── TemplateClassificationTaggerProvider.cs │ ├── TemplateCompletionBuilder.cs │ ├── TemplateCompletionHandler.cs │ ├── TemplateCompletionHandlerProvider.cs │ ├── TemplateCompletionSource.cs │ ├── TemplateCompletionSourceProvider.cs │ ├── TemplateContentType.cs │ ├── TemplateErrorReporter.cs │ ├── TemplateErrorReporterProvider.cs │ ├── TemplateErrorTagger.cs │ ├── TemplateErrorTaggerProvider.cs │ ├── TemplateOutliningTagger.cs │ ├── TemplateOutliningTaggerProvider.cs │ ├── TemplateQuickInfoSource.cs │ ├── TemplateQuickInfoSourceProvider.cs │ ├── TemplateTagger.cs │ └── packages.config ├── T4Toolbox.VisualStudio.ItemTemplates │ ├── C# │ │ ├── Generator │ │ │ ├── Generator.tt │ │ │ └── Generator.vstemplate │ │ ├── Script │ │ │ ├── Script.tt │ │ │ └── Script.vstemplate │ │ └── Template │ │ │ ├── Template.tt │ │ │ └── Template.vstemplate │ ├── T4Toolbox.VisualStudio.ItemTemplates.csproj │ └── VB │ │ ├── Generator │ │ ├── Generator.tt │ │ └── Generator.vstemplate │ │ ├── Script │ │ ├── Script.tt │ │ └── Script.vstemplate │ │ └── Template │ │ ├── Template.tt │ │ └── Template.vstemplate ├── T4Toolbox.VisualStudio │ ├── AssemblyInfo.cs │ ├── BrowseObjectExtender.cs │ ├── BrowseObjectExtenderProvider.cs │ ├── CustomToolParameter.cs │ ├── CustomToolParameters.cs │ ├── CustomToolTemplateEditor.cs │ ├── EnvDteExtensions.cs │ ├── ItemMetadataWizard.cs │ ├── OutputFileManager.cs │ ├── ProjectItemProperty.cs │ ├── ProjectItemTemplateWizard.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── ScriptFileGenerator.cs │ ├── T4Toolbox.VisualStudio.csproj │ ├── T4ToolboxOptions.cs │ ├── T4ToolboxOptionsPage.cs │ ├── T4ToolboxPackage.cs │ ├── TemplateLocator.cs │ ├── TemplatedFileGenerator.cs │ ├── TransformationContextProvider.cs │ └── packages.config ├── T4Toolbox.vsix │ ├── Dark.vstheme │ ├── DarkTheme.pkgdef │ ├── Include │ │ └── T4Toolbox.tt │ ├── License.txt │ ├── T4Toolbox.vsix.csproj │ └── source.extension.vsixmanifest ├── T4Toolbox │ ├── AssemblyInfo.cs │ ├── CSharpTemplate.cs │ ├── ClrTemplate.cs │ ├── CopyToOutputDirectory.cs │ ├── FileMethods.cs │ ├── Generator.cs │ ├── ITransformationContextProvider.cs │ ├── ItemMetadata.cs │ ├── ItemType.cs │ ├── NativeMethods.cs │ ├── OutputFile.cs │ ├── OutputItem.cs │ ├── T4Toolbox.csproj │ ├── Template.cs │ ├── TransformationContext.cs │ ├── TransformationException.cs │ └── packages.config └── TextTemplate.ico └── test ├── Settings.StyleCop ├── T4Toolbox.TemplateAnalysis.Tests ├── AssemblyDirectiveTest.cs ├── AttributeDescriptorTest.cs ├── AttributeNameTest.cs ├── AttributeTest.cs ├── AttributeValueTest.cs ├── BlockEndTest.cs ├── CaptureNodeTest.cs ├── ClassBlockStartTest.cs ├── CodeBlockTest.cs ├── CodeTest.cs ├── CustomDirectiveTest.cs ├── DirectiveBlockStartTest.cs ├── DirectiveDescriptorTest.cs ├── DirectiveNameTest.cs ├── DirectiveTest.cs ├── DoubleQuoteTest.cs ├── EndOfFileTest.cs ├── EqualsTest.cs ├── ExpressionBlockStartTest.cs ├── ImportDirectiveTest.cs ├── IncludeDirectiveTest.cs ├── KnownValuesAttributeTest.cs ├── NonterminalNodeTest.cs ├── OutputDirectiveTest.cs ├── ParameterDirectiveTest.cs ├── PositionTest.cs ├── StatementBlockStartTest.cs ├── SyntaxNodeTest.cs ├── SyntaxNodeVisitorTest.cs ├── SyntaxTokenTest.cs ├── T4Toolbox.TemplateAnalysis.Tests.csproj ├── TemplateDirectiveTest.cs ├── TemplateErrorTest.cs ├── TemplateParserTest.cs ├── TemplateScannerTest.cs ├── TemplateTest.cs ├── TerminalNodeTest.cs ├── ValueDescriptorTest.cs └── packages.config ├── T4Toolbox.Tests.props ├── T4Toolbox.Tests.ruleset ├── T4Toolbox.Tests ├── CSharpTemplateTest.cs ├── ClrTemplateTest.cs ├── FakeGenerator.cs ├── FakeTemplate.cs ├── FakeTextTemplatingService.cs ├── FakeTransformation.cs ├── GeneratorTest.cs ├── GlobalSuppressions.cs ├── OutputItemTest.cs ├── T4Toolbox.Tests.csproj ├── TemplateTest.cs ├── TransformationContextTest.cs └── packages.config ├── T4Toolbox.VisualStudio.Editor.Tests ├── FakeClassificationType.cs ├── FakeClassificationTypeRegistryService.cs ├── FakeCompletionSession.cs ├── FakeQuickInfoSession.cs ├── FakeTextBuffer.cs ├── FakeTextSnapshot.cs ├── FakeTrackingSpan.cs ├── SubstituteExporter.cs ├── T4Toolbox.VisualStudio.Editor.Tests.csproj ├── TemplateAnalyzerTest.cs ├── TemplateClassificationTaggerProviderTest.cs ├── TemplateClassificationTaggerTest.cs ├── TemplateCompletionBuilderTest.cs ├── TemplateCompletionHandlerProviderTest.cs ├── TemplateCompletionHandlerTest.cs ├── TemplateCompletionSourceProviderTest.cs ├── TemplateCompletionSourceTest.cs ├── TemplateErrorReporterProviderTest.cs ├── TemplateErrorTaggerProviderTest.cs ├── TemplateErrorTaggerTest.cs ├── TemplateOutliningTaggerProviderTest.cs ├── TemplateOutliningTaggerTest.cs ├── TemplateQuickInfoSourceProviderTest.cs ├── TemplateQuickInfoSourceTest.cs ├── TemplateTaggerTest.cs └── packages.config ├── T4Toolbox.VisualStudio.IntegrationTests ├── CustomToolParametersTest.cs ├── CustomToolTemplateTest.cs ├── GlobalSuppressions.cs ├── IntegrationTest.cs ├── ItemTemplateTest.cs ├── OutputFileManagerTest.cs ├── PackageTest.cs ├── ScriptFileGeneratorTest.cs ├── T4Toolbox.VisualStudio.IntegrationTests.csproj ├── T4ToolboxOptionsPageTest.cs ├── TargetProject.cs ├── TargetProject.xml ├── TemplateErrorReporterTest.cs ├── TemplateLocatorTest.cs ├── TemplatedFileGeneratorTest.cs ├── TransformationContextProviderTest.cs ├── TransformationContextTest.cs └── packages.config └── T4Toolbox.VisualStudio.Tests ├── BrowseObjectExtenderTest.cs ├── CustomToolParameterTest.cs ├── CustomToolParametersTest.cs ├── CustomToolTemplateEditorTest.cs ├── Fakes ├── FakeDte.cs ├── FakeObjectExtenders.cs ├── FakeProject.cs ├── FakeProjectItem.cs ├── FakeProjectItems.cs ├── FakeProjects.cs ├── FakeProperties.cs ├── FakeProperty.cs ├── FakeSolution.cs ├── FakeTemplateLocator.cs ├── FakeTextTemplating.cs ├── FakeTypeDescriptorContext.cs ├── FakeVsActivityLog.cs ├── StubIPersistDocData.cs ├── StubIVsQueryEditQuerySave.cs └── StubIVsRunningDocumentTable.cs ├── GlobalSuppressions.cs ├── ItemMetadataWizardTest.cs ├── OutputFileManagerTest.cs ├── T4Toolbox.VisualStudio.Tests.csproj ├── T4ToolboxOptionsTest.cs ├── T4ToolboxPackageTest.cs ├── TransformationContextProviderTest.cs └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio and Git files and folders 2 | 3 | *.suo 4 | *.user 5 | *.cache 6 | *.vspscc 7 | *.patch 8 | *.exe 9 | *.snk 10 | 11 | [Bb]ackup*/ 12 | [Bb]in/ 13 | [Oo]bj/ 14 | [Tt]est[Rr]esult*/ 15 | [Pp]ackages/ 16 | .vs/ 17 | -------------------------------------------------------------------------------- /CodeAnalysisDictionary.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Lex 5 | LLoc 6 | EOF 7 | Polymorphically 8 | 9 | 10 | -------------------------------------------------------------------------------- /CommonAssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | using System.Reflection; 6 | using System.Resources; 7 | using System.Runtime.CompilerServices; 8 | using System.Runtime.InteropServices; 9 | 10 | #if DEBUG 11 | [assembly: AssemblyConfiguration("Debug")] 12 | #else 13 | [assembly: AssemblyConfiguration("Release")] 14 | #endif 15 | 16 | [assembly: AssemblyProduct(T4Toolbox.AssemblyInfo.Product)] 17 | [assembly: AssemblyDescription(T4Toolbox.AssemblyInfo.Description)] 18 | [assembly: AssemblyCompany("Oleg Sych")] 19 | [assembly: AssemblyCopyright("Copyright © Oleg Sych. All Rights Reserved.")] 20 | [assembly: AssemblyTrademark("")] 21 | [assembly: AssemblyCulture("")] 22 | [assembly: AssemblyVersion(T4Toolbox.AssemblyInfo.Version)] 23 | [assembly: AssemblyFileVersion(T4Toolbox.AssemblyInfo.Version)] 24 | [assembly: ComVisible(false)] 25 | [assembly: NeutralResourcesLanguage("en-US")] 26 | 27 | // Allow all projects in this solution to access each-other's internals by default. 28 | // In many instances, we need this to enable testing as well as to access constants 29 | // in T4Toolbox.AssemblyInfo class. Revisit this decision when the number of assemblies 30 | // in the project increases to the point where limiting access to internals within the 31 | // solution becomes beneficial. 32 | [assembly: InternalsVisibleTo("T4Toolbox.DirectiveProcessors" + T4Toolbox.AssemblyInfo.PublicKey)] 33 | [assembly: InternalsVisibleTo("T4Toolbox.TemplateAnalysis" + T4Toolbox.AssemblyInfo.PublicKey)] 34 | [assembly: InternalsVisibleTo("T4Toolbox.TemplateAnalysis.Tests" + T4Toolbox.AssemblyInfo.PublicKey)] 35 | [assembly: InternalsVisibleTo("T4Toolbox.Tests" + T4Toolbox.AssemblyInfo.PublicKey)] 36 | [assembly: InternalsVisibleTo("T4Toolbox.VisualStudio" + T4Toolbox.AssemblyInfo.PublicKey)] 37 | [assembly: InternalsVisibleTo("T4Toolbox.VisualStudio.Editor" + T4Toolbox.AssemblyInfo.PublicKey)] 38 | [assembly: InternalsVisibleTo("T4Toolbox.VisualStudio.Editor.Tests" + T4Toolbox.AssemblyInfo.PublicKey)] 39 | [assembly: InternalsVisibleTo("T4Toolbox.VisualStudio.IntegrationTests" + T4Toolbox.AssemblyInfo.PublicKey)] 40 | [assembly: InternalsVisibleTo("T4Toolbox.VisualStudio.Tests" + T4Toolbox.AssemblyInfo.PublicKey)] 41 | 42 | #if SIGN_ASSEMBLY 43 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 44 | #else 45 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 46 | #endif 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2008 Oleg Sych 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /LocalTestRun.testrunconfig: -------------------------------------------------------------------------------- 1 |  2 | 3 | Test settings required to run Visual Studio integration tests. 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /T4Toolbox.Common.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | AnyCPU 7 | $(MSBuildProjectName) 8 | $(MSBuildProjectName) 9 | Properties 10 | v4.6 11 | 12 | 15.0 13 | 15.0 14 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 15 | true 16 | full 17 | prompt 18 | 4 19 | 512 20 | true 21 | bin\$(Configuration)\ 22 | $(MSBuildThisFileDirectory)\T4Toolbox.Common.ruleset 23 | false 24 | 25 | 26 | 27 | true 28 | TRACE 29 | $(OutputPath)$(AssemblyName).xml 30 | true 31 | 32 | 33 | 34 | false 35 | DEBUG;TRACE 36 | false 37 | 38 | 39 | 40 | 41 | true 42 | $(MSBuildThisFileDirectory)\T4Toolbox.snk 43 | $(DefineConstants);SIGN_ASSEMBLY 44 | 45 | 46 | 47 | 48 | 49 | False 50 | 55 | False 56 | 57 | 58 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # CI build definition for https://ci.appveyor.com/project/olegsych/t4toolbox 2 | # To learn more, see http://www.appveyor.com/docs/appveyor-yml 3 | 4 | version: 15.0.0.{build} 5 | 6 | image: Visual Studio 2017 7 | 8 | branches: 9 | only: 10 | - master 11 | 12 | pull_requests: 13 | do_not_increment_build_number: true 14 | 15 | skip_tags: true 16 | 17 | configuration: Release 18 | 19 | environment: 20 | T4ToolboxSnk: 21 | secure: qikNDVTVELcu7WnxruC2+vO9vOdK0whuxosiF5xiV2vI1v/UNno8rtqhoYgKjGoI4IxTvUEtOseNKqF6n0LjKjC2KiiqQj+zvdbkghr9GmWGFiCw27QlbbO/NU9+xWLULt8WxuOTHp681290l304YGRyE2SS2Tb0i86XJXJ5BXC5YvMgK6woVCOHCEITiTmUZBwppFoc5IR3bnyXSSLimLXP0mYPuT+zzPGit2V6HA5VmrXUe8K4DJ1NYDATmcztKusz1klcVzIrtQiII4CWKBvmHHk8g6Hoy8sWHb4CtzHr8QeCvcBwpb6TINLY71M620ELKBczMf2HAUvmcyNY9v+eFnJ8Vcz0gc5o0ENLQ8A/f0i6v57MqnBC9g9WH3kLCNGKe2GVhSdx9+cnaoD5Lnwt3+Qyi9N8UxbGg9yRzSG7u+PU2d/OvneT/r0AGqFIau/yBjSFL3QVMX6j3ycfH653UQOoM/Y8cbyf89tCtz810Y2/IQ4wXUTNEeXvlAiRDlRXPavfjvk8GlCf3ub0LoNbKAx2MXzLN1cQsPmdvCxT7Zlca2PKFwXp4PvIXT50f+QK1HPAn33X2WijYLc9IdiauyKHbP3hdf82b6jmdeCleaFpxRbOUbQyifldxURkla/dZNM5MjdQSMuwqohcK02+t+TzINKTNOQEyOM5JmllU8Y+csgX255G1DyxMNPlsGKor3yhAFsLalbcZu5VMCgPzxvDJSOs3ksAJF9IJB2GynM/Yzy76j8sGbRsx7GW8mT+TxIIiOd/+Y2n/C2jEKoA6RWorNjp1Bw2pjQvI5Z7p8bemTqOjNssQXFJ2m9xfamtlWqQAaBB2KAVjzSPyOCaKGqGXoUsY4XEkoDQ8Nlm0ZJfVGgzz4ccpX4Plhh6sIHThZU0nENypdqy/nNStOkKRw5MKnh57ObgL77bnrWHu0aWZhBfgVFQTo87WWxLEhWFnVfC8rXhXItdz+VWf4oCJ/nrxT13SeMYQ+/FETzF2TCMzP7tQvLRHLuNWNaPvJIsQ56g9uamZQDR7i1jvCjZ16RllA4Vv0y6z34ruaA= 22 | 23 | before_build: 24 | - nuget restore 25 | - ps: >- 26 | Import-Module .\build\Module.psm1 27 | 28 | if (!$env:APPVEYOR_PULL_REQUEST_NUMBER) { 29 | CreateAssemblyKeyFile "T4ToolboxSnk" "T4Toolbox.snk" 30 | } 31 | 32 | build: 33 | parallel: true 34 | verbosity: minimal 35 | 36 | test: 37 | assemblies: '**\*.tests.dll' 38 | 39 | artifacts: 40 | - path: '**\T4Toolbox.*.vsix' -------------------------------------------------------------------------------- /build/Module.psm1: -------------------------------------------------------------------------------- 1 | function CreateAssemblyKeyFile([string] $environmentVariableName, [string] $fileName) { 2 | $base64string = [Environment]::GetEnvironmentVariable($environmentVariableName) 3 | $bytes = [Convert]::FromBase64String($base64string) 4 | $filePath = [IO.Path]::Combine((Get-Location).Path, $fileName) 5 | Write-Host "Writing from $environmentVariableName environment variable to $filePath" 6 | Set-Content -Path $filePath -Value $bytes -Encoding Byte 7 | } 8 | 9 | Export-ModuleMember -Function CreateAssemblyKeyFile -------------------------------------------------------------------------------- /build/Module.tests.ps1: -------------------------------------------------------------------------------- 1 | # This is a PowerShell Unit Test file. To run tests 2 | # PM> Install-Module Pester -Scope CurrentUser 3 | # PM> Invoke-Pester 4 | 5 | Import-Module .\Module.psm1 6 | 7 | Describe "Module" { 8 | Context "CreateAssemblyFile" { 9 | $originalLocation = Get-Location 10 | 11 | It "Converts value of environment variable from Base64 to binary and writes it to file in current location" { 12 | $keyBytes = [Guid]::NewGuid().ToByteArray() 13 | $env:TestKey = [Convert]::ToBase64String($keyBytes) 14 | Set-Location "TestDrive:\" 15 | 16 | CreateAssemblyKeyFile "TestKey" "Test.snk" 17 | 18 | $fileBytes = Get-Content -Path "TestDrive:\Test.snk" -Encoding Byte 19 | $fileBytes | Should Be $keyBytes 20 | } 21 | 22 | Set-Location $originalLocation 23 | } 24 | } 25 | 26 | Remove-Module Module -------------------------------------------------------------------------------- /src/T4Toolbox.DirectiveProcessors/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | using System; 6 | 7 | [assembly: CLSCompliant(false)] 8 | 9 | namespace T4Toolbox.DirectiveProcessors 10 | { 11 | /// 12 | /// Defines constants describing the T4Toolbox.VisualStudio assembly. 13 | /// 14 | internal abstract class AssemblyInfo : T4Toolbox.AssemblyInfo 15 | { 16 | /// 17 | /// Gets the name of the assembly. 18 | /// 19 | public new const string Name = "T4Toolbox.DirectiveProcessors"; 20 | } 21 | } -------------------------------------------------------------------------------- /src/T4Toolbox.DirectiveProcessors/T4Toolbox.DirectiveProcessors.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {E0282961-2D83-48CC-B4D4-8257449CF8F7} 5 | Library 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Properties\CommonAssemblyInfo.cs 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {682e771a-76f7-4972-bbdc-1250b67f399b} 29 | T4Toolbox 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 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}. 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/T4Toolbox.DirectiveProcessors/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/AssemblyDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.ComponentModel.DataAnnotations; 11 | using System.Diagnostics; 12 | 13 | [DisplayName("assembly"), Description("Loads an assembly so that your template code can use its types. The effect is similar to adding an assembly reference in a Visual Studio project.")] 14 | internal sealed class AssemblyDirective : Directive 15 | { 16 | public AssemblyDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 17 | : base(start, name, attributes, end) 18 | { 19 | Debug.Assert(name.Text.Equals("assembly", StringComparison.OrdinalIgnoreCase), "name"); 20 | } 21 | 22 | [DisplayName("Name"), Required(ErrorMessage = "The Name attribute is required"), Description("Name of an assembly in the GAC or absolute file path to the assembly.")] 23 | public string AssemblyName 24 | { 25 | get { return this.GetAttributeValue(); } 26 | } 27 | 28 | protected internal override void Accept(SyntaxNodeVisitor visitor) 29 | { 30 | visitor.VisitAssemblyDirective(this); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Attribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using Microsoft.VisualStudio.Text; 10 | 11 | internal sealed class Attribute : NonterminalNode 12 | { 13 | private readonly AttributeName name; 14 | private readonly Equals equals; 15 | private readonly DoubleQuote quote1; 16 | private readonly AttributeValue value; 17 | private readonly DoubleQuote quote2; 18 | 19 | public Attribute(AttributeName name, Equals equals, DoubleQuote quote1, AttributeValue value, DoubleQuote quote2) 20 | { 21 | Debug.Assert(name != null, "name"); 22 | Debug.Assert(equals != null, "equals"); 23 | Debug.Assert(quote1 != null, "quote1"); 24 | Debug.Assert(value != null, "value"); 25 | Debug.Assert(quote2 != null, "quote2"); 26 | 27 | this.name = name; 28 | this.equals = equals; 29 | this.quote1 = quote1; 30 | this.value = value; 31 | this.quote2 = quote2; 32 | } 33 | 34 | public override SyntaxKind Kind 35 | { 36 | get { return SyntaxKind.Attribute; } 37 | } 38 | 39 | public string Name 40 | { 41 | get { return this.name.Text; } 42 | } 43 | 44 | public override Position Position 45 | { 46 | get { return this.name.Position; } 47 | } 48 | 49 | public override Span Span 50 | { 51 | get { return Span.FromBounds(this.name.Span.Start, this.quote2.Span.End); } 52 | } 53 | 54 | public string Value 55 | { 56 | get { return this.value.Text; } 57 | } 58 | 59 | public override IEnumerable ChildNodes() 60 | { 61 | yield return this.name; 62 | yield return this.equals; 63 | yield return this.quote1; 64 | yield return this.value; 65 | yield return this.quote2; 66 | } 67 | 68 | protected internal override void Accept(SyntaxNodeVisitor visitor) 69 | { 70 | visitor.VisitAttribute(this); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/AttributeName.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal sealed class AttributeName : CaptureNode 8 | { 9 | public AttributeName(int start, string text, Position position = default(Position)) : base(start, text, position) 10 | { 11 | } 12 | 13 | public override SyntaxKind Kind 14 | { 15 | get { return SyntaxKind.AttributeName; } 16 | } 17 | 18 | protected internal override void Accept(SyntaxNodeVisitor visitor) 19 | { 20 | visitor.VisitAttributeName(this); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/AttributeValue.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal sealed class AttributeValue : CaptureNode 8 | { 9 | public AttributeValue(int start, string text, Position position = default(Position)) : base(start, text, position) 10 | { 11 | } 12 | 13 | public override SyntaxKind Kind 14 | { 15 | get { return SyntaxKind.AttributeValue; } 16 | } 17 | 18 | protected internal override void Accept(SyntaxNodeVisitor visitor) 19 | { 20 | visitor.VisitAttributeValue(this); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/BlockEnd.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | [Description("Ends a text template control block or directive.")] 11 | internal sealed class BlockEnd : SyntaxToken 12 | { 13 | public BlockEnd(int start, Position position = default(Position)) : base(start, position) 14 | { 15 | } 16 | 17 | public override SyntaxKind Kind 18 | { 19 | get { return SyntaxKind.BlockEnd; } 20 | } 21 | 22 | public override Span Span 23 | { 24 | get { return new Span(this.Start, 2); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitBlockEnd(this); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/CaptureNode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal abstract class CaptureNode : TerminalNode 10 | { 11 | private readonly int start; 12 | private readonly string text; 13 | 14 | protected CaptureNode(int start, string text, Position position) : base(position) 15 | { 16 | this.start = start; 17 | this.text = text; 18 | } 19 | 20 | public string Text 21 | { 22 | get { return this.text; } 23 | } 24 | 25 | public sealed override Span Span 26 | { 27 | get { return new Span(this.start, this.text.Length); } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/ClassBlockStart.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | [Description("Starts a class feature control block, which contains Visual Basic or Visual C# code (methods, fields, properties, etc.) that will become a part of the compiled TextTransformation class.")] 11 | internal sealed class ClassBlockStart : CodeBlockStart 12 | { 13 | public ClassBlockStart(int start, Position position = default(Position)) : base(start, position) 14 | { 15 | } 16 | 17 | public override SyntaxKind Kind 18 | { 19 | get { return SyntaxKind.ClassBlockStart; } 20 | } 21 | 22 | public override Span Span 23 | { 24 | get { return new Span(this.Start, 3); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitClassBlockStart(this); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Code.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal sealed class Code : TerminalNode 10 | { 11 | private readonly Span span; 12 | 13 | public Code(Span span, Position position = default(Position)) : base(position) 14 | { 15 | this.span = span; 16 | } 17 | 18 | public override SyntaxKind Kind 19 | { 20 | get { return SyntaxKind.Code; } 21 | } 22 | 23 | public override Span Span 24 | { 25 | get { return this.span; } 26 | } 27 | 28 | protected internal override void Accept(SyntaxNodeVisitor visitor) 29 | { 30 | visitor.VisitCode(this); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/CodeBlock.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using Microsoft.VisualStudio.Text; 10 | 11 | internal sealed class CodeBlock : NonterminalNode 12 | { 13 | private readonly CodeBlockStart start; 14 | private readonly Code code; 15 | private readonly BlockEnd end; 16 | 17 | public CodeBlock(CodeBlockStart start, BlockEnd end) 18 | { 19 | Debug.Assert(start != null, "start"); 20 | Debug.Assert(end != null, "end"); 21 | this.start = start; 22 | this.end = end; 23 | } 24 | 25 | public CodeBlock(CodeBlockStart start, Code code, BlockEnd end) : this(start, end) 26 | { 27 | Debug.Assert(code != null, "code"); 28 | this.code = code; 29 | } 30 | 31 | public BlockEnd End 32 | { 33 | get { return this.end; } 34 | } 35 | 36 | public override SyntaxKind Kind 37 | { 38 | get { return SyntaxKind.CodeBlock; } 39 | } 40 | 41 | public override Position Position 42 | { 43 | get { return this.start.Position; } 44 | } 45 | 46 | public override Span Span 47 | { 48 | get { return Span.FromBounds(this.start.Span.Start, this.end.Span.End); } 49 | } 50 | 51 | public CodeBlockStart Start 52 | { 53 | get { return this.start; } 54 | } 55 | 56 | public override IEnumerable ChildNodes() 57 | { 58 | yield return this.start; 59 | 60 | if (this.code != null) 61 | { 62 | yield return this.code; 63 | } 64 | 65 | yield return this.end; 66 | } 67 | 68 | protected internal override void Accept(SyntaxNodeVisitor visitor) 69 | { 70 | visitor.VisitCodeBlock(this); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/CodeBlockStart.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal abstract class CodeBlockStart : SyntaxToken 8 | { 9 | protected CodeBlockStart(int start, Position position) : base(start, position) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/CustomDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Collections.Generic; 8 | using System.ComponentModel; 9 | using System.ComponentModel.DataAnnotations; 10 | using System.Linq; 11 | 12 | [Description("Custom directive.")] 13 | internal sealed class CustomDirective : Directive 14 | { 15 | public CustomDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 16 | : base(start, name, attributes, end) 17 | { 18 | } 19 | 20 | [Required(ErrorMessage = "The Processor attribute is required")] 21 | [Description("Name of a custom directive processor.")] 22 | public string Processor 23 | { 24 | get { return this.GetAttributeValue(); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitCustomDirective(this); 30 | } 31 | 32 | protected override IEnumerable ValidateAttributes() 33 | { 34 | // Custom directives can contain any custom attributes they need 35 | return Enumerable.Empty(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/DirectiveBlockStart.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | [Description("Starts a directive, which provides instructions to the text template transformation engine on how to process the template.")] 11 | internal sealed class DirectiveBlockStart : SyntaxToken 12 | { 13 | public DirectiveBlockStart(int start, Position position = default(Position)) : base(start, position) 14 | { 15 | } 16 | 17 | public override SyntaxKind Kind 18 | { 19 | get { return SyntaxKind.DirectiveBlockStart; } 20 | } 21 | 22 | public override Span Span 23 | { 24 | get { return new Span(this.Start, 3); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitDirectiveBlockStart(this); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/DirectiveName.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal sealed class DirectiveName : CaptureNode 8 | { 9 | public DirectiveName(int start, string text, Position position = default(Position)) : base(start, text, position) 10 | { 11 | } 12 | 13 | public override SyntaxKind Kind 14 | { 15 | get { return SyntaxKind.DirectiveName; } 16 | } 17 | 18 | protected internal override void Accept(SyntaxNodeVisitor visitor) 19 | { 20 | visitor.VisitDirectiveName(this); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/DoubleQuote.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal sealed class DoubleQuote : SyntaxToken 10 | { 11 | public DoubleQuote(int start, Position position = default(Position)) : base(start, position) 12 | { 13 | } 14 | 15 | public override SyntaxKind Kind 16 | { 17 | get { return SyntaxKind.DoubleQuote; } 18 | } 19 | 20 | public override Span Span 21 | { 22 | get { return new Span(this.Start, 1); } 23 | } 24 | 25 | protected internal override void Accept(SyntaxNodeVisitor visitor) 26 | { 27 | visitor.VisitDoubleQuote(this); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/EndOfFile.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal sealed class EndOfFile : SyntaxToken 10 | { 11 | public EndOfFile(int start, Position position = default(Position)) : base(start, position) 12 | { 13 | } 14 | 15 | public override SyntaxKind Kind 16 | { 17 | get { return SyntaxKind.EOF; } 18 | } 19 | 20 | public override Span Span 21 | { 22 | get { return new Span(this.Start, 0); } 23 | } 24 | 25 | protected internal override void Accept(SyntaxNodeVisitor visitor) 26 | { 27 | visitor.VisitEndOfFile(this); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Equals.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal sealed class Equals : SyntaxToken 10 | { 11 | public Equals(int start, Position position = default(Position)) : base(start, position) 12 | { 13 | } 14 | 15 | public override SyntaxKind Kind 16 | { 17 | get { return SyntaxKind.Equals; } 18 | } 19 | 20 | public override Span Span 21 | { 22 | get { return new Span(this.Start, 1); } 23 | } 24 | 25 | protected internal override void Accept(SyntaxNodeVisitor visitor) 26 | { 27 | visitor.VisitEquals(this); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/ExpressionBlockStart.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | [Description("Starts an expression control block, which contains a Visual Basic or Visual C# expression that will be converted to a string and written to the output file.")] 11 | internal sealed class ExpressionBlockStart : CodeBlockStart 12 | { 13 | public ExpressionBlockStart(int start, Position position = default(Position)) : base(start, position) 14 | { 15 | } 16 | 17 | public override SyntaxKind Kind 18 | { 19 | get { return SyntaxKind.ExpressionBlockStart; } 20 | } 21 | 22 | public override Span Span 23 | { 24 | get { return new Span(this.Start, 3); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitExpressionBlockStart(this); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/src/T4Toolbox.TemplateAnalysis/GlobalSuppressions.cs -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/HashCode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal static class HashCode 8 | { 9 | internal static int Combine(int hashCode1, int hashCode2) 10 | { 11 | return (hashCode1 << 5) + hashCode1 ^ hashCode2; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/ImportDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.ComponentModel.DataAnnotations; 11 | using System.Diagnostics; 12 | 13 | [DisplayName("import"), Description("Allows the use of types in a namespace without providing a fully-qualified name. It is the equivalent of using in C# or imports in Visual Basic.")] 14 | internal sealed class ImportDirective : Directive 15 | { 16 | public ImportDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 17 | : base(start, name, attributes, end) 18 | { 19 | Debug.Assert(name.Text.Equals("import", StringComparison.OrdinalIgnoreCase), "name"); 20 | } 21 | 22 | [Required(ErrorMessage = "The Namespace attribute is required")] 23 | [Description("The fully-qualified name of the namespace being imported. Can be a string of namespaces nested to any level.")] 24 | public string Namespace 25 | { 26 | get { return this.GetAttributeValue(); } 27 | } 28 | 29 | protected internal override void Accept(SyntaxNodeVisitor visitor) 30 | { 31 | visitor.VisitImportDirective(this); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/IncludeDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.ComponentModel.DataAnnotations; 11 | using System.Diagnostics; 12 | 13 | [DisplayName("include"), Description("Includes text from another file in the current template.")] 14 | internal sealed class IncludeDirective : Directive 15 | { 16 | public IncludeDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 17 | : base(start, name, attributes, end) 18 | { 19 | Debug.Assert(name.Text.Equals("include", StringComparison.OrdinalIgnoreCase), "name"); 20 | } 21 | 22 | [Required(ErrorMessage = "The File attribute is required")] 23 | [Description("Absolute or relative path to the included file.")] 24 | public string File 25 | { 26 | get { return this.GetAttributeValue(); } 27 | } 28 | 29 | protected internal override void Accept(SyntaxNodeVisitor visitor) 30 | { 31 | visitor.VisitIncludeDirective(this); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/KnownValuesAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel.DataAnnotations; 10 | using System.Diagnostics; 11 | using System.Linq; 12 | using System.Linq.Expressions; 13 | using System.Reflection; 14 | 15 | [AttributeUsage(AttributeTargets.Property)] 16 | internal sealed class KnownValuesAttribute : System.Attribute 17 | { 18 | private readonly Func> getKnownValues; 19 | private IReadOnlyList knownValues; 20 | 21 | public KnownValuesAttribute(Type enumType) 22 | { 23 | this.getKnownValues = () => GetKnownValues(enumType); 24 | } 25 | 26 | public KnownValuesAttribute(Type factoryType, string methodName) 27 | { 28 | Debug.Assert(factoryType != null, "factoryType"); 29 | Debug.Assert(methodName != null, "methodName"); 30 | 31 | MethodInfo factoryMethod = factoryType.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Static); 32 | 33 | Debug.Assert(factoryMethod != null, "factoryMethod"); 34 | 35 | this.getKnownValues = Expression 36 | .Lambda>>(Expression.Call(factoryMethod)) 37 | .Compile(); 38 | } 39 | 40 | public IReadOnlyList KnownValues 41 | { 42 | get { return this.knownValues ?? (this.knownValues = this.getKnownValues().ToList()); } 43 | } 44 | 45 | private static ValueDescriptor CreateValueDescriptor(FieldInfo enumValue) 46 | { 47 | Debug.Assert(enumValue != null, "enumValue"); 48 | 49 | string displayName = null; 50 | string description = null; 51 | 52 | var displayAttribute = enumValue.GetCustomAttribute(); 53 | if (displayAttribute != null) 54 | { 55 | displayName = displayAttribute.Name; 56 | description = displayAttribute.Description; 57 | } 58 | 59 | displayName = displayName ?? enumValue.Name; 60 | 61 | return new ValueDescriptor(displayName, description); 62 | } 63 | 64 | private static IEnumerable GetKnownValues(Type enumType) 65 | { 66 | Debug.Assert(enumType != null, "null"); 67 | Debug.Assert(enumType.IsEnum, "IsEnum"); 68 | return enumType 69 | .GetFields(BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public) 70 | .Select(CreateValueDescriptor); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/NonterminalNode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Collections.Generic; 8 | 9 | internal abstract class NonterminalNode : SyntaxNode 10 | { 11 | public override string ToString() 12 | { 13 | return this.Kind.ToString() + "(" + string.Join(", ", this.ChildNodes()) + ")"; 14 | } 15 | 16 | public override IEnumerable Validate() 17 | { 18 | foreach (SyntaxNode childNode in this.ChildNodes()) 19 | { 20 | foreach (TemplateError error in childNode.Validate()) 21 | { 22 | yield return error; 23 | } 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/OutputDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.ComponentModel.DataAnnotations; 11 | using System.Linq; 12 | using System.Text; 13 | 14 | [DisplayName("output"), Description("Defines extension and encoding of the output file.")] 15 | internal sealed class OutputDirective : Directive 16 | { 17 | public OutputDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 18 | : base(start, name, attributes, end) 19 | { 20 | } 21 | 22 | [Required(ErrorMessage = "The Extension attribute is required")] 23 | [Description("Extension of the output file.")] 24 | public string Extension 25 | { 26 | get { return this.GetAttributeValue(); } 27 | } 28 | 29 | [KnownValues(typeof(OutputDirective), "GetKnownEncodingValues")] 30 | [Description("Encoding of the output file.")] 31 | public string Encoding 32 | { 33 | get { return this.GetAttributeValue(); } 34 | } 35 | 36 | protected internal override void Accept(SyntaxNodeVisitor visitor) 37 | { 38 | visitor.VisitOutputDirective(this); 39 | } 40 | 41 | private static IEnumerable GetKnownEncodingValues() 42 | { 43 | var uniqueNames = new HashSet(StringComparer.OrdinalIgnoreCase); 44 | foreach (EncodingInfo encoding in System.Text.Encoding.GetEncodings()) 45 | { 46 | // Eliminate encodings that differ only by casing 47 | if (uniqueNames.Add(encoding.Name)) 48 | { 49 | yield return new ValueDescriptor(encoding.Name, encoding.DisplayName); 50 | } 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/ParameterDirective.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.ComponentModel.DataAnnotations; 11 | using System.Diagnostics; 12 | 13 | [DisplayName("parameter"), Description("Declares a property in template code initialized with a value passed in from the external context.")] 14 | internal sealed class ParameterDirective : Directive 15 | { 16 | public ParameterDirective(DirectiveBlockStart start, DirectiveName name, IEnumerable attributes, BlockEnd end) 17 | : base(start, name, attributes, end) 18 | { 19 | Debug.Assert(name.Text.Equals("parameter", StringComparison.OrdinalIgnoreCase), "name"); 20 | } 21 | 22 | [DisplayName("Name"), Required(ErrorMessage = "The Name attribute is required")] 23 | [Description("Name of the property.")] 24 | public string ParameterName 25 | { 26 | get { return this.GetAttributeValue(); } 27 | } 28 | 29 | [DisplayName("Type"), Required(ErrorMessage = "The Type attribute is required")] 30 | [Description("Fully-qualified name of the property type.")] 31 | public string ParameterType 32 | { 33 | get { return this.GetAttributeValue(); } 34 | } 35 | 36 | protected internal override void Accept(SyntaxNodeVisitor visitor) 37 | { 38 | visitor.VisitParameterDirective(this); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Position.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Globalization; 9 | 10 | internal struct Position : IEquatable 11 | { 12 | private readonly int line; 13 | private readonly int column; 14 | 15 | public Position(int line, int column) 16 | { 17 | this.line = line; 18 | this.column = column; 19 | } 20 | 21 | public int Line 22 | { 23 | get { return this.line; } 24 | } 25 | 26 | public int Column 27 | { 28 | get { return this.column; } 29 | } 30 | 31 | public bool Equals(Position other) 32 | { 33 | return this.Line == other.Line && this.Column == other.Column; 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return HashCode.Combine(this.Line.GetHashCode(), this.Column.GetHashCode()); 39 | } 40 | 41 | public override bool Equals(object other) 42 | { 43 | return (other is Position) && this.Equals((Position)other); 44 | } 45 | 46 | public override string ToString() 47 | { 48 | return string.Format(CultureInfo.InvariantCulture, "({0},{1})", this.Line, this.Column); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | using System; 6 | 7 | [assembly: CLSCompliant(true)] -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/StatementBlockStart.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | [Description("Starts a statement control block, which contains Visual Basic or Visual C# code that will become a part of the TransformText method in the compiled TextTransformation class.")] 11 | internal sealed class StatementBlockStart : CodeBlockStart 12 | { 13 | public StatementBlockStart(int start, Position position = default(Position)) : base(start, position) 14 | { 15 | } 16 | 17 | public override SyntaxKind Kind 18 | { 19 | get { return SyntaxKind.StatementBlockStart; } 20 | } 21 | 22 | public override Span Span 23 | { 24 | get { return new Span(this.Start, 2); } 25 | } 26 | 27 | protected internal override void Accept(SyntaxNodeVisitor visitor) 28 | { 29 | visitor.VisitStatementBlockStart(this); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/SyntaxToken.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | internal abstract class SyntaxToken : TerminalNode 8 | { 9 | private readonly int start; 10 | 11 | protected SyntaxToken(int start, Position position) : base(position) 12 | { 13 | this.start = start; 14 | } 15 | 16 | protected int Start 17 | { 18 | get { return this.start; } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/Template.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using Microsoft.VisualStudio.Text; 11 | 12 | internal sealed class Template : NonterminalNode 13 | { 14 | private readonly SyntaxNode[] childNodes; 15 | 16 | public Template(params SyntaxNode[] childNodes) 17 | { 18 | Debug.Assert(childNodes != null, "childNodes"); 19 | this.childNodes = childNodes; 20 | } 21 | 22 | public override SyntaxKind Kind 23 | { 24 | get { return SyntaxKind.Template; } 25 | } 26 | 27 | public override Position Position 28 | { 29 | get { return new Position(0, 0); } 30 | } 31 | 32 | public override Span Span 33 | { 34 | get 35 | { 36 | if (this.childNodes.Length == 0) 37 | { 38 | return new Span(); 39 | } 40 | 41 | int start = int.MaxValue; 42 | int end = 0; 43 | foreach (SyntaxNode child in this.childNodes) 44 | { 45 | start = Math.Min(start, child.Span.Start); 46 | end = Math.Max(end, child.Span.End); 47 | } 48 | 49 | return Span.FromBounds(start, end); 50 | } 51 | } 52 | 53 | public override IEnumerable ChildNodes() 54 | { 55 | return this.childNodes; 56 | } 57 | 58 | protected internal override void Accept(SyntaxNodeVisitor visitor) 59 | { 60 | visitor.VisitTemplate(this); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/TemplateError.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Diagnostics; 8 | using Microsoft.VisualStudio.Text; 9 | 10 | internal class TemplateError 11 | { 12 | public TemplateError(string message, Span span, Position position) 13 | { 14 | Debug.Assert(message != null, "message"); 15 | 16 | this.Message = message; 17 | this.Position = position; 18 | this.Span = span; 19 | } 20 | 21 | public string Message { get; private set; } 22 | 23 | public Position Position { get; private set; } 24 | 25 | public Span Span { get; private set; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/TemplateLanguage.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel.DataAnnotations; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | internal enum TemplateLanguage 15 | { 16 | [Display(Name = "C#", Description = "Visual C#. C# is the default template language.")] 17 | CSharp, 18 | 19 | [Display(Name = "VB", Description = "Visual Basic")] 20 | VisualBasic 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/TemplateVisibility.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.ComponentModel.DataAnnotations; 8 | 9 | internal enum TemplateVisibility 10 | { 11 | [Display(Name = "public", Description = "Changes visibility of generated template class to public. Public is the default.")] 12 | Public, 13 | 14 | [Display(Name = "internal", Description = "Changes visibility of generated template class to internal.")] 15 | Internal 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/TerminalNode.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | 10 | internal abstract class TerminalNode : SyntaxNode 11 | { 12 | private readonly Position position; 13 | 14 | protected TerminalNode(Position position) 15 | { 16 | this.position = position; 17 | } 18 | 19 | public override Position Position 20 | { 21 | get { return this.position; } 22 | } 23 | 24 | public sealed override IEnumerable ChildNodes() 25 | { 26 | return Enumerable.Empty(); 27 | } 28 | 29 | public override string ToString() 30 | { 31 | return this.Kind.ToString() + this.Span.ToString() + this.Position.ToString(); 32 | } 33 | 34 | public override IEnumerable Validate() 35 | { 36 | return Enumerable.Empty(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/ValueDescriptor.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Diagnostics; 8 | 9 | /// 10 | /// Encapsulates metadata describing an attribute value. 11 | /// 12 | internal sealed class ValueDescriptor 13 | { 14 | public ValueDescriptor(string displayName, string description = null) 15 | { 16 | Debug.Assert(!string.IsNullOrWhiteSpace(displayName), "displayName"); 17 | this.DisplayName = displayName; 18 | this.Description = description ?? string.Empty; 19 | } 20 | 21 | public string DisplayName { get; private set; } 22 | 23 | public string Description { get; private set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/T4Toolbox.TemplateAnalysis/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/ClassificationTypeDefinitions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.ComponentModel.Composition; 8 | using Microsoft.VisualStudio.Text.Classification; 9 | using Microsoft.VisualStudio.Utilities; 10 | 11 | /// 12 | /// Provides metadata information for registering text template classification types with the Visual Studio editor. 13 | /// 14 | internal static class ClassificationTypeDefinitions 15 | { 16 | [Export, Name(ClassificationTypeName.AttributeName)] 17 | internal static ClassificationTypeDefinition AttributeName { get; set; } 18 | 19 | [Export, Name(ClassificationTypeName.AttributeValue)] 20 | internal static ClassificationTypeDefinition AttributeValue { get; set; } 21 | 22 | [Export, Name(ClassificationTypeName.CodeBlock)] 23 | internal static ClassificationTypeDefinition CodeBlock { get; set; } 24 | 25 | [Export, Name(ClassificationTypeName.Delimiter)] 26 | internal static ClassificationTypeDefinition Delimiter { get; set; } 27 | 28 | [Export, Name(ClassificationTypeName.DirectiveName)] 29 | internal static ClassificationTypeDefinition DirectiveName { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/ClassificationTypeName.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | /// 8 | /// Defines names of Text Template classification types. 9 | /// 10 | internal static class ClassificationTypeName 11 | { 12 | internal const string AttributeName = TemplateContentType.Name + ".AttributeName"; 13 | internal const string AttributeValue = TemplateContentType.Name + ".AttributeValue"; 14 | internal const string CodeBlock = TemplateContentType.Name + ".CodeBlock"; 15 | internal const string Delimiter = TemplateContentType.Name + ".Delimiter"; 16 | internal const string DirectiveName = TemplateContentType.Name + ".DirectiveName"; 17 | } 18 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/ITemplateEditorOptions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | internal interface ITemplateEditorOptions 8 | { 9 | bool CompletionListsEnabled { get; } 10 | 11 | bool ErrorReportingEnabled { get; } 12 | 13 | bool ErrorUnderliningEnabled { get; } 14 | 15 | bool QuickInfoTooltipsEnabled { get; } 16 | 17 | bool SyntaxColorizationEnabled { get; } 18 | 19 | bool TemplateOutliningEnabled { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateAnalysis.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using Microsoft.VisualStudio.Text; 10 | using T4Toolbox.TemplateAnalysis; 11 | 12 | internal class TemplateAnalysis : EventArgs 13 | { 14 | public TemplateAnalysis(ITextSnapshot textSnapshot, Template template, IReadOnlyList errors) 15 | { 16 | this.TextSnapshot = textSnapshot; 17 | this.Template = template; 18 | this.Errors = errors; 19 | } 20 | 21 | public IReadOnlyList Errors { get; private set; } 22 | 23 | public Template Template { get; private set; } 24 | 25 | public ITextSnapshot TextSnapshot { get; private set; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateAnalyzer.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using Microsoft.VisualStudio.Text; 11 | using T4Toolbox.TemplateAnalysis; 12 | 13 | internal sealed class TemplateAnalyzer 14 | { 15 | private TemplateAnalyzer(ITextBuffer textBuffer) 16 | { 17 | textBuffer.Changed += this.BufferChanged; 18 | this.ParseTextSnapshot(textBuffer.CurrentSnapshot); 19 | } 20 | 21 | public event EventHandler TemplateChanged; 22 | 23 | public TemplateAnalysis CurrentAnalysis { get; private set; } 24 | 25 | public static TemplateAnalyzer GetOrCreate(ITextBuffer buffer) 26 | { 27 | Debug.Assert(buffer != null, "buffer"); 28 | return buffer.Properties.GetOrCreateSingletonProperty(() => new TemplateAnalyzer(buffer)); 29 | } 30 | 31 | private void BufferChanged(object sender, TextContentChangedEventArgs e) 32 | { 33 | this.ParseTextSnapshot(e.After); 34 | } 35 | 36 | private void OnTemplateChanged(TemplateAnalysis templateAnalysis) 37 | { 38 | this.CurrentAnalysis = templateAnalysis; 39 | 40 | EventHandler handler = this.TemplateChanged; 41 | if (handler != null) 42 | { 43 | handler(this, templateAnalysis); 44 | } 45 | } 46 | 47 | private void ParseTextSnapshot(ITextSnapshot snapshot) 48 | { 49 | var scanner = new TemplateScanner(snapshot.GetText()); 50 | 51 | var parser = new TemplateParser(scanner); 52 | parser.Parse(); 53 | 54 | // Always return a template object, even if the parser couldn't build one, to avoid downstream errors. 55 | Template template = parser.Template ?? new Template(); 56 | 57 | var errors = new List(parser.Errors); 58 | errors.AddRange(template.Validate()); 59 | 60 | this.OnTemplateChanged(new TemplateAnalysis(snapshot, template, errors)); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateClassificationTaggerProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.ComponentModel.Composition; 9 | using Microsoft.VisualStudio.Text; 10 | using Microsoft.VisualStudio.Text.Classification; 11 | using Microsoft.VisualStudio.Text.Tagging; 12 | using Microsoft.VisualStudio.Utilities; 13 | 14 | [Export(typeof(ITaggerProvider)), TagType(typeof(ClassificationTag)), ContentType(TemplateContentType.Name)] 15 | internal sealed class TemplateClassificationTaggerProvider : ITaggerProvider 16 | { 17 | private readonly ITemplateEditorOptions options; 18 | private readonly IClassificationTypeRegistryService classificationTypeRegistry; 19 | 20 | [ImportingConstructor] 21 | public TemplateClassificationTaggerProvider(ITemplateEditorOptions options, IClassificationTypeRegistryService classificationTypeRegistry) 22 | { 23 | if (options == null) 24 | { 25 | throw new ArgumentNullException(nameof(options)); 26 | } 27 | 28 | if (classificationTypeRegistry == null) 29 | { 30 | throw new ArgumentNullException(nameof(classificationTypeRegistry)); 31 | } 32 | 33 | this.options = options; 34 | this.classificationTypeRegistry = classificationTypeRegistry; 35 | } 36 | 37 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag 38 | { 39 | if (this.options.SyntaxColorizationEnabled) 40 | { 41 | return buffer.Properties.GetOrCreateSingletonProperty(() => new TemplateClassificationTagger(buffer, this.classificationTypeRegistry)) as ITagger; 42 | } 43 | 44 | return null; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateCompletionSource.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | using System.Linq; 11 | using Microsoft.VisualStudio.Language.Intellisense; 12 | using Microsoft.VisualStudio.Text; 13 | 14 | internal sealed class TemplateCompletionSource : ICompletionSource 15 | { 16 | private readonly ITextBuffer buffer; 17 | private readonly TemplateAnalyzer analyzer; 18 | 19 | internal TemplateCompletionSource(ITextBuffer buffer) 20 | { 21 | Debug.Assert(buffer != null, "buffer"); 22 | 23 | this.buffer = buffer; 24 | this.analyzer = TemplateAnalyzer.GetOrCreate(buffer); 25 | } 26 | 27 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "This method is called by the Visual Studio editor and expects to receive valid arguments")] 28 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Justification = "This method is called by the Visual Studio editor and expects to receive valid arguments")] 29 | public void AugmentCompletionSession(ICompletionSession session, IList completionSets) 30 | { 31 | Debug.Assert(session != null, "session"); 32 | Debug.Assert(completionSets != null, "completionSets"); 33 | 34 | TemplateAnalysis current = this.analyzer.CurrentAnalysis; 35 | var builder = new TemplateCompletionBuilder(session.GetTriggerPoint(current.TextSnapshot).Value.Position); 36 | builder.Visit(current.Template); 37 | if (builder.Completions != null) 38 | { 39 | ITrackingSpan applicableTo = current.TextSnapshot.CreateTrackingSpan(builder.Node.Span, SpanTrackingMode.EdgeInclusive); 40 | IEnumerable completions = builder.Completions.OrderBy(completion => completion.DisplayText); 41 | var completionSet = new CompletionSet("All", "All", applicableTo, completions, null); 42 | completionSets.Add(completionSet); 43 | } 44 | } 45 | 46 | public void Dispose() 47 | { 48 | this.buffer.Properties.RemoveProperty(this.GetType()); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateCompletionSourceProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.ComponentModel.Composition; 8 | using System.Diagnostics; 9 | using System.Diagnostics.CodeAnalysis; 10 | using Microsoft.VisualStudio.Language.Intellisense; 11 | using Microsoft.VisualStudio.Text; 12 | using Microsoft.VisualStudio.Utilities; 13 | 14 | [Export(typeof(ICompletionSourceProvider)), Name(TemplateContentType.Name), ContentType(TemplateContentType.Name)] 15 | internal sealed class TemplateCompletionSourceProvider : ICompletionSourceProvider 16 | { 17 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "This method is called by only by the Visual Studio editor and assumes that a textBuffer is supplied")] 18 | public ICompletionSource TryCreateCompletionSource(ITextBuffer textBuffer) 19 | { 20 | Debug.Assert(textBuffer != null, "textBuffer"); 21 | return textBuffer.Properties.GetOrCreateSingletonProperty(() => new TemplateCompletionSource(textBuffer)); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateContentType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.ComponentModel.Composition; 8 | using Microsoft.VisualStudio.Utilities; 9 | 10 | internal static class TemplateContentType 11 | { 12 | internal const string Name = "TextTemplate"; 13 | 14 | [Export, Name(Name), BaseDefinition("code")] 15 | internal static ContentTypeDefinition Definition { get; set; } // Used for metadata only 16 | 17 | [Export, FileExtension(".tt"), ContentType(Name)] 18 | internal static FileExtensionToContentTypeDefinition FileAssociation { get; set; } // Used for metadata only 19 | } 20 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateErrorReporterProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.ComponentModel.Composition; 9 | using Microsoft.VisualStudio.Shell; 10 | using Microsoft.VisualStudio.Text; 11 | using Microsoft.VisualStudio.Text.Tagging; 12 | using Microsoft.VisualStudio.Utilities; 13 | 14 | [Export(typeof(ITaggerProvider)), TagType(typeof(ErrorTag)), ContentType(TemplateContentType.Name)] 15 | internal sealed class TemplateErrorReporterProvider : ITaggerProvider 16 | { 17 | private readonly ITemplateEditorOptions options; 18 | private readonly IServiceProvider serviceProvider; 19 | private readonly ITextDocumentFactoryService textDocumentFactory; 20 | 21 | [ImportingConstructor] 22 | public TemplateErrorReporterProvider( 23 | ITemplateEditorOptions options, 24 | SVsServiceProvider serviceProvider, 25 | ITextDocumentFactoryService textDocumentFactory) 26 | { 27 | if (options == null) 28 | { 29 | throw new ArgumentNullException(nameof(options)); 30 | } 31 | 32 | if (serviceProvider == null) 33 | { 34 | throw new ArgumentNullException(nameof(serviceProvider)); 35 | } 36 | 37 | if (textDocumentFactory == null) 38 | { 39 | throw new ArgumentNullException(nameof(textDocumentFactory)); 40 | } 41 | 42 | this.options = options; 43 | this.serviceProvider = serviceProvider; 44 | this.textDocumentFactory = textDocumentFactory; 45 | } 46 | 47 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag 48 | { 49 | if (this.options.ErrorReportingEnabled) 50 | { 51 | TemplateErrorReporter.GetOrCreate(buffer, this.serviceProvider, this.textDocumentFactory); 52 | } 53 | 54 | return null; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateErrorTagger.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.Diagnostics.CodeAnalysis; 8 | using Microsoft.VisualStudio.Text; 9 | using Microsoft.VisualStudio.Text.Adornments; 10 | using Microsoft.VisualStudio.Text.Tagging; 11 | using T4Toolbox.TemplateAnalysis; 12 | 13 | internal sealed class TemplateErrorTagger : TemplateTagger 14 | { 15 | public TemplateErrorTagger(ITextBuffer buffer) : base(buffer) 16 | { 17 | this.UpdateTagSpans(this.Analyzer.CurrentAnalysis); 18 | } 19 | 20 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "This is an internal method, called by base class.")] 21 | protected override void CreateTagSpans(TemplateAnalysis analysis) 22 | { 23 | ITextSnapshot snapshot = analysis.TextSnapshot; 24 | foreach (TemplateError error in analysis.Errors) 25 | { 26 | this.CreateTagSpan(snapshot.CreateTrackingSpan(error.Span, SpanTrackingMode.EdgeNegative), new ErrorTag(PredefinedErrorTypeNames.SyntaxError, error.Message)); 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateErrorTaggerProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.ComponentModel.Composition; 9 | using Microsoft.VisualStudio.Text; 10 | using Microsoft.VisualStudio.Text.Tagging; 11 | using Microsoft.VisualStudio.Utilities; 12 | 13 | [Export(typeof(ITaggerProvider)), TagType(typeof(ErrorTag)), ContentType(TemplateContentType.Name)] 14 | internal sealed class TemplateErrorTaggerProvider : ITaggerProvider 15 | { 16 | private readonly ITemplateEditorOptions options; 17 | 18 | [ImportingConstructor] 19 | public TemplateErrorTaggerProvider(ITemplateEditorOptions options) 20 | { 21 | if (options == null) 22 | { 23 | throw new ArgumentNullException(nameof(options)); 24 | } 25 | 26 | this.options = options; 27 | } 28 | 29 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag 30 | { 31 | if (buffer == null) 32 | { 33 | throw new ArgumentNullException(nameof(buffer)); 34 | } 35 | 36 | if (this.options.ErrorUnderliningEnabled) 37 | { 38 | return buffer.Properties.GetOrCreateSingletonProperty(() => new TemplateErrorTagger(buffer)) as ITagger; 39 | } 40 | 41 | return null; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateOutliningTaggerProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.ComponentModel.Composition; 9 | using Microsoft.VisualStudio.Text; 10 | using Microsoft.VisualStudio.Text.Tagging; 11 | using Microsoft.VisualStudio.Utilities; 12 | 13 | [Export(typeof(ITaggerProvider)), TagType(typeof(OutliningRegionTag)), ContentType(TemplateContentType.Name)] 14 | internal sealed class TemplateOutliningTaggerProvider : ITaggerProvider 15 | { 16 | private readonly ITemplateEditorOptions options; 17 | 18 | [ImportingConstructor] 19 | public TemplateOutliningTaggerProvider(ITemplateEditorOptions options) 20 | { 21 | if (options == null) 22 | { 23 | throw new ArgumentNullException(nameof(options)); 24 | } 25 | 26 | this.options = options; 27 | } 28 | 29 | public ITagger CreateTagger(ITextBuffer buffer) where T : ITag 30 | { 31 | if (buffer == null) 32 | { 33 | throw new ArgumentNullException(nameof(buffer)); 34 | } 35 | 36 | if (this.options.TemplateOutliningEnabled) 37 | { 38 | return buffer.Properties.GetOrCreateSingletonProperty(() => new TemplateOutliningTagger(buffer)) as ITagger; 39 | } 40 | 41 | return null; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateQuickInfoSource.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using Microsoft.VisualStudio.Language.Intellisense; 11 | using Microsoft.VisualStudio.Text; 12 | 13 | internal sealed class TemplateQuickInfoSource : IQuickInfoSource 14 | { 15 | private readonly TemplateAnalyzer analyzer; 16 | 17 | public TemplateQuickInfoSource(ITextBuffer buffer) 18 | { 19 | Debug.Assert(buffer != null, "buffer"); 20 | this.analyzer = TemplateAnalyzer.GetOrCreate(buffer); 21 | } 22 | 23 | public void AugmentQuickInfoSession(IQuickInfoSession session, IList quickInfoContent, out ITrackingSpan applicableToSpan) 24 | { 25 | if (session == null) 26 | { 27 | throw new ArgumentNullException("session"); 28 | } 29 | 30 | if (quickInfoContent == null) 31 | { 32 | throw new ArgumentNullException("quickInfoContent"); 33 | } 34 | 35 | TemplateAnalysis analysis = this.analyzer.CurrentAnalysis; 36 | SnapshotPoint? triggerPoint = session.GetTriggerPoint(analysis.TextSnapshot); 37 | if (triggerPoint != null && analysis.Template != null) 38 | { 39 | string description; 40 | Span applicableTo; 41 | if (analysis.Template.TryGetDescription(triggerPoint.Value.Position, out description, out applicableTo)) 42 | { 43 | quickInfoContent.Add(description); 44 | applicableToSpan = analysis.TextSnapshot.CreateTrackingSpan(applicableTo, SpanTrackingMode.EdgeExclusive); 45 | return; 46 | } 47 | } 48 | 49 | applicableToSpan = null; 50 | } 51 | 52 | public void Dispose() 53 | { 54 | GC.SuppressFinalize(this); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateQuickInfoSourceProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.ComponentModel.Composition; 9 | using Microsoft.VisualStudio.Language.Intellisense; 10 | using Microsoft.VisualStudio.Text; 11 | using Microsoft.VisualStudio.Utilities; 12 | 13 | [Export(typeof(IQuickInfoSourceProvider)), ContentType(TemplateContentType.Name)] 14 | [Name("Template Quick Info Source"), Order(Before = "Default Quick Info Presenter")] 15 | internal sealed class TemplateQuickInfoSourceProvider : IQuickInfoSourceProvider 16 | { 17 | private readonly ITemplateEditorOptions options; 18 | 19 | [ImportingConstructor] 20 | public TemplateQuickInfoSourceProvider(ITemplateEditorOptions options) 21 | { 22 | if (options == null) 23 | { 24 | throw new ArgumentNullException(nameof(options)); 25 | } 26 | 27 | this.options = options; 28 | } 29 | 30 | public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer buffer) 31 | { 32 | if (buffer == null) 33 | { 34 | throw new ArgumentNullException(nameof(buffer)); 35 | } 36 | 37 | if (this.options.QuickInfoTooltipsEnabled) 38 | { 39 | return buffer.Properties.GetOrCreateSingletonProperty(() => new TemplateQuickInfoSource(buffer)); 40 | } 41 | 42 | return null; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/TemplateTagger.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.Windows; 8 | using Microsoft.VisualStudio.Text; 9 | using Microsoft.VisualStudio.Text.Tagging; 10 | using T4Toolbox.TemplateAnalysis; 11 | 12 | internal abstract class TemplateTagger : SimpleTagger where T : ITag 13 | { 14 | private readonly TemplateAnalyzer analyzer; 15 | 16 | protected TemplateTagger(ITextBuffer buffer) : base(buffer) 17 | { 18 | this.analyzer = TemplateAnalyzer.GetOrCreate(buffer); 19 | WeakEventManager.AddHandler(this.analyzer, "TemplateChanged", this.TemplateChanged); 20 | } 21 | 22 | protected TemplateAnalyzer Analyzer 23 | { 24 | get { return this.analyzer; } 25 | } 26 | 27 | protected abstract void CreateTagSpans(TemplateAnalysis analysis); 28 | 29 | protected void UpdateTagSpans(TemplateAnalysis templateAnalysis) 30 | { 31 | using (this.Update()) 32 | { 33 | this.RemoveTagSpans(trackingTagSpan => true); // remove all tag spans 34 | this.CreateTagSpans(templateAnalysis); 35 | } 36 | } 37 | 38 | private void TemplateChanged(object sender, TemplateAnalysis currentAnalysis) 39 | { 40 | this.UpdateTagSpans(currentAnalysis); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.Editor/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Generator/Generator.tt: -------------------------------------------------------------------------------- 1 | <#+ 2 | // 3 | // Copyright © $registeredorganization$. All Rights Reserved. 4 | // 5 | 6 | public class $fileinputname$ : Generator 7 | { 8 | protected override void RunCore() 9 | { 10 | 11 | } 12 | } 13 | #> 14 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Generator/Generator.vstemplate: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | Generator.tt 12 | Generator 13 | An empty code generator 14 | CSharp 15 | 16 | 17 | 18 | Generator.tt 19 | 20 | 21 | 22 | 23 | 24 | 25 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 26 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 27 | 28 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Script/Script.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" debug="True" #> 2 | <#@ output extension="cs" #> 3 | <#@ include file="T4Toolbox.tt" #> 4 | <# 5 | // 6 | // Copyright © $registeredorganization$. All Rights Reserved. 7 | // 8 | 9 | 10 | #> 11 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Script/Script.vstemplate: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | Script.tt 9 | Script 10 | A T4 text template that can generate multiple output files. 11 | CSharp 12 | 13 | 14 | 15 | Script.tt 16 | 17 | 18 | 19 | 20 | 21 | 22 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 23 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 24 | 25 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Template/Template.tt: -------------------------------------------------------------------------------- 1 | <#+ 2 | // 3 | // Copyright © $registeredorganization$. All Rights Reserved. 4 | // 5 | 6 | public class $fileinputname$ : CSharpTemplate 7 | { 8 | public override string TransformText() 9 | { 10 | base.TransformText(); 11 | #> 12 | namespace <#= DefaultNamespace #> 13 | { 14 | public class <#= Identifier("Sample Class") #> 15 | { 16 | private string <#= FieldName("Sample Field") #>; 17 | 18 | public string <#= PropertyName("Sample Property") #> { get; set; } 19 | } 20 | } 21 | <#+ 22 | return this.GenerationEnvironment.ToString(); 23 | } 24 | } 25 | #> 26 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/C#/Template/Template.vstemplate: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | Template.tt 12 | Template 13 | An empty code generation template 14 | CSharp 15 | 16 | 17 | 18 | Template.tt 19 | 20 | 21 | 22 | 23 | 24 | 25 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 26 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 27 | 28 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Generator/Generator.tt: -------------------------------------------------------------------------------- 1 | <#+ 2 | ' 3 | ' Copyright © $registeredorganization$. All Rights Reserved. 4 | ' 5 | 6 | Public Class $fileinputname$ 7 | Inherits Generator 8 | 9 | Protected Overrides Sub RunCore() 10 | 11 | End Sub 12 | 13 | End Class 14 | #> 15 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Generator/Generator.vstemplate: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | Generator.tt 12 | Generator 13 | An empty code generator 14 | VisualBasic 15 | 16 | 17 | 18 | Generator.tt 19 | 20 | 21 | 22 | 23 | 24 | 25 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 26 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 27 | 28 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Script/Script.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="VB" debug="True" #> 2 | <#@ output extension="vb" #> 3 | <#@ include file="T4Toolbox.tt" #> 4 | <# 5 | ' 6 | ' Copyright © $registeredorganization$. All Rights Reserved. 7 | ' 8 | 9 | 10 | #> 11 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Script/Script.vstemplate: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | Script.tt 9 | Script 10 | A T4 text template that can generate multiple output files. 11 | VisualBasic 12 | 13 | 14 | 15 | Script.tt 16 | 17 | 18 | 19 | 20 | 21 | 22 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 23 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 24 | 25 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Template/Template.tt: -------------------------------------------------------------------------------- 1 | <#+ 2 | ' 3 | ' Copyright © $registeredorganization$. All Rights Reserved. 4 | ' 5 | 6 | Public Class $fileinputname$ 7 | Inherits Template 8 | 9 | Public Overrides Function TransformText() As String 10 | 11 | Return Me.GenerationEnvironment.ToString() 12 | End Function 13 | 14 | End Class 15 | #> 16 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio.ItemTemplates/VB/Template/Template.vstemplate: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | Template.tt 12 | Template 13 | An empty code generation template 14 | VisualBasic 15 | 16 | 17 | 18 | Template.tt 19 | 20 | 21 | 22 | 23 | 24 | 25 | Microsoft.VSDesigner, Version=11.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a 26 | Microsoft.VSDesigner.ProjectWizard.ItemPropertyWizard 27 | 28 | -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | using System; 6 | using System.Reflection; 7 | using Microsoft.VisualStudio.Shell; 8 | 9 | [assembly: AssemblyTitle(T4Toolbox.VisualStudio.AssemblyInfo.Name)] 10 | [assembly: CLSCompliant(false)] 11 | 12 | // Help Visual Studio resolve references to the T4Toolbox assembly. 13 | [assembly: ProvideCodeBase( 14 | AssemblyName = T4Toolbox.AssemblyInfo.Name, 15 | PublicKeyToken = T4Toolbox.AssemblyInfo.PublicKeyToken, 16 | Version = T4Toolbox.AssemblyInfo.Version, 17 | CodeBase = @"$PackageFolder$\" + T4Toolbox.AssemblyInfo.Name + ".dll")] 18 | 19 | // This is currently required because MPF enumerates attributes applied to T4ToolboxPackage class when instantiating 20 | // the T4ToolboxOptionsPage. This can be eliminated if I can figure out how to register directive processors via MEF instead 21 | // of ProvideDirectiveProcessorAttribute. 22 | [assembly: ProvideCodeBase( 23 | AssemblyName = T4Toolbox.DirectiveProcessors.AssemblyInfo.Name, 24 | PublicKeyToken = T4Toolbox.DirectiveProcessors.AssemblyInfo.PublicKeyToken, 25 | Version = T4Toolbox.DirectiveProcessors.AssemblyInfo.Version, 26 | CodeBase = @"$PackageFolder$\" + T4Toolbox.DirectiveProcessors.AssemblyInfo.Name + ".dll")] 27 | 28 | // Help Visual Studio resolve references to the T4Toolbox.VisualStudio assembly. 29 | [assembly: ProvideCodeBase( 30 | AssemblyName = T4Toolbox.VisualStudio.AssemblyInfo.Name, 31 | PublicKeyToken = T4Toolbox.VisualStudio.AssemblyInfo.PublicKeyToken, 32 | Version = T4Toolbox.VisualStudio.AssemblyInfo.Version, 33 | CodeBase = @"$PackageFolder$\" + T4Toolbox.VisualStudio.AssemblyInfo.Name + ".dll")] 34 | 35 | namespace T4Toolbox.VisualStudio 36 | { 37 | /// 38 | /// Defines constants describing the T4Toolbox.VisualStudio assembly. 39 | /// 40 | internal abstract class AssemblyInfo : T4Toolbox.AssemblyInfo 41 | { 42 | /// 43 | /// Gets the name of the assembly. 44 | /// 45 | public new const string Name = "T4Toolbox.VisualStudio"; 46 | } 47 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/BrowseObjectExtenderProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio 6 | { 7 | using System; 8 | using EnvDTE; 9 | using Microsoft.VisualStudio.Shell.Interop; 10 | 11 | /// 12 | /// Provides a "Template" property extender for C# and Visual Basic project items. 13 | /// 14 | internal sealed class BrowseObjectExtenderProvider : IExtenderProvider, IDisposable 15 | { 16 | private const string ExtenderName = "T4Toolbox"; 17 | 18 | private readonly string extenderCategory; 19 | private readonly ObjectExtenders objectExtenders; 20 | private readonly int providerCookie; 21 | private readonly IServiceProvider serviceProvider; 22 | 23 | public BrowseObjectExtenderProvider(IServiceProvider serviceProvider, string extenderCategory) 24 | { 25 | this.serviceProvider = serviceProvider; 26 | this.objectExtenders = (ObjectExtenders)serviceProvider.GetService(typeof(ObjectExtenders)); 27 | this.extenderCategory = extenderCategory; 28 | this.providerCookie = this.objectExtenders.RegisterExtenderProvider(extenderCategory, BrowseObjectExtenderProvider.ExtenderName, this); 29 | } 30 | 31 | public bool CanExtend(string extenderCategory, string extenderName, object extendee) 32 | { 33 | return extenderCategory == this.extenderCategory && extenderName == ExtenderName && extendee is IVsBrowseObject; 34 | } 35 | 36 | public void Dispose() 37 | { 38 | this.objectExtenders.UnregisterExtenderProvider(this.providerCookie); 39 | } 40 | 41 | public object GetExtender(string extenderCategory, string extenderName, object extendee, IExtenderSite site, int extenderCookie) 42 | { 43 | return new BrowseObjectExtender(this.serviceProvider, (IVsBrowseObject)extendee, site, extenderCookie); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/EnvDteExtensions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/src/T4Toolbox.VisualStudio/EnvDteExtensions.cs -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/ItemMetadataWizard.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/src/T4Toolbox.VisualStudio/ItemMetadataWizard.cs -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/ProjectItemProperty.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio 6 | { 7 | /// 8 | /// Defines constants for commonly-used VisualStudio project item properties. 9 | /// 10 | internal static class ProjectItemProperty 11 | { 12 | /// 13 | /// Internal name of the "Copy to Output Directory" project item property. 14 | /// 15 | public const string CopyToOutputDirectory = "CopyToOutputDirectory"; 16 | 17 | /// 18 | /// Internal name of the "Custom Tool" project item property. 19 | /// 20 | public const string CustomTool = "CustomTool"; 21 | 22 | /// 23 | /// Internal name of the "Custom Tool Namespace" project item property. 24 | /// 25 | public const string CustomToolNamespace = "CustomToolNamespace"; 26 | 27 | /// 28 | /// Internal name of the "Custom Tool Parameters" project item property provided by the T4 Toolbox. 29 | /// 30 | public const string CustomToolParameters = BrowseObjectExtender.Name + ".CustomToolParameters"; 31 | 32 | /// 33 | /// Internal name of the "Custom Tool Template" project item property provided by the T4 Toolbox. 34 | /// 35 | public const string CustomToolTemplate = BrowseObjectExtender.Name + ".CustomToolTemplate"; 36 | 37 | /// 38 | /// Internal name of the "Build Action" project item property. 39 | /// 40 | public const string ItemType = "ItemType"; 41 | } 42 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/T4ToolboxOptionsPage.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio 6 | { 7 | using System; 8 | using System.Runtime.InteropServices; 9 | using Microsoft.VisualStudio.Shell; 10 | 11 | /// 12 | /// A property grid page for in the Visual Studio Options dialog. 13 | /// 14 | [Guid("7929ACCC-926C-4D90-865A-4BB7D2EFB6D9")] 15 | internal class T4ToolboxOptionsPage : DialogPage 16 | { 17 | private readonly T4ToolboxOptions localOptions = new T4ToolboxOptions(); 18 | 19 | public override object AutomationObject 20 | { 21 | get { return this.localOptions; } 22 | } 23 | 24 | public override void LoadSettingsFromStorage() 25 | { 26 | this.localOptions.CopyFrom(this.GetGlobalOptions()); 27 | } 28 | 29 | public override void SaveSettingsToStorage() 30 | { 31 | this.GetGlobalOptions().CopyFrom(this.localOptions); 32 | } 33 | 34 | protected override void OnApply(PageApplyEventArgs e) 35 | { 36 | base.OnApply(e); 37 | this.GetGlobalOptions().SaveSettingsToStorage(); 38 | } 39 | 40 | protected virtual T4ToolboxOptions GetGlobalOptions() 41 | { 42 | return T4ToolboxOptions.Instance; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/TemplateLocator.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio 6 | { 7 | using System; 8 | using System.ComponentModel.Design; 9 | using System.Globalization; 10 | using System.IO; 11 | using Microsoft.VisualStudio.TextTemplating; 12 | using Microsoft.VisualStudio.TextTemplating.VSHost; 13 | 14 | /// 15 | /// Internal service for locating a template based on its file name. 16 | /// 17 | internal class TemplateLocator 18 | { 19 | protected TemplateLocator(IServiceProvider serviceProvider) 20 | { 21 | this.ServiceProvider = serviceProvider; 22 | } 23 | 24 | protected IServiceProvider ServiceProvider { get; private set; } 25 | 26 | /// 27 | /// Returns full path to the template file resolved using T4 include rules. 28 | /// 29 | public virtual bool LocateTemplate(string fullInputPath, ref string templatePath) 30 | { 31 | var textTemplating = (ITextTemplating)this.ServiceProvider.GetService(typeof(STextTemplating)); 32 | 33 | // Use the built-in "include" resolution logic to find the template. 34 | string[] references; 35 | textTemplating.PreprocessTemplate(Path.ChangeExtension(fullInputPath, ".tt"), string.Empty, null, "DummyClass", string.Empty, out references); 36 | 37 | var engineHost = (ITextTemplatingEngineHost)textTemplating; 38 | 39 | string templateFileContent; 40 | string templateFullPath; 41 | if (engineHost.LoadIncludeText(templatePath, out templateFileContent, out templateFullPath)) 42 | { 43 | templatePath = Path.GetFullPath(templateFullPath); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | internal static void Register(IServiceContainer serviceContainer) 51 | { 52 | serviceContainer.AddService(typeof(TemplateLocator), CreateService, true); 53 | } 54 | 55 | private static object CreateService(IServiceContainer container, Type serviceType) 56 | { 57 | if (serviceType == typeof(TemplateLocator)) 58 | { 59 | return new TemplateLocator(container); 60 | } 61 | 62 | return null; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/T4Toolbox.VisualStudio/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/T4Toolbox.vsix/Dark.vstheme: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/T4Toolbox.vsix/DarkTheme.pkgdef: -------------------------------------------------------------------------------- 1 | [$RootKey$\Themes\{1ded0138-47ce-435e-84ef-9ec1f439b749}\T4Toolbox] 2 | "Data"=hex:da,00,00,00,0b,00,00,00,01,00,00,00,85,56,a0,75,a8,00,ed,4d,ba,e5,e7,a5,0b,fa,92,9a,05,00,00,00,1c,00,00,00,54,65,78,74,20,54,65,6d,70,6c,61,74,65,20,41,74,74,72,69,62,75,74,65,20,4e,61,6d,65,00,01,9c,dc,fe,ff,1d,00,00,00,54,65,78,74,20,54,65,6d,70,6c,61,74,65,20,41,74,74,72,69,62,75,74,65,20,56,61,6c,75,65,00,01,c8,c8,c8,ff,18,00,00,00,54,65,78,74,20,54,65,6d,70,6c,61,74,65,20,43,6f,64,65,20,42,6c,6f,63,6b,01,50,50,50,ff,00,17,00,00,00,54,65,78,74,20,54,65,6d,70,6c,61,74,65,20,44,65,6c,69,6d,69,74,65,72,01,ff,ff,b3,ff,01,00,00,00,ff,1c,00,00,00,54,65,78,74,20,54,65,6d,70,6c,61,74,65,20,44,69,72,65,63,74,69,76,65,20,4e,61,6d,65,00,01,56,9c,d6,ff 3 | -------------------------------------------------------------------------------- /src/T4Toolbox.vsix/Include/T4Toolbox.tt: -------------------------------------------------------------------------------- 1 | <#@ TransformationContext processor="T4Toolbox.TransformationContextProcessor" #> 2 | <#@ import namespace="T4Toolbox" #> -------------------------------------------------------------------------------- /src/T4Toolbox.vsix/License.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2008 Oleg Sych 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /src/T4Toolbox.vsix/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | T4 Toolbox for Visual Studio 2017 6 | Extends Text Templates with syntax colorization, error reporting, outlining, QuickInfo tooltips, statement completion, generation of multiple output files with source control integration, support for template parameters in Solution Explorer properties and more. 7 | https://github.com/olegsych/T4Toolbox 8 | License.txt 9 | http://olegsych.github.io/T4Toolbox/getting-started.html 10 | https://github.com/olegsych/T4Toolbox/releases 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/T4Toolbox/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | using System; 6 | using System.Reflection; 7 | using System.Runtime.CompilerServices; 8 | 9 | [assembly: AssemblyTitle(T4Toolbox.AssemblyInfo.Name)] 10 | [assembly: CLSCompliant(true)] 11 | 12 | namespace T4Toolbox 13 | { 14 | /// 15 | /// Defines constants for common assembly information. 16 | /// 17 | /// 18 | /// This class is defined here instead of the CommonAssemblyInfo.cs because we need to use the 19 | /// to enable access to internal members for testing. 20 | /// With internals visible to all projects in the solution, defining this class in every project 21 | /// generates compiler errors due to naming collisions. 22 | /// 23 | internal abstract class AssemblyInfo 24 | { 25 | /// 26 | /// Name of the T4 Toolbox assembly. 27 | /// 28 | public const string Name = "T4Toolbox"; 29 | 30 | /// 31 | /// Name of the product. 32 | /// 33 | public const string Product = "T4 Toolbox"; 34 | 35 | /// 36 | /// Description of the product. 37 | /// 38 | public const string Description = "Extends code generation capabilities of Text Templates."; 39 | 40 | #if SIGN_ASSEMBLY 41 | public const string PublicKey = ", PublicKey=00240000048000009400000006020000002400005253413100040000010001005d511b529d32a2542d3c9c5824631a08e8dc6ea3e5a6175989d27df82bb803bd869f9ada9fbc11ce7a99208b7228c6b9b2ce9440bdc61062bf27c01d2633cee0bd0076dc2ca87c5f88a79316cf8b4a9db4d79f8d019b2b289b3a9fedccb610d53d6e3b6d9dfe05d8aee8e5ccb9f5a709ed0c93c88824c552787bded111d02bca"; 42 | public const string PublicKeyToken = "dc4a538672a7b38f"; 43 | #else 44 | public const string PublicKey = ""; 45 | public const string PublicKeyToken = ""; 46 | #endif 47 | 48 | /// 49 | /// Version of the T4 Toolbox assembly. 50 | /// 51 | public const string Version = "15.0.0.0"; 52 | } 53 | } -------------------------------------------------------------------------------- /src/T4Toolbox/ClrTemplate.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | using System; 8 | using System.IO; 9 | using System.Text; 10 | 11 | /// 12 | /// Serves as a base class for templates that produce code in CLR languages, such as C# or Visual Basic. 13 | /// 14 | public abstract class ClrTemplate : Template 15 | { 16 | /// 17 | /// Gets default namespace based on location of the T4 script file in the project. 18 | /// 19 | public string DefaultNamespace 20 | { 21 | get 22 | { 23 | // Start with the root namespace specified for the project 24 | var defaultNamespace = new StringBuilder(this.RootNamespace); 25 | 26 | // Determine relative location of the template file within the project 27 | 28 | // If the file is added to the project as a link from another folder, use the link path instead of the actual file path. 29 | string relativeInputFilePath = this.Context.GetMetadataValue("Link"); 30 | if (string.IsNullOrEmpty(relativeInputFilePath)) 31 | { 32 | // Otherwise determine it based on the location of the input file relative to the location of the project file 33 | string projectFile = this.Context.GetPropertyValue("MSBuildProjectFullPath"); 34 | relativeInputFilePath = FileMethods.GetRelativePath(projectFile, this.Context.InputFile); 35 | } 36 | 37 | // Append folder names to the root namespace 38 | string relativeDirectory = Path.GetDirectoryName(relativeInputFilePath) ?? string.Empty; 39 | foreach (string folderName in relativeDirectory.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries)) 40 | { 41 | if (folderName != ".") 42 | { 43 | defaultNamespace.Append('.'); 44 | defaultNamespace.Append(folderName.Replace(" ", string.Empty)); 45 | } 46 | } 47 | 48 | return defaultNamespace.ToString(); 49 | } 50 | } 51 | 52 | /// 53 | /// Gets the default namespace of the project where the T4 script file is located. 54 | /// 55 | public string RootNamespace 56 | { 57 | get { return this.Context.GetPropertyValue("RootNamespace"); } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/T4Toolbox/CopyToOutputDirectory.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | /// 8 | /// Defines if and when a file is copied to the output directory. 9 | /// 10 | public enum CopyToOutputDirectory 11 | { 12 | /// 13 | /// Do not copy this file to the output directory. 14 | /// 15 | DoNotCopy = 0, 16 | 17 | /// 18 | /// Always copy this file to the output directory. 19 | /// 20 | CopyAlways = 1, 21 | 22 | /// 23 | /// Copy this file to the output directory only if it is 24 | /// newer than the same file in the output directory. 25 | /// 26 | CopyIfNewer = 2, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/T4Toolbox/FileMethods.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | using System; 8 | using System.Globalization; 9 | using System.Text; 10 | 11 | /// 12 | /// File access utility methods. 13 | /// 14 | internal static class FileMethods 15 | { 16 | /// 17 | /// Converts absolute path to a relative path. 18 | /// 19 | /// 20 | /// Full path to the base file. 21 | /// 22 | /// 23 | /// Full path to the target file. 24 | /// 25 | /// 26 | /// Relative path to the specified file. 27 | /// 28 | internal static string GetRelativePath(string fromFile, string toFile) 29 | { 30 | var relativePath = new StringBuilder(260); 31 | if (!NativeMethods.PathRelativePathTo(relativePath, fromFile, 0, toFile, 0)) 32 | { 33 | throw new ArgumentException( 34 | string.Format( 35 | CultureInfo.CurrentCulture, 36 | "Cannot convert '{0}' to a path relative to the location of '{1}'.", 37 | toFile, 38 | fromFile)); 39 | } 40 | 41 | return relativePath.ToString(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/T4Toolbox/ITransformationContextProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | using System.Runtime.InteropServices; 8 | using Microsoft.VisualStudio.TextTemplating.VSHost; 9 | 10 | /// 11 | /// Encapsulates host-specific functionality required by the . 12 | /// 13 | [Guid("2B1575B6-6135-4CCA-820B-63980CF62BC3")] // This is a global Visual Studio service 14 | public interface ITransformationContextProvider 15 | { 16 | /// 17 | /// Returns value of an MSBuild metadata with the specified . 18 | /// 19 | /// 20 | /// An IVsHierarchy object returned by that represents an MSBuild project containing the file. 21 | /// 22 | /// 23 | /// Full path of the file whose metadata is to be returned. 24 | /// 25 | /// 26 | /// Name of the MSBuild metadata element whose value is to be returned. 27 | /// 28 | string GetMetadataValue(object hierarchy, string fileName, string metadataName); 29 | 30 | /// 31 | /// Returns value of an MSBuild property with the specified . 32 | /// 33 | /// 34 | /// An IVsHierarchy object returned by that represents an MSBuild project whose property is to be retrieved. 35 | /// 36 | /// 37 | /// Name of the property in the MSBuild project. 38 | /// 39 | string GetPropertyValue(object hierarchy, string propertyName); 40 | 41 | /// 42 | /// Updates output files generated by a text template. 43 | /// 44 | /// 45 | /// A that contains name of the template file. 46 | /// 47 | /// 48 | /// An array of objects that contain content and attributes of the output files. 49 | /// 50 | void UpdateOutputFiles(string inputFile, OutputFile[] outputFiles); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/T4Toolbox/ItemMetadata.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/src/T4Toolbox/ItemMetadata.cs -------------------------------------------------------------------------------- /src/T4Toolbox/ItemType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | /// 8 | /// Defines the known Build Actions for Visual Studio project items. 9 | /// 10 | public static class ItemType 11 | { 12 | /// 13 | /// No action is taken. 14 | /// 15 | public const string None = "None"; 16 | 17 | /// 18 | /// The file is compiled. 19 | /// 20 | public const string Compile = "Compile"; 21 | 22 | /// 23 | /// The file is included in the Content project output group. 24 | /// 25 | public const string Content = "Content"; 26 | 27 | /// 28 | /// The file is included in the main generated assembly or in a satellite assembly as a resource. 29 | /// 30 | public const string EmbeddedResource = "EmbeddedResource"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/T4Toolbox/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | using System.Runtime.InteropServices; 8 | using System.Text; 9 | 10 | /// 11 | /// Contains native methods used by the T4 Toolbox. 12 | /// 13 | internal static class NativeMethods 14 | { 15 | /// 16 | /// Creates a relative path from one file or folder to another. 17 | /// 18 | /// 19 | /// A pointer to a string that receives the relative path. This buffer is 20 | /// assumed to be at least MAX_PATH characters in size. 21 | /// 22 | /// 23 | /// A pointer to a null-terminated string of maximum length MAX_PATH that 24 | /// contains the path that defines the start of the relative path. 25 | /// 26 | /// 27 | /// The file attributes of . If this value contains FILE_ATTRIBUTE_DIRECTORY, 28 | /// from is assumed to be a directory; otherwise, from is assumed to be a file. 29 | /// 30 | /// 31 | /// A pointer to a null-terminated string of maximum length MAX_PATH that contains 32 | /// the path that defines the endpoint of the relative path. 33 | /// 34 | /// 35 | /// The file attributes of . If this value contains FILE_ATTRIBUTE_DIRECTORY, 36 | /// to is assumed to be directory; otherwise, to is assumed to be a file. 37 | /// 38 | /// 39 | /// true if method succeeded and false if it failed. 40 | /// 41 | [return: MarshalAs(UnmanagedType.Bool)] 42 | [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] 43 | internal static extern bool PathRelativePathTo([Out] StringBuilder path, [In] string from, [In] uint fromAttributes, [In] string to, [In] uint toAttributes); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/T4Toolbox/OutputFile.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox 6 | { 7 | using System; 8 | using System.Text; 9 | 10 | /// 11 | /// This class contains information about generated output file. 12 | /// 13 | [Serializable] 14 | public class OutputFile : OutputItem 15 | { 16 | /// 17 | /// Stores content of the output file. 18 | /// 19 | private readonly StringBuilder content; 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | public OutputFile() 25 | { 26 | this.content = new StringBuilder(); 27 | } 28 | 29 | internal OutputFile(StringBuilder content) 30 | { 31 | this.content = content; 32 | } 33 | 34 | /// 35 | /// Gets content of the output file. 36 | /// 37 | /// 38 | /// A storing content of the . 39 | /// 40 | public StringBuilder Content 41 | { 42 | get { return this.content; } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/T4Toolbox/T4Toolbox.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | {682E771A-76F7-4972-BBDC-1250B67F399B} 5 | Library 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Properties\CommonAssemblyInfo.cs 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 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}. 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/T4Toolbox/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/TextTemplate.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/src/TextTemplate.ico -------------------------------------------------------------------------------- /test/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/AttributeNameTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class AttributeNameTest 11 | { 12 | [Fact] 13 | public static void AttributeNameIsSubclassOfCaptureNode() 14 | { 15 | Assert.True(typeof(AttributeName).IsSubclassOf(typeof(CaptureNode))); 16 | } 17 | 18 | [Fact] 19 | public static void AttributeNameIsSealed() 20 | { 21 | Assert.True(typeof(AttributeName).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsAttributeNameSyntaxKind() 26 | { 27 | var target = new AttributeName(0, string.Empty); 28 | Assert.Equal(SyntaxKind.AttributeName, target.Kind); 29 | } 30 | 31 | [Fact] 32 | public static void AcceptCallsVisitAttributeNameMethodOfSyntaxNodeVisitor() 33 | { 34 | var visitor = Substitute.For(); 35 | var node = new AttributeName(0, string.Empty); 36 | node.Accept(visitor); 37 | visitor.Received().VisitAttributeName(node); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/AttributeValueTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class AttributeValueTest 11 | { 12 | [Fact] 13 | public static void AttributeValueIsSubclassOfCaptureNode() 14 | { 15 | Assert.True(typeof(AttributeValue).IsSubclassOf(typeof(CaptureNode))); 16 | } 17 | 18 | [Fact] 19 | public static void AttributeValueIsSealed() 20 | { 21 | Assert.True(typeof(AttributeValue).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsAttributeValueSyntaxKind() 26 | { 27 | var target = new AttributeValue(0, string.Empty); 28 | Assert.Equal(SyntaxKind.AttributeValue, target.Kind); 29 | } 30 | 31 | [Fact] 32 | public static void AcceptCallsVisitAttributeValueMethodOfSyntaxNodeVisitor() 33 | { 34 | var visitor = Substitute.For(); 35 | var node = new AttributeValue(0, string.Empty); 36 | node.Accept(visitor); 37 | visitor.Received().VisitAttributeValue(node); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/BlockEndTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class BlockEndTest 13 | { 14 | [Fact] 15 | public static void BlockEndIsSubclassOfSyntaxToken() 16 | { 17 | Assert.True(typeof(BlockEnd).IsSubclassOf(typeof(SyntaxToken))); 18 | } 19 | 20 | [Fact] 21 | public static void BlockEndIsSealed() 22 | { 23 | Assert.True(typeof(BlockEnd).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void GetDescriptionReturnsDescriptionOfDirectiveBlockStart() 28 | { 29 | var target = new BlockEnd(0); 30 | string description; 31 | Span applicableTo; 32 | Assert.True(target.TryGetDescription(0, out description, out applicableTo)); 33 | Assert.Contains("control block", description, StringComparison.OrdinalIgnoreCase); 34 | Assert.Contains("directive", description, StringComparison.OrdinalIgnoreCase); 35 | Assert.Equal(target.Span, applicableTo); 36 | } 37 | 38 | [Fact] 39 | public static void KindReturnsBlockEndSyntaxKind() 40 | { 41 | Assert.Equal(SyntaxKind.BlockEnd, new BlockEnd(0).Kind); 42 | } 43 | 44 | [Fact] 45 | public static void SpanLengthReturnsLengthOfToken() 46 | { 47 | Assert.Equal("#>".Length, new BlockEnd(0).Span.Length); 48 | } 49 | 50 | [Fact] 51 | public static void AcceptCallsVisitBlockEndMethodOfSyntaxNodeVisitor() 52 | { 53 | var visitor = Substitute.For(); 54 | var node = new BlockEnd(0); 55 | node.Accept(visitor); 56 | visitor.Received().VisitBlockEnd(node); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/CaptureNodeTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Xunit; 9 | 10 | public static class CaptureNodeTest 11 | { 12 | [Fact] 13 | public static void CaptureNodeIsSubclassOfTerminalNode() 14 | { 15 | Assert.True(typeof(CaptureNode).IsSubclassOf(typeof(TerminalNode))); 16 | } 17 | 18 | [Fact] 19 | public static void ConstructorSetsPositionProperty() 20 | { 21 | var target = new TestableCaptureNode(0, string.Empty, new Position(4, 2)); 22 | Assert.Equal(new Position(4, 2), target.Position); 23 | } 24 | 25 | [Fact] 26 | public static void SpanStartsAtPositionSpecifiedInConstructor() 27 | { 28 | var target = new TestableCaptureNode(42, "template"); 29 | Assert.Equal(42, target.Span.Start); 30 | } 31 | 32 | [Fact] 33 | public static void SpanLengthEqualsToLengthOfTextSpecifiedInConstructor() 34 | { 35 | var target = new TestableCaptureNode(0, "template"); 36 | Assert.Equal("template".Length, target.Span.Length); 37 | } 38 | 39 | [Fact] 40 | public static void TextReturnsValueSpecifiedInConstructor() 41 | { 42 | var target = new TestableCaptureNode(0, "template"); 43 | Assert.Equal("template", target.Text); 44 | } 45 | 46 | private class TestableCaptureNode : CaptureNode 47 | { 48 | public TestableCaptureNode(int start, string text, Position position = default(Position)) 49 | : base(start, text, position) 50 | { 51 | } 52 | 53 | public override SyntaxKind Kind 54 | { 55 | get { throw new NotImplementedException(); } 56 | } 57 | 58 | protected internal override void Accept(SyntaxNodeVisitor visitor) 59 | { 60 | throw new NotImplementedException(); 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/ClassBlockStartTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class ClassBlockStartTest 13 | { 14 | [Fact] 15 | public static void ClassBlockStartIsSubclassOfCodeBlockStart() 16 | { 17 | Assert.True(typeof(ClassBlockStart).IsSubclassOf(typeof(CodeBlockStart))); 18 | } 19 | 20 | [Fact] 21 | public static void ClassBlockStartIsSealed() 22 | { 23 | Assert.True(typeof(ClassBlockStart).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void AcceptCallsVisitClassBlockStartMethodOfSyntaxNodeVisitor() 28 | { 29 | var visitor = Substitute.For(); 30 | var node = new ClassBlockStart(default(int)); 31 | node.Accept(visitor); 32 | visitor.Received().VisitClassBlockStart(node); 33 | } 34 | 35 | [Fact] 36 | public static void GetDescriptionReturnsDescriptionOfClassCodeBlocks() 37 | { 38 | var target = new ClassBlockStart(0); 39 | string description; 40 | Span applicableTo; 41 | Assert.True(target.TryGetDescription(0, out description, out applicableTo)); 42 | Assert.Contains("class feature", description, StringComparison.OrdinalIgnoreCase); 43 | Assert.Equal(target.Span, applicableTo); 44 | } 45 | 46 | [Fact] 47 | public static void KindReturnsClassBlockStartSyntaxKind() 48 | { 49 | Assert.Equal(SyntaxKind.ClassBlockStart, new ClassBlockStart(0).Kind); 50 | } 51 | 52 | [Fact] 53 | public static void SpanLengthReturnsLengthOfToken() 54 | { 55 | Assert.Equal("<#+".Length, new ClassBlockStart(0).Span.Length); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/CodeTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | using NSubstitute; 9 | using Xunit; 10 | 11 | public static class CodeTest 12 | { 13 | [Fact] 14 | public static void CodeIsSubclassOfTerminalNode() 15 | { 16 | Assert.True(typeof(Code).IsSubclassOf(typeof(TerminalNode))); 17 | } 18 | 19 | [Fact] 20 | public static void CodeIsSealed() 21 | { 22 | Assert.True(typeof(Code).IsSealed); 23 | } 24 | 25 | [Fact] 26 | public static void KindReturnsCodeSyntaxKind() 27 | { 28 | Assert.Equal(SyntaxKind.Code, new Code(default(Span)).Kind); 29 | } 30 | 31 | [Fact] 32 | public static void SpanReturnsValueSpecifiedInConstructor() 33 | { 34 | Assert.Equal(new Span(4, 2), new Code(new Span(4, 2)).Span); 35 | } 36 | 37 | [Fact] 38 | public static void AcceptCallsVisitCodeMethodOfSyntaxNodeVisitor() 39 | { 40 | var visitor = Substitute.For(); 41 | var node = new Code(default(Span)); 42 | node.Accept(visitor); 43 | visitor.Received().VisitCode(node); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/DirectiveBlockStartTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class DirectiveBlockStartTest 13 | { 14 | [Fact] 15 | public static void DirectiveBlockStartIsSubclassOfSyntaxToken() 16 | { 17 | Assert.True(typeof(DirectiveBlockStart).IsSubclassOf(typeof(SyntaxToken))); 18 | } 19 | 20 | [Fact] 21 | public static void DirectiveBlockStartIsSealed() 22 | { 23 | Assert.True(typeof(DirectiveBlockStart).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void AcceptCallsVisitDirectiveBlockStartMethodOfSyntaxNodeVisitor() 28 | { 29 | var visitor = Substitute.For(); 30 | var node = new DirectiveBlockStart(default(int)); 31 | node.Accept(visitor); 32 | visitor.Received().VisitDirectiveBlockStart(node); 33 | } 34 | 35 | [Fact] 36 | public static void GetDescriptionReturnsDescriptionOfDirectiveBlockStart() 37 | { 38 | var target = new DirectiveBlockStart(0); 39 | string description; 40 | Span applicableTo; 41 | Assert.True(target.TryGetDescription(0, out description, out applicableTo)); 42 | Assert.Contains("directive", description, StringComparison.OrdinalIgnoreCase); 43 | Assert.Equal(target.Span, applicableTo); 44 | } 45 | 46 | [Fact] 47 | public static void KindReturnsDirectiveBlockStartSyntaxKind() 48 | { 49 | Assert.Equal(SyntaxKind.DirectiveBlockStart, new DirectiveBlockStart(0).Kind); 50 | } 51 | 52 | [Fact] 53 | public static void SpanLengthReturnsLengthOfToken() 54 | { 55 | Assert.Equal("<#@".Length, new DirectiveBlockStart(0).Span.Length); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/DirectiveNameTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class DirectiveNameTest 11 | { 12 | [Fact] 13 | public static void DirectiveNameIsSubclassOfTerminalNode() 14 | { 15 | Assert.True(typeof(DirectiveName).IsSubclassOf(typeof(TerminalNode))); 16 | } 17 | 18 | [Fact] 19 | public static void DirectiveNameIsSealed() 20 | { 21 | Assert.True(typeof(DirectiveName).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsDirectiveNameSyntaxKind() 26 | { 27 | var target = new DirectiveName(0, string.Empty); 28 | Assert.Equal(SyntaxKind.DirectiveName, target.Kind); 29 | } 30 | 31 | [Fact] 32 | public static void AcceptCallsVisitDirectiveNameMethodOfSyntaxNodeVisitor() 33 | { 34 | var visitor = Substitute.For(); 35 | var node = new DirectiveName(0, string.Empty); 36 | node.Accept(visitor); 37 | visitor.Received().VisitDirectiveName(node); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/DoubleQuoteTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class DoubleQuoteTest 11 | { 12 | [Fact] 13 | public static void DoubleQuoteIsSubclassOfSyntaxToken() 14 | { 15 | Assert.True(typeof(DoubleQuote).IsSubclassOf(typeof(SyntaxToken))); 16 | } 17 | 18 | [Fact] 19 | public static void DoubleQuoteIsSealed() 20 | { 21 | Assert.True(typeof(DoubleQuote).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsDoubleQuoteSyntaxKind() 26 | { 27 | Assert.Equal(SyntaxKind.DoubleQuote, new DoubleQuote(0).Kind); 28 | } 29 | 30 | [Fact] 31 | public static void SpanLengthReturnsLengthOfToken() 32 | { 33 | Assert.Equal("\"".Length, new DoubleQuote(0).Span.Length); 34 | } 35 | 36 | [Fact] 37 | public static void AcceptCallsVisitDoubleQuoteMethodOfSyntaxNodeVisitor() 38 | { 39 | var visitor = Substitute.For(); 40 | var syntaxNode = new DoubleQuote(default(int)); 41 | syntaxNode.Accept(visitor); 42 | visitor.Received().VisitDoubleQuote(syntaxNode); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/EndOfFileTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class EndOfFileTest 11 | { 12 | [Fact] 13 | public static void EndOfFileIsSubclassOfSyntaxToken() 14 | { 15 | Assert.True(typeof(EndOfFile).IsSubclassOf(typeof(SyntaxToken))); 16 | } 17 | 18 | [Fact] 19 | public static void EndOfFileIsSealed() 20 | { 21 | Assert.True(typeof(EndOfFile).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsEndOfFileSyntaxKind() 26 | { 27 | Assert.Equal(SyntaxKind.EOF, new EndOfFile(0).Kind); 28 | } 29 | 30 | [Fact] 31 | public static void SpanLengthReturnsLengthOfToken() 32 | { 33 | Assert.Equal(0, new EndOfFile(0).Span.Length); 34 | } 35 | 36 | [Fact] 37 | public static void AcceptCallsVisitEndOfFileMethodOfSyntaxNodeVisitor() 38 | { 39 | var visitor = Substitute.For(); 40 | var node = new EndOfFile(default(int)); 41 | node.Accept(visitor); 42 | visitor.Received().VisitEndOfFile(node); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/EqualsTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using NSubstitute; 8 | using Xunit; 9 | 10 | public static class EqualsTest 11 | { 12 | [Fact] 13 | public static void EqualsIsSubclassOfSyntaxToken() 14 | { 15 | Assert.True(typeof(Equals).IsSubclassOf(typeof(SyntaxToken))); 16 | } 17 | 18 | [Fact] 19 | public static void EqualsIsSealed() 20 | { 21 | Assert.True(typeof(Equals).IsSealed); 22 | } 23 | 24 | [Fact] 25 | public static void KindReturnsEqualsSyntaxKind() 26 | { 27 | Assert.Equal(SyntaxKind.Equals, new Equals(0).Kind); 28 | } 29 | 30 | [Fact] 31 | public static void SpanLengthReturnsLengthOfToken() 32 | { 33 | Assert.Equal("=".Length, new Equals(0).Span.Length); 34 | } 35 | 36 | [Fact] 37 | public static void AcceptCallsVisitEqualsMethodOfSyntaxNodeVisitor() 38 | { 39 | var visitor = Substitute.For(); 40 | var node = new Equals(default(int)); 41 | node.Accept(visitor); 42 | visitor.Received().VisitEquals(node); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/ExpressionBlockStartTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class ExpressionBlockStartTest 13 | { 14 | [Fact] 15 | public static void ExpressionBlockStartIsSubclassOfCodeBlockStart() 16 | { 17 | Assert.True(typeof(ExpressionBlockStart).IsSubclassOf(typeof(CodeBlockStart))); 18 | } 19 | 20 | [Fact] 21 | public static void ExpressionBlockStartIsSealed() 22 | { 23 | Assert.True(typeof(ExpressionBlockStart).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void AcceptCallsVisitExpressionBlockStartMethodOfSyntaxNodeVisitor() 28 | { 29 | var visitor = Substitute.For(); 30 | var node = new ExpressionBlockStart(default(int)); 31 | node.Accept(visitor); 32 | visitor.Received().VisitExpressionBlockStart(node); 33 | } 34 | 35 | [Fact] 36 | public static void GetDescriptionReturnsDescriptionOfExpressionCodeBlocks() 37 | { 38 | var target = new ExpressionBlockStart(0); 39 | string description; 40 | Span applicableTo; 41 | Assert.True(target.TryGetDescription(0, out description, out applicableTo)); 42 | Assert.Contains("expression", description, StringComparison.OrdinalIgnoreCase); 43 | Assert.Equal(target.Span, applicableTo); 44 | } 45 | 46 | [Fact] 47 | public static void KindReturnsExpressionBlockStartSyntaxKind() 48 | { 49 | Assert.Equal(SyntaxKind.ExpressionBlockStart, new ExpressionBlockStart(0).Kind); 50 | } 51 | 52 | [Fact] 53 | public static void SpanLengthReturnsLengthOfToken() 54 | { 55 | Assert.Equal("<#=".Length, new ExpressionBlockStart(0).Span.Length); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/PositionTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Xunit; 8 | 9 | public static class PositionTest 10 | { 11 | [Fact] 12 | public static void PositionIsValueType() // to be lightweight 13 | { 14 | Assert.True(typeof(Position).IsValueType); 15 | } 16 | 17 | [Fact] 18 | public static void PositionIsInternal() // for internal consumption only 19 | { 20 | Assert.True(typeof(Position).IsNotPublic); 21 | } 22 | 23 | [Fact] 24 | public static void LineReturnsValueSpecifiedInConstructor() 25 | { 26 | var target = new Position(42, 0); 27 | Assert.Equal(42, target.Line); 28 | } 29 | 30 | [Fact] 31 | public static void ColumnReturnsValueSpecifiedInConstructor() 32 | { 33 | var target = new Position(0, 42); 34 | Assert.Equal(42, target.Column); 35 | } 36 | 37 | [Fact] 38 | public static void EqualsReturnsTrueWhenLineAndColumnAreSame() 39 | { 40 | var a = new Position(4, 2); 41 | var b = new Position(4, 2); 42 | Assert.Equal(a, b); 43 | } 44 | 45 | [Fact] 46 | public static void GetHashCodeReturnsValueCalculatedFromLineAndColumn() 47 | { 48 | var a = new Position(4, 2); 49 | var b = new Position(4, 2); 50 | Assert.Equal(a.GetHashCode(), b.GetHashCode()); 51 | } 52 | 53 | [Fact] 54 | public static void ToStringReturnsLineAndColumnInParenthesis() // consistently with MSBuild messages 55 | { 56 | Assert.Equal("(4,2)", new Position(4, 2).ToString()); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/StatementBlockStartTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class StatementBlockStartTest 13 | { 14 | [Fact] 15 | public static void StatementBlockStartIsSubclassOfCodeBlockStart() 16 | { 17 | Assert.True(typeof(StatementBlockStart).IsSubclassOf(typeof(CodeBlockStart))); 18 | } 19 | 20 | [Fact] 21 | public static void StatementBlockStartIsSealed() 22 | { 23 | Assert.True(typeof(StatementBlockStart).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void AcceptCallsAcceptStatementBlockStartMethodOfSyntaxNodeVisitor() 28 | { 29 | var visitor = Substitute.For(); 30 | var node = new StatementBlockStart(default(int)); 31 | node.Accept(visitor); 32 | visitor.Received().VisitStatementBlockStart(node); 33 | } 34 | 35 | [Fact] 36 | public static void GetDescriptionReturnsDescriptionOfStatementCodeBlocks() 37 | { 38 | var target = new StatementBlockStart(0); 39 | string description; 40 | Span applicableTo; 41 | Assert.True(target.TryGetDescription(0, out description, out applicableTo)); 42 | Assert.Contains("statement", description, StringComparison.OrdinalIgnoreCase); 43 | Assert.Equal(target.Span, applicableTo); 44 | } 45 | 46 | [Fact] 47 | public static void KindReturnsStatementBlockStartSyntaxKind() 48 | { 49 | Assert.Equal(SyntaxKind.StatementBlockStart, new StatementBlockStart(0).Kind); 50 | } 51 | 52 | [Fact] 53 | public static void SpanLengthReturnsLengthOfTheToken() 54 | { 55 | Assert.Equal("<#".Length, new StatementBlockStart(0).Span.Length); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/SyntaxTokenTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.Text; 9 | using Xunit; 10 | 11 | public static class SyntaxTokenTest 12 | { 13 | [Fact] 14 | public static void ConstructorSetsPositionProperty() 15 | { 16 | var target = new TestableSyntaxToken(0, new Position(4, 2)); 17 | Assert.Equal(new Position(4, 2), target.Position); 18 | } 19 | 20 | [Fact] 21 | public static void SyntaxTokenIsSubclassOfTerminalNode() 22 | { 23 | Assert.True(typeof(SyntaxToken).IsSubclassOf(typeof(TerminalNode))); 24 | } 25 | 26 | [Fact] 27 | public static void StartReturnsValueSpecifiedInConstructor() 28 | { 29 | var target = new TestableSyntaxToken(42); 30 | Assert.Equal(42, target.Start); 31 | } 32 | 33 | private class TestableSyntaxToken : SyntaxToken 34 | { 35 | public TestableSyntaxToken(int start, Position position = default(Position)) : base(start, position) 36 | { 37 | } 38 | 39 | public new int Start 40 | { 41 | get { return base.Start; } 42 | } 43 | 44 | public override SyntaxKind Kind 45 | { 46 | get { throw new NotImplementedException(); } 47 | } 48 | 49 | public override Span Span 50 | { 51 | get { throw new NotImplementedException(); } 52 | } 53 | 54 | protected internal override void Accept(SyntaxNodeVisitor visitor) 55 | { 56 | throw new NotImplementedException(); 57 | } 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/TemplateErrorTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | using Xunit; 9 | 10 | public static class TemplateErrorTest 11 | { 12 | [Fact] 13 | public static void MessageReturnsValueSpecifiedInConstructor() 14 | { 15 | var target = new TemplateError("42", default(Span), default(Position)); 16 | Assert.Equal("42", target.Message); 17 | } 18 | 19 | [Fact] 20 | public static void PositionReturnsValueSpecifiedInConstructor() 21 | { 22 | var target = new TemplateError(string.Empty, default(Span), new Position(4, 2)); 23 | Assert.Equal(new Position(4, 2), target.Position); 24 | } 25 | 26 | [Fact] 27 | public static void SpanReturnsValueSpecifiedInConstructor() 28 | { 29 | var target = new TemplateError(string.Empty, new Span(4, 2), default(Position)); 30 | Assert.Equal(new Span(4, 2), target.Span); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/TemplateTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System.Linq; 8 | using Microsoft.VisualStudio.Text; 9 | using NSubstitute; 10 | using Xunit; 11 | 12 | public static class TemplateTest 13 | { 14 | [Fact] 15 | public static void TemplateIsSubclassOfNonterminalNode() 16 | { 17 | Assert.True(typeof(Template).IsSubclassOf(typeof(NonterminalNode))); 18 | } 19 | 20 | [Fact] 21 | public static void TemplateIsSealed() 22 | { 23 | Assert.True(typeof(Template).IsSealed); 24 | } 25 | 26 | [Fact] 27 | public static void AcceptCallsVisitTemplateMethodOfSyntaxNodeVisitor() 28 | { 29 | var visitor = Substitute.For(); 30 | var template = new Template(); 31 | template.Accept(visitor); 32 | visitor.Received().VisitTemplate(template); 33 | } 34 | 35 | [Fact] 36 | public static void KindReturnsTemplateSyntaxKind() 37 | { 38 | Assert.Equal(SyntaxKind.Template, new Template().Kind); 39 | } 40 | 41 | [Fact] 42 | public static void PositionReturnsFixedValue() 43 | { 44 | var target = new Template(); 45 | Assert.Equal(new Position(0, 0), target.Position); 46 | } 47 | 48 | [Fact] 49 | public static void SpanStartReturnsMinStartOfChildNodes() 50 | { 51 | var end = new BlockEnd(40); 52 | var start = new StatementBlockStart(4); 53 | var target = new Template(end, start); // intentionally reversed 54 | Assert.Equal(start.Span.Start, target.Span.Start); 55 | } 56 | 57 | [Fact] 58 | public static void SpanEndReturnsMaxEndOfChildNodes() 59 | { 60 | var end = new BlockEnd(40); 61 | var start = new StatementBlockStart(4); 62 | var target = new Template(end, start); // intentionally reversed 63 | Assert.Equal(end.Span.End, target.Span.End); 64 | } 65 | 66 | [Fact] 67 | public static void SpanIsEmptyWhenNodeHasNoChildren() 68 | { 69 | Assert.Equal(new Span(), new Template().Span); 70 | } 71 | 72 | [Fact] 73 | public static void ChildNodesReturnsNodesSpecifiedInConstructor() 74 | { 75 | var start = new StatementBlockStart(0); 76 | var end = new BlockEnd(2); 77 | var node = new Template(start, end); 78 | Assert.Same(start, node.ChildNodes().First()); 79 | Assert.Same(end, node.ChildNodes().Last()); 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/TerminalNodeTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Linq; 10 | using Microsoft.VisualStudio.Text; 11 | using Xunit; 12 | 13 | public static class TerminalNodeTest 14 | { 15 | [Fact] 16 | public static void ConstructorSetsPositionProperty() 17 | { 18 | var target = new TestableTerminalNode(new Position(4, 2)); 19 | Assert.Equal(new Position(4, 2), target.Position); 20 | } 21 | 22 | [Fact] 23 | public static void ChildNodesReturnsEmptyEnumerable() 24 | { 25 | var node = new TestableTerminalNode(); 26 | IEnumerable childNodes = node.ChildNodes(); 27 | Assert.NotNull(childNodes); 28 | Assert.False(childNodes.Any()); 29 | } 30 | 31 | [Fact] 32 | public static void ValidateReturnsEmptyEnumerable() 33 | { 34 | var node = new TestableTerminalNode(); 35 | IEnumerable errors = node.Validate(); 36 | Assert.NotNull(errors); 37 | Assert.False(errors.Any()); 38 | } 39 | 40 | private class TestableTerminalNode : TerminalNode 41 | { 42 | public TestableTerminalNode(Position position = default(Position)) : base(position) 43 | { 44 | } 45 | 46 | public override SyntaxKind Kind 47 | { 48 | get { throw new NotImplementedException(); } 49 | } 50 | 51 | public override Span Span 52 | { 53 | get { throw new NotImplementedException(); } 54 | } 55 | 56 | protected internal override void Accept(SyntaxNodeVisitor visitor) 57 | { 58 | throw new NotImplementedException(); 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/ValueDescriptorTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.TemplateAnalysis 6 | { 7 | using Xunit; 8 | 9 | public static class ValueDescriptorTest 10 | { 11 | [Fact] 12 | public static void ClassIsInternalAndNotMeantForPublicConsumption() 13 | { 14 | Assert.False(typeof(ValueDescriptor).IsPublic); 15 | } 16 | 17 | [Fact] 18 | public static void ClassIsSealedAndNotMeantToHaveDerivedClasses() 19 | { 20 | Assert.True(typeof(ValueDescriptor).IsSealed); 21 | } 22 | 23 | [Fact] 24 | public static void DisplayNameReturnsValueSpecifiedInConstructor() 25 | { 26 | var value = new ValueDescriptor("DisplayName"); 27 | Assert.Equal("DisplayName", value.DisplayName); 28 | } 29 | 30 | [Fact] 31 | public static void DescriptionIsEmptyStringByDefault() 32 | { 33 | var value = new ValueDescriptor("DisplayName"); 34 | Assert.Empty(value.Description); 35 | } 36 | 37 | [Fact] 38 | public static void DescriptionReturnsValueSpecifiedInConstructor() 39 | { 40 | var value = new ValueDescriptor("DisplayName", "Description"); 41 | Assert.Equal("Description", value.Description); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test/T4Toolbox.TemplateAnalysis.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/T4Toolbox.Tests.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | $(MSBuildThisFileDirectory)\T4Toolbox.Tests.ruleset 6 | 7 | 8 | 9 | 10 | 11 | true 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/CSharpTemplateTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.Tests 6 | { 7 | using System; 8 | using System.IO; 9 | 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | 12 | [TestClass] 13 | public class CSharpTemplateTest : IDisposable 14 | { 15 | private readonly CSharpTemplate template = new TestCSharpTemplate(); 16 | 17 | public void Dispose() 18 | { 19 | this.template.Dispose(); 20 | } 21 | 22 | [TestMethod] 23 | public void FieldNameReturnsCamelCasedIdentifier() 24 | { 25 | Assert.AreEqual("testName", this.template.FieldName("Test Name")); 26 | } 27 | 28 | [TestMethod] 29 | public void IdentifierRemovesWhiteSpace() 30 | { 31 | Assert.AreEqual("TestName", this.template.Identifier(" Test Name ")); 32 | } 33 | 34 | [TestMethod] 35 | public void IdentifierConvertsReservedKeywordToLiteralIdentifier() 36 | { 37 | Assert.AreEqual("@class", this.template.Identifier("class")); 38 | } 39 | 40 | [TestMethod] 41 | public void PropertyNameReturnsPascalCasedIdentifier() 42 | { 43 | Assert.AreEqual("TestName", this.template.PropertyName("Test Name")); 44 | } 45 | 46 | [TestMethod] 47 | public void TransformTextGeneratesFileHeader() 48 | { 49 | using (var transformation = new FakeTransformation()) 50 | using (var context = new TransformationContext(transformation, transformation.GenerationEnvironment)) 51 | { 52 | this.template.Context = context; 53 | transformation.Host.TemplateFile = Path.GetRandomFileName(); 54 | string output = this.template.TransformText(); 55 | StringAssert.Contains(output, ""); 56 | StringAssert.Contains(output, transformation.Host.TemplateFile); 57 | } 58 | } 59 | 60 | // CSharpTemplate is abstract class. Need a concrete descendant to test it. 61 | private class TestCSharpTemplate : CSharpTemplate 62 | { 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/FakeGenerator.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.Tests 6 | { 7 | using System; 8 | 9 | internal class FakeGenerator : Generator 10 | { 11 | public Action RanCore { get; set; } 12 | 13 | public Action Validated { get; set; } 14 | 15 | protected override void RunCore() 16 | { 17 | if (this.RanCore != null) 18 | { 19 | this.RanCore(); 20 | } 21 | } 22 | 23 | protected override void Validate() 24 | { 25 | if (this.Validated != null) 26 | { 27 | this.Validated(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/FakeTemplate.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.Tests 6 | { 7 | using System; 8 | 9 | internal class FakeTemplate : Template 10 | { 11 | public Action Initialized { get; set; } 12 | 13 | public Action TransformedText { get; set; } 14 | 15 | public Action Validated { get; set; } 16 | 17 | public override void Initialize() 18 | { 19 | base.Initialize(); 20 | 21 | if (this.Initialized != null) 22 | { 23 | this.Initialized(); 24 | } 25 | } 26 | 27 | public override string TransformText() 28 | { 29 | if (this.TransformedText != null) 30 | { 31 | this.TransformedText(); 32 | } 33 | 34 | return this.GenerationEnvironment.ToString(); 35 | } 36 | 37 | protected override void Validate() 38 | { 39 | base.Validate(); 40 | 41 | if (this.Validated != null) 42 | { 43 | this.Validated(); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/FakeTransformation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.Tests 6 | { 7 | using System.Collections.Generic; 8 | using System.Diagnostics.CodeAnalysis; 9 | using System.Text; 10 | using Microsoft.VisualStudio.TextTemplating; 11 | 12 | internal class FakeTransformation : TextTransformation 13 | { 14 | [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "Session is initialized by default")] 15 | public FakeTransformation() 16 | { 17 | this.Host = new FakeTextTemplatingService(); 18 | this.Session = new Dictionary(); 19 | } 20 | 21 | public FakeTextTemplatingService Host { get; set; } 22 | 23 | public new StringBuilder GenerationEnvironment 24 | { 25 | get { return base.GenerationEnvironment; } 26 | } 27 | 28 | public override string TransformText() 29 | { 30 | return this.GenerationEnvironment.ToString(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.Tests/GlobalSuppressions.cs -------------------------------------------------------------------------------- /test/T4Toolbox.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/FakeClassificationType.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Diagnostics; 10 | using Microsoft.VisualStudio.Text.Classification; 11 | 12 | internal class FakeClassificationType : IClassificationType 13 | { 14 | public FakeClassificationType(string classification, IEnumerable baseTypes) 15 | { 16 | Debug.Assert(classification != null, "classification"); 17 | Debug.Assert(baseTypes != null, "baseTypes"); 18 | 19 | this.Classification = classification; 20 | this.BaseTypes = baseTypes; 21 | } 22 | 23 | public bool IsOfType(string type) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | 28 | public string Classification { get; private set; } 29 | 30 | public IEnumerable BaseTypes { get; private set; } 31 | } 32 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/FakeClassificationTypeRegistryService.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | using Microsoft.VisualStudio.Text.Classification; 11 | 12 | internal class FakeClassificationTypeRegistryService : IClassificationTypeRegistryService 13 | { 14 | private readonly Dictionary registry = new Dictionary(StringComparer.OrdinalIgnoreCase); 15 | 16 | public IClassificationType GetClassificationType(string type) 17 | { 18 | IClassificationType classificationType; 19 | if (this.registry.TryGetValue(type, out classificationType)) 20 | { 21 | return classificationType; 22 | } 23 | 24 | return null; 25 | } 26 | 27 | public IClassificationType CreateClassificationType(string type, IEnumerable baseTypes) 28 | { 29 | if (this.registry.ContainsKey(type)) 30 | { 31 | throw new InvalidOperationException(); 32 | } 33 | 34 | IClassificationType classificationType = new FakeClassificationType(type, baseTypes); 35 | this.registry.Add(type, classificationType); 36 | return classificationType; 37 | } 38 | 39 | public IClassificationType CreateTransientClassificationType(IEnumerable baseTypes) 40 | { 41 | throw new NotImplementedException(); 42 | } 43 | 44 | public IClassificationType CreateTransientClassificationType(params IClassificationType[] baseTypes) 45 | { 46 | throw new NotImplementedException(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/FakeTrackingSpan.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using Microsoft.VisualStudio.Text; 8 | 9 | internal class FakeTrackingSpan : ITrackingSpan 10 | { 11 | private Span span; 12 | private SpanTrackingMode trackingMode; 13 | 14 | public FakeTrackingSpan(Span span, SpanTrackingMode trackingMode) 15 | { 16 | this.span = span; 17 | this.trackingMode = trackingMode; 18 | } 19 | 20 | #region ITrackingSpan 21 | 22 | SnapshotSpan ITrackingSpan.GetSpan(ITextSnapshot snapshot) 23 | { 24 | return new SnapshotSpan(snapshot, this.span); 25 | } 26 | 27 | Span ITrackingSpan.GetSpan(ITextVersion version) 28 | { 29 | throw new System.NotImplementedException(); 30 | } 31 | 32 | string ITrackingSpan.GetText(ITextSnapshot snapshot) 33 | { 34 | throw new System.NotImplementedException(); 35 | } 36 | 37 | SnapshotPoint ITrackingSpan.GetStartPoint(ITextSnapshot snapshot) 38 | { 39 | throw new System.NotImplementedException(); 40 | } 41 | 42 | SnapshotPoint ITrackingSpan.GetEndPoint(ITextSnapshot snapshot) 43 | { 44 | throw new System.NotImplementedException(); 45 | } 46 | 47 | ITextBuffer ITrackingSpan.TextBuffer 48 | { 49 | get { throw new System.NotImplementedException(); } 50 | } 51 | 52 | SpanTrackingMode ITrackingSpan.TrackingMode 53 | { 54 | get { return this.trackingMode; } 55 | } 56 | 57 | TrackingFidelityMode ITrackingSpan.TrackingFidelity 58 | { 59 | get { throw new System.NotImplementedException(); } 60 | } 61 | 62 | #endregion 63 | } 64 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/SubstituteExporter.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System.ComponentModel.Composition; 8 | using NSubstitute; 9 | 10 | internal class SubstituteExporter where T : class 11 | { 12 | [Export] 13 | public T Instance = Substitute.For(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/TemplateCompletionHandlerTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Diagnostics.CodeAnalysis; 9 | using Microsoft.VisualStudio.OLE.Interop; 10 | using NSubstitute; 11 | using Xunit; 12 | 13 | public static class TemplateCompletionHandlerTest 14 | { 15 | [Fact] 16 | public static void TemplateCompletionHandlerIsInternalBecauseItIsOnlyMeantToBeImportedByVisualStudio() 17 | { 18 | Assert.False(typeof(TemplateCompletionHandler).IsPublic); 19 | } 20 | 21 | [Fact] 22 | public static void TemplateCompletionHandlerIsSealedBecauseItIsNotMeantToHaveChildClasses() 23 | { 24 | Assert.True(typeof(TemplateCompletionHandler).IsSealed); 25 | } 26 | 27 | [Fact] 28 | public static void TemplateCompletionHandlerImplementsIOleCommandTargetToInterceptKeystrokes() 29 | { 30 | Assert.Equal(typeof(IOleCommandTarget), typeof(TemplateCompletionHandler).GetInterfaces()[0]); 31 | } 32 | 33 | [Fact(Skip = "Not Implemented")] 34 | public static void TestExecMethod() 35 | { 36 | // TODO: Test this 37 | } 38 | 39 | [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.VisualStudio.OLE.Interop.IOleCommandTarget.QueryStatus(System.Guid@,System.UInt32,Microsoft.VisualStudio.OLE.Interop.OLECMD[],System.IntPtr)", Justification = "This test does not call QueryStatus, it only asserts it was called.")] 40 | [Fact] 41 | public static void QueryStatusCallsNextCommandTargetToSupportDefaultCommandHandling() 42 | { 43 | var nextHandler = Substitute.For(); 44 | var handler = new TemplateCompletionHandler { NextHandler = nextHandler }; 45 | 46 | Guid commandGroup = Guid.Empty; 47 | handler.QueryStatus(ref commandGroup, 0, null, IntPtr.Zero); 48 | 49 | nextHandler.Received().QueryStatus(ref commandGroup, 0, null, IntPtr.Zero); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/TemplateErrorTaggerTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Editor 6 | { 7 | using System; 8 | using System.Linq; 9 | using Microsoft.VisualStudio.Text; 10 | using Microsoft.VisualStudio.Text.Tagging; 11 | using Xunit; 12 | 13 | public static class TemplateErrorTaggerTest 14 | { 15 | [Fact] 16 | public static void TemplateErrorTaggerIsInternalAndNotIntendedForConsumptionOutsideOfT4Toolbox() 17 | { 18 | Assert.True(typeof(TemplateErrorTagger).IsNotPublic); 19 | } 20 | 21 | [Fact] 22 | public static void TemplateErrorTaggerIsSealedAndNotIntendedHaveChildClasses() 23 | { 24 | Assert.True(typeof(TemplateErrorTagger).IsSealed); 25 | } 26 | 27 | [Fact] 28 | public static void GetTagsReturnsErrorSpanForSyntaxError() 29 | { 30 | var buffer = new FakeTextBuffer("<#"); 31 | var tagger = new TemplateErrorTagger(buffer); 32 | 33 | var snapshotSpans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length)); 34 | ITagSpan errorSpan = tagger.GetTags(snapshotSpans).Single(); 35 | 36 | Assert.Equal(new Span(2, 0), errorSpan.Span); 37 | Assert.Contains("#>", (string)errorSpan.Tag.ToolTipContent, StringComparison.Ordinal); 38 | } 39 | 40 | [Fact] 41 | public static void GetTagsReturnsErrorSpanForSemanticError() 42 | { 43 | var buffer = new FakeTextBuffer("<#@ include file=\" \" #>"); 44 | var tagger = new TemplateErrorTagger(buffer); 45 | 46 | var snapshotSpans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length)); 47 | ITagSpan errorSpan = tagger.GetTags(snapshotSpans).Single(); 48 | 49 | Assert.Equal(new Span(12, 8), errorSpan.Span); 50 | Assert.Contains("File", (string)errorSpan.Tag.ToolTipContent, StringComparison.OrdinalIgnoreCase); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Editor.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.IntegrationTests/GlobalSuppressions.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/T4ToolboxOptionsPageTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.IntegrationTests 6 | { 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | 9 | [TestClass] 10 | public sealed class T4ToolboxOptionsPageTest 11 | { 12 | [TestMethod] 13 | public void AutomationObjectReturnsCloneOfGlobalOptions() 14 | { 15 | using (var page = new T4ToolboxOptionsPage()) 16 | { 17 | Assert.AreNotSame(T4ToolboxOptions.Instance, page.AutomationObject); 18 | } 19 | } 20 | 21 | [TestMethod] 22 | public void SaveSettingsToStorageUpdatesGlobalOptions() 23 | { 24 | var globalOptions = new T4ToolboxOptions(); 25 | using (var page = new TestableT4ToolboxOptionsPage(globalOptions)) 26 | { 27 | var localOptions = (T4ToolboxOptions)page.AutomationObject; 28 | localOptions.SyntaxColorizationEnabled = !globalOptions.SyntaxColorizationEnabled; 29 | page.SaveSettingsToStorage(); 30 | Assert.AreEqual(localOptions.SyntaxColorizationEnabled, globalOptions.SyntaxColorizationEnabled); 31 | } 32 | } 33 | 34 | [TestMethod] 35 | public void LoadSettingsFromStorageUpdatesLocalOptions() 36 | { 37 | var globalOptions = new T4ToolboxOptions(); 38 | using (var page = new TestableT4ToolboxOptionsPage(globalOptions)) 39 | { 40 | var localOptions = (T4ToolboxOptions)page.AutomationObject; 41 | localOptions.SyntaxColorizationEnabled = !globalOptions.SyntaxColorizationEnabled; 42 | page.LoadSettingsFromStorage(); 43 | Assert.AreEqual(globalOptions.SyntaxColorizationEnabled, localOptions.SyntaxColorizationEnabled); 44 | } 45 | } 46 | 47 | private class TestableT4ToolboxOptionsPage : T4ToolboxOptionsPage 48 | { 49 | private readonly T4ToolboxOptions globalOptions; 50 | 51 | public TestableT4ToolboxOptionsPage(T4ToolboxOptions globalOptions) 52 | { 53 | this.globalOptions = globalOptions; 54 | } 55 | 56 | protected override T4ToolboxOptions GetGlobalOptions() 57 | { 58 | return this.globalOptions; 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/TargetProject.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.IntegrationTests 6 | { 7 | using System; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | 10 | /// 11 | /// Provides access to test data in TargetProject.xml file for use in data-driven tests. 12 | /// 13 | internal class TargetProject 14 | { 15 | public const string Provider = "Microsoft.VisualStudio.TestTools.DataSource.XML"; 16 | public const string Connection = @"|DataDirectory|\TargetProject.xml"; 17 | public const string Table = "TargetProject"; 18 | 19 | public TargetProject(TestContext testContext) 20 | { 21 | if (testContext.DataRow == null) 22 | { 23 | throw new InvalidOperationException("Test method does not have a valid DataSourceAttribute."); 24 | } 25 | 26 | this.Language = (string)testContext.DataRow["Language"]; 27 | this.Template = (string)testContext.DataRow["Template"]; 28 | this.CodeFileExtension = (string)testContext.DataRow["CodeFileExtension"]; 29 | this.DefaultTextTemplateLanguage = (string)testContext.DataRow["DefaultTextTemplateLanguage"]; 30 | 31 | // To help distinguish test run results in Test Explorer, dump them to the console output 32 | Console.WriteLine( 33 | "Language = '{0}', Template = '{1}', Code File Extension = '{2}', Default Text Template Language = '{3}'.", 34 | new object[] { this.Language, this.Template, this.CodeFileExtension, this.DefaultTextTemplateLanguage }); 35 | } 36 | 37 | public string Language { get; private set; } 38 | 39 | public string Template { get; private set; } 40 | 41 | public string CodeFileExtension { get; private set; } 42 | 43 | /// 44 | /// Gets the default T4 language, as specified in the <#@ template #> directive of a text template. 45 | /// 46 | public string DefaultTextTemplateLanguage { get; private set; } 47 | } 48 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/TargetProject.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | CSharp 4 | 5 | .cs 6 | C# 7 | 8 | 9 | VisualBasic 10 | 11 | .vb 12 | VB 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/TemplateLocatorTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.IntegrationTests 6 | { 7 | using System.IO; 8 | using System.Threading.Tasks; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | [TestClass] 12 | public class TemplateLocatorTest : IntegrationTest 13 | { 14 | [TestMethod] 15 | public async Task TemplateLocatorFindsTemplateRelativeToInputFolder() 16 | { 17 | await UIThreadDispatcher.InvokeAsync(delegate 18 | { 19 | IntegrationTest.LoadT4ToolboxPackage(); 20 | string inputPath = this.CreateTempFile(SolutionDirectory, string.Empty); 21 | string templatePath = this.CreateTempFile(SolutionDirectory, string.Empty); 22 | var templateLocator = (TemplateLocator)ServiceProvider.GetService(typeof(TemplateLocator)); 23 | string resolvedPath = Path.GetFileName(templatePath); 24 | Assert.IsTrue(templateLocator.LocateTemplate(inputPath, ref resolvedPath)); 25 | Assert.AreEqual(templatePath, resolvedPath); 26 | }); 27 | } 28 | 29 | [TestMethod, Ignore] // VS 2017 loads TemplateLocator from the TestResults/Out folder instead of the extension install root 30 | public async Task TemplateLocatorFindsTemplateRelativeToIncludeFolder() 31 | { 32 | await UIThreadDispatcher.InvokeAsync(delegate 33 | { 34 | IntegrationTest.LoadT4ToolboxPackage(); 35 | string inputPath = this.CreateTempFile(SolutionDirectory, string.Empty); 36 | string includeFolder = Path.Combine(Path.GetDirectoryName(typeof(TemplateLocator).Assembly.Location), "Include"); 37 | string templatePath = this.CreateTempFile(includeFolder, string.Empty); 38 | 39 | var templateLocator = (TemplateLocator)ServiceProvider.GetService(typeof(TemplateLocator)); 40 | string resolvedPath = Path.GetFileName(templatePath); 41 | Assert.IsTrue(templateLocator.LocateTemplate(inputPath, ref resolvedPath)); 42 | Assert.AreEqual(templatePath, resolvedPath); 43 | }); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/TransformationContextTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.IntegrationTests 6 | { 7 | using System.IO; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using EnvDTE; 11 | using Microsoft.VisualStudio.TestTools.UnitTesting; 12 | 13 | using VSLangProj; 14 | 15 | [TestClass] 16 | public class TransformationContextTest : IntegrationTest 17 | { 18 | [TestMethod, DataSource(TargetProject.Provider, TargetProject.Connection, TargetProject.Table, DataAccessMethod.Sequential)] 19 | public async Task TransformationContextInitializesParameterValuesFromMetadata() 20 | { 21 | await UIThreadDispatcher.InvokeAsync(delegate 22 | { 23 | Project project = this.CreateTestProject(); 24 | string templateFile = Path.Combine(Path.GetDirectoryName(project.FullName), Path.ChangeExtension(Path.GetRandomFileName(), "tt")); 25 | ProjectItem template = CreateTestProjectItemFromFile(project.ProjectItems, templateFile); 26 | 27 | const string ParameterName = "StringParameter"; 28 | const string ParameterValue = "42"; 29 | template.SetItemAttribute(ParameterName, ParameterValue); 30 | 31 | string templateContent = 32 | "<#@ template language=\"" + this.TargetProject.DefaultTextTemplateLanguage + "\" #>" + 33 | "<#@ output extension=\"txt\" #>" + 34 | "<#@ include file=\"T4Toolbox.tt\" #>" + 35 | "<#@ parameter type=\"System.String\" name=\"" + ParameterName + "\" #>" + 36 | "<#= " + ParameterName + " #>"; 37 | 38 | File.WriteAllText(template.FileNames[1], templateContent); 39 | ((VSProjectItem)template.Object).RunCustomTool(); 40 | 41 | ProjectItem output = template.ProjectItems.Cast().Single(); 42 | Assert.AreEqual(ParameterValue, File.ReadAllText(output.FileNames[1])); 43 | }); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.IntegrationTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeDte.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeDte.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProject.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProject.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjectItem.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjectItem.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjectItems.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjectItems.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjects.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProjects.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProperties.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProperties.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProperty.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeProperty.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeSolution.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/Fakes/FakeSolution.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeTemplateLocator.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests.Fakes 6 | { 7 | using System.IO; 8 | 9 | internal class FakeTemplateLocator : TemplateLocator 10 | { 11 | public FakeTemplateLocator() : base(null) 12 | { 13 | } 14 | 15 | public override bool LocateTemplate(string fullInputPath, ref string templatePath) 16 | { 17 | templatePath = Path.GetFullPath(templatePath); 18 | return File.Exists(templatePath); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeTypeDescriptorContext.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests.Fakes 6 | { 7 | using System; 8 | using System.ComponentModel; 9 | using System.Diagnostics; 10 | 11 | internal class FakeTypeDescriptorContext : ITypeDescriptorContext 12 | { 13 | private readonly IServiceProvider serviceProvider; 14 | private readonly object instance; 15 | 16 | public FakeTypeDescriptorContext(IServiceProvider serviceProvider, object instance) 17 | { 18 | Debug.Assert(serviceProvider != null, "serviceProvider"); 19 | Debug.Assert(instance != null, "instance"); 20 | 21 | this.serviceProvider = serviceProvider; 22 | this.instance = instance; 23 | } 24 | 25 | IContainer ITypeDescriptorContext.Container 26 | { 27 | get { throw new NotImplementedException(); } 28 | } 29 | 30 | object ITypeDescriptorContext.Instance 31 | { 32 | get { return this.instance; } 33 | } 34 | 35 | PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor 36 | { 37 | get { throw new NotImplementedException(); } 38 | } 39 | 40 | object IServiceProvider.GetService(Type serviceType) 41 | { 42 | return this.serviceProvider.GetService(serviceType); 43 | } 44 | 45 | void ITypeDescriptorContext.OnComponentChanged() 46 | { 47 | throw new NotImplementedException(); 48 | } 49 | 50 | bool ITypeDescriptorContext.OnComponentChanging() 51 | { 52 | throw new NotImplementedException(); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/FakeVsActivityLog.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Fakes 6 | { 7 | using System; 8 | using Microsoft.VisualStudio; 9 | using Microsoft.VisualStudio.Shell.Interop; 10 | 11 | internal class FakeVsActivityLog : SVsActivityLog, IVsActivityLog 12 | { 13 | public int LogEntry(uint activityType, string source, string description) 14 | { 15 | return this.LogEntryGuidHrPath(activityType, source, description, Guid.Empty, 0, string.Empty); 16 | } 17 | 18 | public int LogEntryGuid(uint activityType, string source, string description, Guid guid) 19 | { 20 | return this.LogEntryGuidHrPath(activityType, source, description, guid, 0, string.Empty); 21 | } 22 | 23 | public int LogEntryGuidHr(uint activityType, string source, string description, Guid guid, int result) 24 | { 25 | return this.LogEntryGuidHrPath(activityType, source, description, guid, result, string.Empty); 26 | } 27 | 28 | public int LogEntryGuidHrPath(uint activityType, string source, string description, Guid guid, int result, string path) 29 | { 30 | // Intentionally left blank. 31 | // Implement this method if/when verifying activity log entries becomes necessary. 32 | return VSConstants.S_OK; 33 | } 34 | 35 | public int LogEntryGuidPath(uint activityType, string source, string description, Guid guid, string path) 36 | { 37 | return this.LogEntryGuidHrPath(activityType, source, description, guid, 0, path); 38 | } 39 | 40 | public int LogEntryHr(uint activityType, string source, string description, int result) 41 | { 42 | return this.LogEntryGuidHrPath(activityType, source, description, Guid.Empty, 0, string.Empty); 43 | } 44 | 45 | public int LogEntryHrPath(uint activityType, string source, string description, int result, string path) 46 | { 47 | return this.LogEntryGuidHrPath(activityType, source, description, Guid.Empty, result, path); 48 | } 49 | 50 | public int LogEntryPath(uint activityType, string source, string description, string path) 51 | { 52 | return this.LogEntryGuidHrPath(activityType, source, description, Guid.Empty, 0, path); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/Fakes/StubIPersistDocData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests.Fakes 6 | { 7 | using System; 8 | using Microsoft.VisualStudio; 9 | using Microsoft.VisualStudio.Shell.Interop; 10 | 11 | internal class StubIPersistDocData : IVsPersistDocData 12 | { 13 | internal Func ReloadDocData { get; set; } 14 | 15 | #region IVsPersistDocData 16 | 17 | int IVsPersistDocData.GetGuidEditorType(out Guid classId) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | 22 | int IVsPersistDocData.IsDocDataDirty(out int isDirty) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | 27 | int IVsPersistDocData.SetUntitledDocPath(string docDataPath) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | 32 | int IVsPersistDocData.LoadDocData(string fileName) 33 | { 34 | throw new NotImplementedException(); 35 | } 36 | 37 | int IVsPersistDocData.SaveDocData(VSSAVEFLAGS saveFlags, out string fileName, out int saveCanceled) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | 42 | int IVsPersistDocData.Close() 43 | { 44 | throw new NotImplementedException(); 45 | } 46 | 47 | int IVsPersistDocData.OnRegisterDocData(uint docCookie, IVsHierarchy hierarchy, uint itemId) 48 | { 49 | throw new NotImplementedException(); 50 | } 51 | 52 | int IVsPersistDocData.RenameDocData(uint attributes, IVsHierarchy hierarchy, uint itemId, string fileName) 53 | { 54 | throw new NotImplementedException(); 55 | } 56 | 57 | int IVsPersistDocData.IsDocDataReloadable(out int isReloadable) 58 | { 59 | throw new NotImplementedException(); 60 | } 61 | 62 | int IVsPersistDocData.ReloadDocData(uint flags) 63 | { 64 | if (this.ReloadDocData != null) 65 | { 66 | return this.ReloadDocData(flags); 67 | } 68 | 69 | return VSConstants.S_OK; 70 | } 71 | 72 | #endregion 73 | } 74 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/olegsych/T4Toolbox/22ea14adf093be3414f418c71cb5cba67dd1e55c/test/T4Toolbox.VisualStudio.Tests/GlobalSuppressions.cs -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/ItemMetadataWizardTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests 6 | { 7 | using System.Collections.Generic; 8 | using Microsoft.VisualStudio.TemplateWizard; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | using T4Toolbox.VisualStudio.Tests.Fakes; 12 | 13 | [TestClass] 14 | public class ItemMetadataWizardTest 15 | { 16 | [TestMethod] 17 | public void ProjectItemFinishedGeneratingSetsMetadata() 18 | { 19 | using (var dte = new FakeDte()) 20 | { 21 | var solution = new FakeSolution(dte); 22 | var project = new FakeProject(solution); 23 | var projectItem = new FakeProjectItem(project); 24 | 25 | var replacements = new Dictionary(); 26 | replacements["$wizarddata$"] = @" 27 | 28 | TextTemplatingFilePreprocessor 29 | "; 30 | 31 | var wizard = new ItemMetadataWizard(); 32 | wizard.RunStarted(null, replacements, default(WizardRunKind), null); 33 | wizard.ProjectItemFinishedGenerating(projectItem); 34 | 35 | // Wizard should clear the value 36 | Assert.AreEqual("TextTemplatingFilePreprocessor", projectItem.GetItemAttribute("Generator")); 37 | } 38 | } 39 | 40 | [TestMethod] 41 | public void ProjectItemFinishedGeneratingRemovesEmptyMetadata() 42 | { 43 | using (var dte = new FakeDte()) 44 | { 45 | var solution = new FakeSolution(dte); 46 | var project = new FakeProject(solution); 47 | var projectItem = new FakeProjectItem(project); 48 | projectItem.SetItemAttribute("Generator", "TextTemplatingFileGenerator"); 49 | 50 | var replacements = new Dictionary(); 51 | replacements["$wizarddata$"] = @" 52 | 53 | 54 | "; 55 | 56 | var wizard = new ItemMetadataWizard(); 57 | wizard.RunStarted(null, replacements, default(WizardRunKind), null); 58 | wizard.ProjectItemFinishedGenerating(projectItem); 59 | 60 | // Wizard should clear the value 61 | Assert.AreEqual(string.Empty, projectItem.GetItemAttribute("Generator")); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/T4ToolboxPackageTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests 6 | { 7 | using Microsoft.VisualStudio; 8 | using Microsoft.VisualStudio.Shell.Interop; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | using T4Toolbox.VisualStudio.Fakes; 11 | using T4Toolbox.VisualStudio.Tests.Fakes; 12 | 13 | [TestClass] 14 | public class T4ToolboxPackageTest 15 | { 16 | [TestMethod] 17 | public void SetSiteCompletesSuccessfully() 18 | { 19 | using (var serviceProvider = new FakeDte()) 20 | using (var package = new T4ToolboxPackage()) 21 | { 22 | serviceProvider.AddService(typeof(SVsActivityLog), new FakeVsActivityLog(), false); 23 | IVsPackage vspackage = package; 24 | Assert.AreEqual(VSConstants.S_OK, vspackage.SetSite(serviceProvider)); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/TransformationContextProviderTest.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright © Oleg Sych. All Rights Reserved. 3 | // 4 | 5 | namespace T4Toolbox.VisualStudio.Tests 6 | { 7 | using System; 8 | using System.ComponentModel.Design; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | 11 | [TestClass] 12 | public class TransformationContextProviderTest 13 | { 14 | [TestMethod] 15 | public void RegisterAddsServiceToContainer() 16 | { 17 | Assert.IsNotNull(CreateTransformationContextProvider()); 18 | } 19 | 20 | [TestMethod, ExpectedException(typeof(ArgumentNullException))] 21 | public void UpdateOutputFilesThrowsArgumentNullExceptionWhenInputFileIsNull() 22 | { 23 | ITransformationContextProvider target = CreateTransformationContextProvider(); 24 | target.UpdateOutputFiles(null, new OutputFile[0]); 25 | } 26 | 27 | [TestMethod, ExpectedException(typeof(ArgumentException))] 28 | public void UpdateOutputFilesThrowsArgumentExceptionWhenInputFileIsNotRooted() 29 | { 30 | ITransformationContextProvider target = CreateTransformationContextProvider(); 31 | target.UpdateOutputFiles("input.tt", new OutputFile[0]); 32 | } 33 | 34 | [TestMethod, ExpectedException(typeof(ArgumentNullException))] 35 | public void UpdateOutputFilesThrowsArgumentNullExceptionWhenOutputFilesIsNull() 36 | { 37 | ITransformationContextProvider target = CreateTransformationContextProvider(); 38 | target.UpdateOutputFiles(@"C:\input.tt", null); 39 | } 40 | 41 | [TestMethod, ExpectedException(typeof(ArgumentException))] 42 | public void UpdateOutputFilesThrowsArgumentExceptionWhenAnyOutputFileIsNull() 43 | { 44 | ITransformationContextProvider target = CreateTransformationContextProvider(); 45 | target.UpdateOutputFiles(@"C:\input.tt", new OutputFile[1]); 46 | } 47 | 48 | private static ITransformationContextProvider CreateTransformationContextProvider() 49 | { 50 | using (var container = new ServiceContainer()) 51 | { 52 | TransformationContextProvider.Register(container); 53 | return (ITransformationContextProvider)container.GetService(typeof(ITransformationContextProvider)); 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /test/T4Toolbox.VisualStudio.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | --------------------------------------------------------------------------------